Skip to content

Commit dffb641

Browse files
committed
Merge tag 'selinux-pr-20250725' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore: - Introduce the concept of a SELinux "neveraudit" type which prevents all auditing of the given type/domain. Taken by itself, the benefit of marking a SELinux domain with the "neveraudit" tag is likely not very interesting, especially given the significant overlap with the "dontaudit" tag. However, given that the "neveraudit" tag applies to *all* auditing of the tagged domain, we can do some fairly interesting optimizations when a SELinux domain is marked as both "permissive" and "dontaudit" (think of the unconfined_t domain). While this pull request includes optimized inode permission and getattr hooks, these optimizations require SELinux policy changes, therefore the improvements may not be visible on standard downstream Linux distos for a period of time. - Continue the deprecation process of /sys/fs/selinux/user. After removing the associated userspace code in 2020, we marked the /sys/fs/selinux/user interface as deprecated in Linux v6.13 with pr_warn() and the usual documention update. This adds a five second sleep after the pr_warn(), following a previous deprecation process pattern that has worked well for us in the past in helping identify any existing users that we haven't yet reached. - Add a __GFP_NOWARN flag to our initial hash table allocation. Fuzzers such a syzbot often attempt abnormally large SELinux policy loads, which the SELinux code gracefully handles by checking for allocation failures, but not before the allocator emits a warning which causes the automated fuzzing to flag this as an error and report it to the list. While we want to continue to support the work done by the fuzzing teams, we want to focus on proper issues and not an error case that is already handled safely. Add a NOWARN flag to quiet the allocator and prevent syzbot from tripping on this again. - Remove some unnecessary selinuxfs cleanup code, courtesy of Al. - Update the SELinux in-kernel documentation with pointers to additional information. * tag 'selinux-pr-20250725' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: don't bother with selinuxfs_info_free() on failures selinux: add __GFP_NOWARN to hashtab_init() allocations selinux: optimize selinux_inode_getattr/permission() based on neveraudit|permissive selinux: introduce neveraudit types documentation: add links to SELinux resources selinux: add a 5 second sleep to /sys/fs/selinux/user
2 parents 30b9dca + ee79ba3 commit dffb641

10 files changed

Lines changed: 83 additions & 5 deletions

File tree

Documentation/admin-guide/LSM/SELinux.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
SELinux
33
=======
44

5+
Information about the SELinux kernel subsystem can be found at the
6+
following links:
7+
8+
https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git/tree/README.md
9+
10+
https://github.com/selinuxproject/selinux-kernel/wiki
11+
12+
Information about the SELinux userspace can be found at:
13+
14+
https://github.com/SELinuxProject/selinux/wiki
15+
516
If you want to use SELinux, chances are you will want
617
to use the distro-provided policies, or install the
718
latest reference policy release from

security/selinux/hooks.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,8 @@ static inline void task_avdcache_update(struct task_security_struct *tsec,
31813181
tsec->avdcache.dir[spot].audited = audited;
31823182
tsec->avdcache.dir[spot].allowed = avd->allowed;
31833183
tsec->avdcache.dir[spot].permissive = avd->flags & AVD_FLAGS_PERMISSIVE;
3184+
tsec->avdcache.permissive_neveraudit =
3185+
(avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT));
31843186
}
31853187

