apparmor: convert fperm lookup to use accept as an index
authorJohn Johansen <john.johansen@canonical.com>
Fri, 13 Nov 2020 09:46:23 +0000 (01:46 -0800)
committerJohn Johansen <john.johansen@canonical.com>
Mon, 3 Oct 2022 21:49:03 +0000 (14:49 -0700)
Remap file dfa accept table from embedded perms to index and then move
fperm lookup to use the accept entry as an index into the fperm table.

This is a step toward unifying permission lookup.

Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/file.c
security/apparmor/policy_unpack.c

index d2be851..7bddec3 100644 (file)
@@ -188,13 +188,15 @@ struct aa_perms default_perms = {};
 struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules,
                                 unsigned int state, struct path_cond *cond)
 {
+       unsigned int index = ACCEPT_TABLE(file_rules->dfa)[state];
+
        if (!(file_rules->perms))
                return &default_perms;
 
        if (uid_eq(current_fsuid(), cond->uid))
-               return &(file_rules->perms[state * 2]);
+               return &(file_rules->perms[index]);
 
-       return &(file_rules->perms[state * 2 + 1]);
+       return &(file_rules->perms[index + 1]);
 }
 
 /**
index f2a0759..4cf62c1 100644 (file)
@@ -837,6 +837,29 @@ static struct aa_perms *compute_perms(struct aa_dfa *dfa)
 }
 
 /**
+ * remap_dfa_accept - remap old dfa accept table to be an index
+ * @dfa: dfa to do the remapping on
+ * @factor: scaling factor for the index conversion.
+ *
+ * Used in conjunction with compute_Xperms, it converts old style perms
+ * that are encoded in the dfa accept tables to the new style where
+ * there is a permission table and the accept table is an index into
+ * the permission table.
+ */
+static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor)
+{
+       unsigned int state;
+       unsigned int state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
+
+       AA_BUG(!dfa);
+
+       for (state = 0; state < state_count; state++)
+               ACCEPT_TABLE(dfa)[state] = state * factor;
+       kvfree(dfa->tables[YYTD_ID_ACCEPT2]);
+       dfa->tables[YYTD_ID_ACCEPT2] = NULL;
+}
+
+/**
  * unpack_profile - unpack a serialized profile
  * @e: serialized data extent information (NOT NULL)
  * @ns_name: pointer of newly allocated copy of %NULL in case of error
@@ -1051,6 +1074,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                                "dfa_start"))
                        /* default start state */
                        profile->file.start[AA_CLASS_FILE] = DFA_START;
+               profile->file.perms = compute_fperms(profile->file.dfa);
+               if (!profile->file.perms) {
+                       info = "failed to remap file permission table";
+                       goto fail;
+               }
+               remap_dfa_accept(profile->file.dfa, 2);
+               if (!unpack_trans_table(e, profile)) {
+                       info = "failed to unpack profile transition table";
+                       goto fail;
+               }
        } else if (profile->policy.dfa &&
                   profile->policy.start[AA_CLASS_FILE]) {
                profile->file.dfa = aa_get_dfa(profile->policy.dfa);
@@ -1058,16 +1091,6 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        } else
                profile->file.dfa = aa_get_dfa(nulldfa);
 
-       profile->file.perms = compute_fperms(profile->file.dfa);
-       if (!profile->file.perms) {
-               info = "failed to remap file permission table";
-               goto fail;
-       }
-       if (!unpack_trans_table(e, profile)) {
-               info = "failed to unpack profile transition table";
-               goto fail;
-       }
-
        if (unpack_nameX(e, AA_STRUCT, "data")) {
                info = "out of memory";
                profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL);
@@ -1198,9 +1221,7 @@ static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
 {
        int i;
        for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
-               if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
-                       return false;
-               if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
+               if (!verify_xindex(ACCEPT_TABLE(dfa)[i], table_size))
                        return false;
        }
        return true;
@@ -1211,14 +1232,16 @@ static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
  * @profile: profile to verify (NOT NULL)
  *
  * Returns: 0 if passes verification else error
+ *
+ * This verification is post any unpack mapping or changes
  */
 static int verify_profile(struct aa_profile *profile)
 {
        if (profile->file.dfa &&
-           !verify_dfa_xindex(profile->file.dfa,
-                              profile->file.trans.size)) {
-               audit_iface(profile, NULL, NULL, "Invalid named transition",
-                           NULL, -EPROTO);
+            !verify_dfa_xindex(profile->file.dfa,
+                               profile->file.trans.size)) {
+               audit_iface(profile, NULL, NULL,
+                           "Unpack: Invalid named transition", NULL, -EPROTO);
                return -EPROTO;
        }