selinux: introduce neveraudit types

Introduce neveraudit types i.e. types that should never trigger
audit messages. This allows the AVC to skip all audit-related
processing for such types. Note that neveraudit differs from
dontaudit not only wrt being applied for all checks with a given
source type but also in that it disables all auditing, not just
permission denials.

When a type is both a permissive type and a neveraudit type,
the security server can short-circuit the security_compute_av()
logic, allowing all permissions and not auditing any permissions.

This change just introduces the basic support but does not yet
further optimize the AVC or hook function logic when a type
is both a permissive type and a dontaudit type.

Suggested-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Stephen Smalley 2025-05-21 10:41:23 -04:00 committed by Paul Moore
parent 17bd3c0166
commit 1106896146
5 changed files with 48 additions and 1 deletions

View file

@ -65,6 +65,10 @@ static inline u32 avc_audit_required(u32 requested, struct av_decision *avd,
int result, u32 auditdeny, u32 *deniedp)
{
u32 denied, audited;
if (avd->flags & AVD_FLAGS_NEVERAUDIT)
return 0;
denied = requested & ~avd->allowed;
if (unlikely(denied)) {
audited = denied & avd->auditdeny;

View file

@ -47,10 +47,11 @@
#define POLICYDB_VERSION_GLBLUB 32
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
#define POLICYDB_VERSION_COND_XPERMS 34 /* extended permissions in conditional policies */
#define POLICYDB_VERSION_NEVERAUDIT 35 /* neveraudit types */
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NEVERAUDIT
/* Mask for just the mount related flags */
#define SE_MNTMASK 0x0f
@ -260,6 +261,7 @@ struct extended_perms {
/* definitions of av_decision.flags */
#define AVD_FLAGS_PERMISSIVE 0x0001
#define AVD_FLAGS_NEVERAUDIT 0x0002
void security_compute_av(u32 ssid, u32 tsid, u16 tclass,
struct av_decision *avd,

View file

@ -160,6 +160,11 @@ static const struct policydb_compat_info policydb_compat[] = {
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
{
.version = POLICYDB_VERSION_NEVERAUDIT,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
};
static const struct policydb_compat_info *
@ -531,6 +536,7 @@ static void policydb_init(struct policydb *p)
ebitmap_init(&p->filename_trans_ttypes);
ebitmap_init(&p->policycaps);
ebitmap_init(&p->permissive_map);
ebitmap_init(&p->neveraudit_map);
}
/*
@ -852,6 +858,7 @@ void policydb_destroy(struct policydb *p)
ebitmap_destroy(&p->filename_trans_ttypes);
ebitmap_destroy(&p->policycaps);
ebitmap_destroy(&p->permissive_map);
ebitmap_destroy(&p->neveraudit_map);
}
/*
@ -2538,6 +2545,12 @@ int policydb_read(struct policydb *p, struct policy_file *fp)
goto bad;
}
if (p->policyvers >= POLICYDB_VERSION_NEVERAUDIT) {
rc = ebitmap_read(&p->neveraudit_map, fp);
if (rc)
goto bad;
}
rc = -EINVAL;
info = policydb_lookup_compat(p->policyvers);
if (!info) {
@ -3723,6 +3736,12 @@ int policydb_write(struct policydb *p, struct policy_file *fp)
return rc;
}
if (p->policyvers >= POLICYDB_VERSION_NEVERAUDIT) {
rc = ebitmap_write(&p->neveraudit_map, fp);
if (rc)
return rc;
}
num_syms = info->sym_num;
for (i = 0; i < num_syms; i++) {
struct policy_data pd;

View file

@ -300,6 +300,8 @@ struct policydb {
struct ebitmap permissive_map;
struct ebitmap neveraudit_map;
/* length of this policy when it was loaded */
size_t len;

View file

@ -1153,6 +1153,14 @@ void security_compute_av(u32 ssid,
if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
avd->flags |= AVD_FLAGS_PERMISSIVE;
/* neveraudit domain? */
if (ebitmap_get_bit(&policydb->neveraudit_map, scontext->type))
avd->flags |= AVD_FLAGS_NEVERAUDIT;
/* both permissive and neveraudit => allow */
if (avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT))
goto allow;
tcontext = sidtab_search(sidtab, tsid);
if (!tcontext) {
pr_err("SELinux: %s: unrecognized SID %d\n",
@ -1172,6 +1180,8 @@ void security_compute_av(u32 ssid,
policydb->allow_unknown);
out:
rcu_read_unlock();
if (avd->flags & AVD_FLAGS_NEVERAUDIT)
avd->auditallow = avd->auditdeny = 0;
return;
allow:
avd->allowed = 0xffffffff;
@ -1208,6 +1218,14 @@ void security_compute_av_user(u32 ssid,
if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
avd->flags |= AVD_FLAGS_PERMISSIVE;
/* neveraudit domain? */
if (ebitmap_get_bit(&policydb->neveraudit_map, scontext->type))
avd->flags |= AVD_FLAGS_NEVERAUDIT;
/* both permissive and neveraudit => allow */
if (avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT))
goto allow;
tcontext = sidtab_search(sidtab, tsid);
if (!tcontext) {
pr_err("SELinux: %s: unrecognized SID %d\n",
@ -1225,6 +1243,8 @@ void security_compute_av_user(u32 ssid,
NULL);
out:
rcu_read_unlock();
if (avd->flags & AVD_FLAGS_NEVERAUDIT)
avd->auditallow = avd->auditdeny = 0;
return;
allow:
avd->allowed = 0xffffffff;