]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selinux: introduce neveraudit types
authorStephen Smalley <stephen.smalley.work@gmail.com>
Wed, 21 May 2025 14:41:23 +0000 (10:41 -0400)
committerPaul Moore <paul@paul-moore.com>
Thu, 19 Jun 2025 21:23:04 +0000 (17:23 -0400)
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>
security/selinux/include/avc.h
security/selinux/include/security.h
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c

index 281f4010366336c32731f42b3501ea13ca05b1d8..01b5167fee1a89681e7d35163e1904edf2a0e59f 100644 (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;
index 278c144c22d6094bfd7fbf54b3878679b55a1465..8201e6a3ac0fc80c8e8809b32e93eff7b96800a5 100644 (file)
 #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,
index 9ea97194371363a5a4f6aa0e2dd035b28821c222..91df3db6a88cddf796b8d3d1954ea606ebfd1b2e 100644 (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;
index 25650224b6e7c8007832737965af4bec76276c7c..89a180b1742fb8a2469971dc558433e834373ad6 100644 (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;
 
index 7becf3808818a612434cdc5c2214ff92896a4579..9b3b64ea6790ea951fed72eb710316ac93af525b 100644 (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;