31863188
/**
@@ -3207,10 +3209,13 @@ static int selinux_inode_permission(struct inode *inode, int requested)
32073209
if (!mask)
32083210
return 0;
32093211

3212+
tsec = selinux_cred(current_cred());
3213+
if (task_avdcache_permnoaudit(tsec))
3214+
return 0;
3215+
32103216
isec = inode_security_rcu(inode, requested & MAY_NOT_BLOCK);
32113217
if (IS_ERR(isec))
32123218
return PTR_ERR(isec);
3213-
tsec = selinux_cred(current_cred());
32143219
perms = file_mask_to_av(inode->i_mode, mask);
32153220

32163221
rc = task_avdcache_search(tsec, isec, &avdc);
@@ -3274,6 +3279,13 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
32743279

32753280
static int selinux_inode_getattr(const struct path *path)
32763281
{
3282+
struct task_security_struct *tsec;
3283+
3284+
tsec = selinux_cred(current_cred());
3285+
3286+
if (task_avdcache_permnoaudit(tsec))
3287+
return 0;
3288+
32773289
return path_has_perm(current_cred(), path, FILE__GETATTR);
32783290
}
32793291

security/selinux/include/avc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ static inline u32 avc_audit_required(u32 requested, struct av_decision *avd,
6565
int result, u32 auditdeny, u32 *deniedp)
6666
{
6767
u32 denied, audited;
68+
69+
if (avd->flags & AVD_FLAGS_NEVERAUDIT)
70+
return 0;
71+
6872
denied = requested & ~avd->allowed;
6973
if (unlikely(denied)) {
7074
audited = denied & avd->auditdeny;

security/selinux/include/objsec.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,17 @@ struct task_security_struct {
4949
u32 seqno; /* AVC sequence number */
5050
unsigned int dir_spot; /* dir cache index to check first */
5151
struct avdc_entry dir[TSEC_AVDC_DIR_SIZE]; /* dir entries */
52+
bool permissive_neveraudit; /* permissive and neveraudit */
5253
} avdcache;
5354
} __randomize_layout;
5455

