Skip to content

Commit 690ffcd

Browse files
committed
Merge tag 'selinux-pr-20250121' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore: - Extended permissions supported in conditional policy The SELinux extended permissions, aka "xperms", allow security admins to target individuals ioctls, and recently netlink messages, with their SELinux policy. Adding support for conditional policies allows admins to toggle the granular xperms using SELinux booleans, helping pave the way for greater use of xperms in general purpose SELinux policies. This change bumps the maximum SELinux policy version to 34. - Fix a SCTP/SELinux error return code inconsistency Depending on the loaded SELinux policy, specifically it's EXTSOCKCLASS support, the bind(2) LSM/SELinux hook could return different error codes due to the SELinux code checking the socket's SELinux object class (which can vary depending on EXTSOCKCLASS) and not the socket's sk_protocol field. We fix this by doing the obvious, and looking at the sock->sk_protocol field instead of the object class. - Makefile fixes to properly cleanup av_permissions.h Add av_permissions.h to "targets" so that it is properly cleaned up using the kbuild infrastructure. - A number of smaller improvements by Christian Göttsche A variety of straightforward changes to reduce code duplication, reduce pointer lookups, migrate void pointers to defined types, simplify code, constify function parameters, and correct iterator types. * tag 'selinux-pr-20250121' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: make more use of str_read() when loading the policy selinux: avoid unnecessary indirection in struct level_datum selinux: use known type instead of void pointer selinux: rename comparison functions for clarity selinux: rework match_ipv6_addrmask() selinux: constify and reconcile function parameter names selinux: avoid using types indicating user space interaction selinux: supply missing field initializers selinux: add netlink nlmsg_type audit message selinux: add support for xperms in conditional policies selinux: Fix SCTP error inconsistency in selinux_socket_bind() selinux: use native iterator types selinux: add generated av_permissions.h to targets
2 parents f96a974 + 01c2253 commit 690ffcd

22 files changed

+170
-165
lines changed

