diff mbox series

[3/4] checkpolicy: only set declared permission bits for wildcards

Message ID 20230512092311.42583-3-cgzones@googlemail.com (mailing list archive)
State Accepted
Commit 00728e12d4a7
Delegated to: Petr Lautrbach
Headers show
Series [1/4] checkpolicy: drop unused token CLONE | expand

Commit Message

Christian Göttsche May 12, 2023, 9:23 a.m. UTC
When setting permission bits from a wildcard or complement only set the
bits for permissions actually declared for the associated class.  This
helps optimizing the policy later, since only rules are dropped with a
complete empty permission bitset.  Example policy:

    class CLASS1
    sid kernel
    class CLASS1 { PERM1 }
    type TYPE1;
    bool BOOL1 true;
    allow TYPE1 self : CLASS1 { PERM1 };
    role ROLE1;
    role ROLE1 types { TYPE1 };
    if ! BOOL1 { allow TYPE1 self: CLASS1 *; }
    user USER1 roles ROLE1;
    sid kernel USER1:ROLE1:TYPE1

Also emit a warning if a rule will have an empty permission bitset due
to an exhausting complement.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 checkpolicy/policy_define.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 95cd5c85..cef8f3c4 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -2511,6 +2511,8 @@  int define_te_avtab_extended_perms(int which)
 	return rc;
 }
 
+#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1))
+
 static int define_te_avtab_helper(int which, avrule_t ** rule)
 {
 	char *id;
@@ -2616,8 +2618,8 @@  static int define_te_avtab_helper(int which, avrule_t ** rule)
 			cladatum = policydbp->class_val_to_struct[i];
 
 			if (strcmp(id, "*") == 0) {
-				/* set all permissions in the class */
-				cur_perms->data = ~0U;
+				/* set all declared permissions in the class */
+				cur_perms->data = PERMISSION_MASK(cladatum->permissions.nprim);
 				goto next;
 			}
 
@@ -2625,7 +2627,16 @@  static int define_te_avtab_helper(int which, avrule_t ** rule)
 				/* complement the set */
 				if (which == AVRULE_DONTAUDIT)
 					yywarn("dontaudit rule with a ~?");
-				cur_perms->data = ~cur_perms->data;
+				cur_perms->data = ~cur_perms->data & PERMISSION_MASK(cladatum->permissions.nprim);
+				if (cur_perms->data == 0) {
+					class_perm_node_t *tmp = cur_perms;
+					yywarn("omitting avrule with no permission set");
+					if (perms == cur_perms)
+						perms = cur_perms->next;
+					cur_perms = cur_perms->next;
+					free(tmp);
+					continue;
+				}
 				goto next;
 			}
 
@@ -3549,8 +3560,6 @@  static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr)
 	return NULL;
 }
 
-#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1))
-
 int define_constraint(constraint_expr_t * expr)
 {
 	struct constraint_node *node;