56+
static inline bool task_avdcache_permnoaudit(struct task_security_struct *tsec)
57+
{
58+
return (tsec->avdcache.permissive_neveraudit &&
59+
tsec->sid == tsec->avdcache.sid &&
60+
tsec->avdcache.seqno == avc_policy_seqno());
61+
}
62+
5563
enum label_initialized {
5664
LABEL_INVALID, /* invalid or not initialized */
5765
LABEL_INITIALIZED, /* initialized */

security/selinux/include/security.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@
4747
#define POLICYDB_VERSION_GLBLUB 32
4848
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
4949
#define POLICYDB_VERSION_COND_XPERMS 34 /* extended permissions in conditional policies */
50+
#define POLICYDB_VERSION_NEVERAUDIT 35 /* neveraudit types */
5051

5152
/* Range of policy versions we understand*/
5253
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
53-
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS
54+
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NEVERAUDIT
5455

5556
/* Mask for just the mount related flags */
5657
#define SE_MNTMASK 0x0f
@@ -260,6 +261,7 @@ struct extended_perms {
260261

261262
/* definitions of av_decision.flags */
262263
#define AVD_FLAGS_PERMISSIVE 0x0001
264+
#define AVD_FLAGS_NEVERAUDIT 0x0002
263265

264266
void security_compute_av(u32 ssid, u32 tsid, u16 tclass,
265267
struct av_decision *avd,

security/selinux/selinuxfs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
10721072
pr_warn_ratelimited("SELinux: %s (%d) wrote to /sys/fs/selinux/user!"
10731073
" This will not be supported in the future; please update your"
10741074
" userspace.\n", current->comm, current->pid);
1075+
ssleep(5);
10751076

10761077
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
10771078
SECCLASS_SECURITY, SECURITY__COMPUTE_USER,
@@ -2097,8 +2098,6 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
20972098
pr_err("SELinux: %s: failed while creating inodes\n",
20982099
__func__);
20992100

2100-
selinux_fs_info_free(sb);
2101-
21022101
return ret;
21032102
}
21042103

security/selinux/ss/hashtab.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ int hashtab_init(struct hashtab *h, u32 nel_hint)
4040
h->htable = NULL;
4141

4242
if (size) {
43-
h->htable = kcalloc(size, sizeof(*h->htable), GFP_KERNEL);
43+
h->htable = kcalloc(size, sizeof(*h->htable),
44+
GFP_KERNEL | __GFP_NOWARN);
4445
if (!h->htable)
4546
return -ENOMEM;
4647
h->size = size;

security/selinux/ss/policydb.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ static const struct policydb_compat_info policydb_compat[] = {
160160
.sym_num = SYM_NUM,
161161
.ocon_num = OCON_NUM,
162162
},
163+
{
164+
.version = POLICYDB_VERSION_NEVERAUDIT,
165+
.sym_num = SYM_NUM,
166+
.ocon_num = OCON_NUM,
167+
},
163168
};
164169

165170
static const struct policydb_compat_info *
@@ -531,6 +536,7 @@ static void policydb_init(struct policydb *p)
531536
ebitmap_init(&p->filename_trans_ttypes);
532537
ebitmap_init(&p->policycaps);
533538
ebitmap_init(&p->permissive_map);
539+
ebitmap_init(&p->neveraudit_map);
534540
}
535541

536542
/*
@@ -852,6 +858,7 @@ void policydb_destroy(struct policydb *p)
852858
ebitmap_destroy(&p->filename_trans_ttypes);
853859
ebitmap_destroy(&p->policycaps);
854860
ebitmap_destroy(&p->permissive_map);
861+
ebitmap_destroy(&p->neveraudit_map);
855862
}
856863

857864
/*
@@ -2538,6 +2545,12 @@ int policydb_read(struct policydb *p, struct policy_file *fp)
25382545
goto bad;
25392546
}
25402547

2548+
if (p->policyvers >= POLICYDB_VERSION_NEVERAUDIT) {
2549+
rc = ebitmap_read(&p->neveraudit_map, fp);
2550+
if (rc)
2551+
goto bad;
2552+
}
2553+
25412554
rc = -EINVAL;
25422555
info = policydb_lookup_compat(p->policyvers);
25432556
if (!info) {
@@ -3723,6 +3736,12 @@ int policydb_write(struct policydb *p, struct policy_file *fp)
37233736
return rc;
37243737
}
37253738

3739+
if (p->policyvers >= POLICYDB_VERSION_NEVERAUDIT) {
3740+
rc = ebitmap_write(&p->neveraudit_map, fp);
3741+
if (rc)
3742+
return rc;
3743+
}
3744+
37263745
num_syms = info->sym_num;
37273746
for (i = 0; i < num_syms; i++) {
37283747
struct policy_data pd;

security/selinux/ss/policydb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ struct policydb {
300300

301301
struct ebitmap permissive_map;
302302

303+
struct ebitmap neveraudit_map;
304+
303305
/* length of this policy when it was loaded */
304306
size_t len;
305307

security/selinux/ss/services.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,14 @@ void security_compute_av(u32 ssid,
11531153
if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
11541154
avd->flags |= AVD_FLAGS_PERMISSIVE;
11551155

1156+
/* neveraudit domain? */
1157+
if (ebitmap_get_bit(&policydb->neveraudit_map, scontext->type))
1158+
avd->flags |= AVD_FLAGS_NEVERAUDIT;
1159+
1160+
/* both permissive and neveraudit => allow */
1161+
if (avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT))
1162+
goto allow;
1163+
11561164
tcontext = sidtab_search(sidtab, tsid);
11571165
if (!tcontext) {
11581166
pr_err("SELinux: %s: unrecognized SID %d\n",
@@ -1172,6 +1180,8 @@ void security_compute_av(u32 ssid,
11721180
policydb->allow_unknown);
11731181
out:
11741182
rcu_read_unlock();
1183+
if (avd->flags & AVD_FLAGS_NEVERAUDIT)
1184+
avd->auditallow = avd->auditdeny = 0;
11751185
return;
11761186
allow:
11771187
avd->allowed = 0xffffffff;
@@ -1208,6 +1218,14 @@ void security_compute_av_user(u32 ssid,
12081218
if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
12091219
avd->flags |= AVD_FLAGS_PERMISSIVE;
12101220

1221+
/* neveraudit domain? */
1222+
if (ebitmap_get_bit(&policydb->neveraudit_map, scontext->type))
1223+
avd->flags |= AVD_FLAGS_NEVERAUDIT;
1224+
1225+
/* both permissive and neveraudit => allow */
1226+
if (avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT))
1227+
goto allow;
1228+
12111229
tcontext = sidtab_search(sidtab, tsid);
12121230
if (!tcontext) {
12131231
pr_err("SELinux: %s: unrecognized SID %d\n",
@@ -1225,6 +1243,8 @@ void security_compute_av_user(u32 ssid,
12251243
NULL);
12261244
out:
12271245
rcu_read_unlock();
1246+
if (avd->flags & AVD_FLAGS_NEVERAUDIT)
1247+
avd->auditallow = avd->auditdeny = 0;
12281248
return;
12291249
allow:
12301250
avd->allowed = 0xffffffff;

0 commit comments

Comments
 (0)