include/linux/lsm_audit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct common_audit_data {
7777
#define LSM_AUDIT_DATA_LOCKDOWN 15
7878
#define LSM_AUDIT_DATA_NOTIFICATION 16
7979
#define LSM_AUDIT_DATA_ANONINODE 17
80+
#define LSM_AUDIT_DATA_NLMSGTYPE 18
8081
union {
8182
struct path path;
8283
struct dentry *dentry;
@@ -98,6 +99,7 @@ struct common_audit_data {
9899
struct lsm_ibendport_audit *ibendport;
99100
int reason;
100101
const char *anonclass;
102+
u16 nlmsg_type;
101103
} u;
102104
/* this union contains LSM specific data */
103105
union {

security/lsm_audit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,9 @@ static void dump_common_audit_data(struct audit_buffer *ab,
425425
case LSM_AUDIT_DATA_ANONINODE:
426426
audit_log_format(ab, " anonclass=%s", a->u.anonclass);
427427
break;
428+
case LSM_AUDIT_DATA_NLMSGTYPE:
429+
audit_log_format(ab, " nl-msgtype=%hu", a->u.nlmsg_type);
430+
break;
428431
} /* switch (a->type) */
429432
}
430433

security/selinux/Makefile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
3333
quiet_cmd_genhdrs = GEN $(addprefix $(obj)/,$(genhdrs))
3434
cmd_genhdrs = $< $(addprefix $(obj)/,$(genhdrs))
3535

36-
# see the note above, replace the $targets and 'flask.h' rule with the lines
37-
# below:
38-
# targets += $(genhdrs)
36+
targets += $(genhdrs)
37+
38+
# see the note above, replace the 'flask.h' rule with the line below:
3939
# $(addprefix $(obj)/,$(genhdrs)) &: $(obj)/genheaders FORCE
40-
targets += flask.h
4140
$(obj)/flask.h: $(obj)/genheaders FORCE
4241
$(call if_changed,genhdrs)
4342

security/selinux/hooks.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ static const struct {
407407

408408
static int match_opt_prefix(char *s, int l, char **arg)
409409
{
410-
int i;
410+
unsigned int i;
411411

412412
for (i = 0; i < ARRAY_SIZE(tokens); i++) {
413413
size_t len = tokens[i].len;
@@ -3135,7 +3135,7 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
31353135
const struct cred *cred = current_cred();
31363136
struct inode *inode = d_backing_inode(dentry);
31373137
unsigned int ia_valid = iattr->ia_valid;
3138-
__u32 av = FILE__WRITE;
3138+
u32 av = FILE__WRITE;
31393139

31403140
/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
31413141
if (ia_valid & ATTR_FORCE) {
@@ -4835,7 +4835,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
48354835
return err;
48364836
err_af:
48374837
/* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4838-
if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4838+
if (sk->sk_protocol == IPPROTO_SCTP)
48394839
return -EINVAL;
48404840
return -EAFNOSUPPORT;
48414841
}
@@ -5939,14 +5939,14 @@ static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_t
59395939
{
59405940
struct sk_security_struct *sksec = sk->sk_security;
59415941
struct common_audit_data ad;
5942-
struct lsm_network_audit net;
59435942
u8 driver;
59445943
u8 xperm;
59455944

59465945
if (sock_skip_has_perm(sksec->sid))
59475946
return 0;
59485947

5949-
ad_net_init_from_sk(&ad, &net, sk);
5948+
ad.type = LSM_AUDIT_DATA_NLMSGTYPE;
5949+
ad.u.nlmsg_type = nlmsg_type;
59505950

59515951
driver = nlmsg_type >> 8;
59525952
xperm = nlmsg_type & 0xff;

security/selinux/include/classmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ const struct security_class_mapping secclass_map[] = {
179179
{ "anon_inode", { COMMON_FILE_PERMS, NULL } },
180180
{ "io_uring", { "override_creds", "sqpoll", "cmd", NULL } },
181181
{ "user_namespace", { "create", NULL } },
182-
{ NULL }
182+
/* last one */ { NULL, {} }
183183
};
184184

185185
#ifdef __KERNEL__ /* avoid this check when building host programs */

security/selinux/include/conditional.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
int security_get_bools(struct selinux_policy *policy, u32 *len, char ***names,
1717
int **values);
1818

19-
int security_set_bools(u32 len, int *values);
19+
int security_set_bools(u32 len, const int *values);
2020

2121
int security_get_bool_value(u32 index);
2222

security/selinux/include/security.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@
4646
#define POLICYDB_VERSION_INFINIBAND 31
4747
#define POLICYDB_VERSION_GLBLUB 32
4848
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
49+
#define POLICYDB_VERSION_COND_XPERMS 34 /* extended permissions in conditional policies */
4950

5051
/* Range of policy versions we understand*/
5152
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
52-
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS
53+
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS
5354

5455
/* Mask for just the mount related flags */
5556
#define SE_MNTMASK 0x0f
@@ -292,7 +293,7 @@ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
292293
int security_context_to_sid_force(const char *scontext, u32 scontext_len,
293294
u32 *sid);
294295

295-
int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel);
296+
int security_get_user_sids(u32 fromsid, const char *username, u32 **sids, u32 *nel);
296297

297298
int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
298299

@@ -310,7 +311,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
310311
int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
311312
u16 tclass);
312313

313-
int security_bounded_transition(u32 oldsid, u32 newsid);
314+
int security_bounded_transition(u32 old_sid, u32 new_sid);
314315

315316
int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
316317

security/selinux/selinuxfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,7 @@ static const struct file_operations sel_avc_hash_stats_ops = {
15151515
#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
15161516
static struct avc_cache_stats *sel_avc_get_stat_idx(loff_t *idx)
15171517
{
1518-
int cpu;
1518+
loff_t cpu;
15191519

15201520
for (cpu = *idx; cpu < nr_cpu_ids; ++cpu) {
15211521
if (!cpu_possible(cpu))
@@ -2001,7 +2001,7 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
20012001
[SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO},
20022002
[SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops,
20032003
S_IWUGO},
2004-
/* last one */ {""}
2004+
/* last one */ {"", NULL, 0}
20052005
};
20062006

20072007
ret = selinux_fs_info_create(sb);

security/selinux/ss/avtab.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,10 @@ static const uint16_t spec_order[] = {
336336
};
337337
/* clang-format on */
338338

339-
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
339+
int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *pol,
340340
int (*insertf)(struct avtab *a, const struct avtab_key *k,
341341
const struct avtab_datum *d, void *p),
342-
void *p)
342+
void *p, bool conditional)
343343
{
344344
__le16 buf16[4];
345345
u16 enabled;
@@ -457,6 +457,13 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
457457
"was specified\n",
458458
vers);
459459
return -EINVAL;
460+
} else if ((vers < POLICYDB_VERSION_COND_XPERMS) &&
461+
(key.specified & AVTAB_XPERMS) && conditional) {
462+
pr_err("SELinux: avtab: policy version %u does not "
463+
"support extended permissions rules in conditional "
464+
"policies and one was specified\n",
465+
vers);
466+
return -EINVAL;
460467
} else if (key.specified & AVTAB_XPERMS) {
461468
memset(&xperms, 0, sizeof(struct avtab_extended_perms));
462469
rc = next_entry(&xperms.specified, fp, sizeof(u8));
@@ -500,7 +507,7 @@ static int avtab_insertf(struct avtab *a, const struct avtab_key *k,
500507
return avtab_insert(a, k, d);
501508
}
502509

503-
int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
510+
int avtab_read(struct avtab *a, struct policy_file *fp, struct policydb *pol)
504511
{
505512
int rc;
506513
__le32 buf[1];
@@ -523,7 +530,7 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
523530
goto bad;
524531

525532
for (i = 0; i < nel; i++) {
526-
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
533+
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL, false);
527534
if (rc) {
528535
if (rc == -ENOMEM)
529536
pr_err("SELinux: avtab: out of memory\n");
@@ -543,7 +550,7 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
543550
goto out;
544551
}
545552

546-
int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp)
553+
int avtab_write_item(struct policydb *p, const struct avtab_node *cur, struct policy_file *fp)
547554
{
548555
__le16 buf16[4];
549556
__le32 buf32[ARRAY_SIZE(cur->datum.u.xperms->perms.p)];
@@ -579,7 +586,7 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp)
579586
return 0;
580587
}
581588

582-
int avtab_write(struct policydb *p, struct avtab *a, void *fp)
589+
int avtab_write(struct policydb *p, struct avtab *a, struct policy_file *fp)
583590
{
584591
u32 i;
585592
int rc = 0;

security/selinux/ss/avtab.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct avtab {
8989
};
9090

9191
void avtab_init(struct avtab *h);
92-
int avtab_alloc(struct avtab *, u32);
92+
int avtab_alloc(struct avtab *h, u32 nrules);
9393
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig);
9494
void avtab_destroy(struct avtab *h);
9595

@@ -105,15 +105,16 @@ static inline void avtab_hash_eval(struct avtab *h, const char *tag)
105105
#endif
106106

107107
struct policydb;
108-
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
108+
struct policy_file;
109+
int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *pol,
109110
int (*insert)(struct avtab *a, const struct avtab_key *k,
110111
const struct avtab_datum *d, void *p),
111-
void *p);
112+
void *p, bool conditional);
112113

113-
int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
114+
int avtab_read(struct avtab *a, struct policy_file *fp, struct policydb *pol);
114115
int avtab_write_item(struct policydb *p, const struct avtab_node *cur,
115-
void *fp);
116-
int avtab_write(struct policydb *p, struct avtab *a, void *fp);
116+
struct policy_file *fp);
117+
int avtab_write(struct policydb *p, struct avtab *a, struct policy_file *fp);
117118

118119
struct avtab_node *avtab_insert_nonunique(struct avtab *h,
119120
const struct avtab_key *key,

security/selinux/ss/conditional.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ static int bool_isvalid(struct cond_bool_datum *b)
206206
return 1;
207207
}
208208

209-
int cond_read_bool(struct policydb *p, struct symtab *s, void *fp)
209+
int cond_read_bool(struct policydb *p, struct symtab *s, struct policy_file *fp)
210210
{
211211
char *key = NULL;
212212
struct cond_bool_datum *booldatum;
@@ -230,17 +230,11 @@ int cond_read_bool(struct policydb *p, struct symtab *s, void *fp)
230230
goto err;
231231

232232
len = le32_to_cpu(buf[2]);
233-
if (((len == 0) || (len == (u32)-1)))
234-
goto err;
235233

236-
rc = -ENOMEM;
237-
key = kmalloc(len + 1, GFP_KERNEL);
238-
if (!key)
239-
goto err;
240-
rc = next_entry(key, fp, len);
234+
rc = str_read(&key, GFP_KERNEL, fp, len);
241235
if (rc)
242236
goto err;
243-
key[len] = '\0';
237+
244238
rc = symtab_insert(s, key, booldatum);
245239
if (rc)
246240
goto err;
@@ -323,7 +317,7 @@ static int cond_insertf(struct avtab *a, const struct avtab_key *k,
323317
return 0;
324318
}
325319

326-
static int cond_read_av_list(struct policydb *p, void *fp,
320+
static int cond_read_av_list(struct policydb *p, struct policy_file *fp,
327321
struct cond_av_list *list,
328322
struct cond_av_list *other)
329323
{
@@ -349,7 +343,7 @@ static int cond_read_av_list(struct policydb *p, void *fp,
349343
for (i = 0; i < len; i++) {
350344
data.dst = &list->nodes[i];
351345
rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
352-
&data);
346+
&data, true);
353347
if (rc) {
354348
kfree(list->nodes);
355349
list->nodes = NULL;
@@ -375,7 +369,7 @@ static int expr_node_isvalid(struct policydb *p, struct cond_expr_node *expr)
375369
return 1;
376370
}
377371

378-
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
372+
static int cond_read_node(struct policydb *p, struct cond_node *node, struct policy_file *fp)
379373
{
380374
__le32 buf[2];
381375
u32 i, len;
@@ -415,7 +409,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
415409
return cond_read_av_list(p, fp, &node->false_list, &node->true_list);
416410
}
417411

418-
int cond_read_list(struct policydb *p, void *fp)
412+
int cond_read_list(struct policydb *p, struct policy_file *fp)
419413
{
420414
__le32 buf[1];
421415
u32 i, len;
@@ -453,7 +447,7 @@ int cond_write_bool(void *vkey, void *datum, void *ptr)
453447
char *key = vkey;
454448
struct cond_bool_datum *booldatum = datum;
455449
struct policy_data *pd = ptr;
456-
void *fp = pd->fp;
450+
struct policy_file *fp = pd->fp;
457451
__le32 buf[3];
458452
u32 len;
459453
int rc;
@@ -536,7 +530,7 @@ static int cond_write_node(struct policydb *p, struct cond_node *node,
536530
return 0;
537531
}
538532

539-
int cond_write_list(struct policydb *p, void *fp)
533+
int cond_write_list(struct policydb *p, struct policy_file *fp)
540534
{
541535
u32 i;
542536
__le32 buf[1];

security/selinux/ss/conditional.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ int cond_destroy_bool(void *key, void *datum, void *p);
6868

6969
int cond_index_bool(void *key, void *datum, void *datap);
7070

71-
int cond_read_bool(struct policydb *p, struct symtab *s, void *fp);
72-
int cond_read_list(struct policydb *p, void *fp);
71+
int cond_read_bool(struct policydb *p, struct symtab *s, struct policy_file *fp);
72+
int cond_read_list(struct policydb *p, struct policy_file *fp);
7373
int cond_write_bool(void *key, void *datum, void *ptr);
74-
int cond_write_list(struct policydb *p, void *fp);
74+
int cond_write_list(struct policydb *p, struct policy_file *fp);
7575

7676
void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
7777
struct av_decision *avd, struct extended_perms *xperms);

security/selinux/ss/context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ u32 context_compute_hash(const struct context *c)
2020
* context struct with only the len & str set (and vice versa)
2121
* under a given policy. Since context structs from different
2222
* policies should never meet, it is safe to hash valid and
23-
* invalid contexts differently. The context_cmp() function
23+
* invalid contexts differently. The context_equal() function
2424
* already operates under the same assumption.
2525
*/
2626
if (c->len)

security/selinux/ss/context.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,13 @@ static inline int mls_context_glblub(struct context *dst,
132132
return rc;
133133
}
134134

135-
static inline int mls_context_cmp(const struct context *c1,
136-
const struct context *c2)
135+
static inline bool mls_context_equal(const struct context *c1,
136+
const struct context *c2)
137137
{
138138
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
139-
ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
139+
ebitmap_equal(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
140140
(c1->range.level[1].sens == c2->range.level[1].sens) &&
141-
ebitmap_cmp(&c1->range.level[1].cat, &c2->range.level[1].cat));
141+
ebitmap_equal(&c1->range.level[1].cat, &c2->range.level[1].cat));
142142
}
143143

144144
static inline void mls_context_destroy(struct context *c)
@@ -188,15 +188,15 @@ static inline void context_destroy(struct context *c)
188188
mls_context_destroy(c);
189189
}
190190

191-
static inline int context_cmp(const struct context *c1,
192-
const struct context *c2)
191+
static inline bool context_equal(const struct context *c1,
192+
const struct context *c2)
193193
{
194194
if (c1->len && c2->len)
195195
return (c1->len == c2->len && !strcmp(c1->str, c2->str));
196196
if (c1->len || c2->len)
197197
return 0;
198198
return ((c1->user == c2->user) && (c1->role == c2->role) &&
199-
(c1->type == c2->type) && mls_context_cmp(c1, c2));
199+
(c1->type == c2->type) && mls_context_equal(c1, c2));
200200
}
201201

202202
u32 context_compute_hash(const struct context *c);

0 commit comments

Comments
 (0)