summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/apparmor/Makefile3
-rw-r--r--security/apparmor/include/policy_compat.h33
-rw-r--r--security/apparmor/include/policy_unpack.h1
-rw-r--r--security/apparmor/policy_compat.c319
-rw-r--r--security/apparmor/policy_unpack.c290
5 files changed, 359 insertions, 287 deletions
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index ff23fcfefe19..4377123c2b98 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -5,7 +5,8 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o secid.o file.o policy_ns.o label.o mount.o net.o
+ resource.o secid.o file.o policy_ns.o label.o mount.o net.o \
+ policy_compat.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
clean-files := capability_names.h rlim_names.h net_names.h
diff --git a/security/apparmor/include/policy_compat.h b/security/apparmor/include/policy_compat.h
new file mode 100644
index 000000000000..af0e174332df
--- /dev/null
+++ b/security/apparmor/include/policy_compat.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * Code to provide backwards compatibility with older policy versions,
+ * by converting/mapping older policy formats into the newer internal
+ * formats.
+ *
+ * Copyright 2022 Canonical Ltd.
+ */
+
+#ifndef __POLICY_COMPAT_H
+#define __POLICY_COMPAT_H
+
+#include "policy.h"
+
+#define K_ABI_MASK 0x3ff
+#define FORCE_COMPLAIN_FLAG 0x800
+#define VERSION_LT(X, Y) (((X) & K_ABI_MASK) < ((Y) & K_ABI_MASK))
+#define VERSION_LE(X, Y) (((X) & K_ABI_MASK) <= ((Y) & K_ABI_MASK))
+#define VERSION_GT(X, Y) (((X) & K_ABI_MASK) > ((Y) & K_ABI_MASK))
+
+#define v5 5 /* base version */
+#define v6 6 /* per entry policydb mediation check */
+#define v7 7
+#define v8 8 /* full network masking */
+#define v9 9 /* xbits are used as permission bits in policydb */
+
+int aa_compat_map_xmatch(struct aa_policydb *policy);
+int aa_compat_map_policy(struct aa_policydb *policy, u32 version);
+int aa_compat_map_file(struct aa_policydb *policy);
+
+#endif /* __POLICY_COMPAT_H */
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
index eb5f7d7f132b..cdfbc8a54a9d 100644
--- a/security/apparmor/include/policy_unpack.h
+++ b/security/apparmor/include/policy_unpack.h
@@ -16,6 +16,7 @@
#include <linux/dcache.h>
#include <linux/workqueue.h>
+
struct aa_load_ent {
struct list_head list;
struct aa_profile *new;
diff --git a/security/apparmor/policy_compat.c b/security/apparmor/policy_compat.c
new file mode 100644
index 000000000000..1aa5cced935e
--- /dev/null
+++ b/security/apparmor/policy_compat.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor functions for unpacking policy loaded
+ * from userspace.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2022 Canonical Ltd.
+ *
+ * Code to provide backwards compatibility with older policy versions,
+ * by converting/mapping older policy formats into the newer internal
+ * formats.
+ */
+
+#include <linux/ctype.h>
+#include <linux/errno.h>
+
+#include "include/lib.h"
+#include "include/policy_unpack.h"
+#include "include/policy_compat.h"
+
+/* remap old accept table embedded permissions to separate permission table */
+static u32 dfa_map_xindex(u16 mask)
+{
+ u16 old_index = (mask >> 10) & 0xf;
+ u32 index = 0;
+
+ if (mask & 0x100)
+ index |= AA_X_UNSAFE;
+ if (mask & 0x200)
+ index |= AA_X_INHERIT;
+ if (mask & 0x80)
+ index |= AA_X_UNCONFINED;
+
+ if (old_index == 1) {
+ index |= AA_X_UNCONFINED;
+ } else if (old_index == 2) {
+ index |= AA_X_NAME;
+ } else if (old_index == 3) {
+ index |= AA_X_NAME | AA_X_CHILD;
+ } else if (old_index) {
+ index |= AA_X_TABLE;
+ index |= old_index - 4;
+ }
+
+ return index;
+}
+
+/*
+ * map old dfa inline permissions to new format
+ */
+#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \
+ ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
+#define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f)
+#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
+#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
+#define dfa_user_xindex(dfa, state) \
+ (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
+
+#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \
+ 0x7f) | \
+ ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
+#define dfa_other_xbits(dfa, state) \
+ ((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f)
+#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
+#define dfa_other_quiet(dfa, state) \
+ ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
+#define dfa_other_xindex(dfa, state) \
+ dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
+
+/**
+ * map_old_perms - map old file perms layout to the new layout
+ * @old: permission set in old mapping
+ *
+ * Returns: new permission mapping
+ */
+static u32 map_old_perms(u32 old)
+{
+ u32 new = old & 0xf;
+
+ if (old & MAY_READ)
+ new |= AA_MAY_GETATTR | AA_MAY_OPEN;
+ if (old & MAY_WRITE)
+ new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE |
+ AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN;
+ if (old & 0x10)
+ new |= AA_MAY_LINK;
+ /* the old mapping lock and link_subset flags where overlaid
+ * and use was determined by part of a pair that they were in
+ */
+ if (old & 0x20)
+ new |= AA_MAY_LOCK | AA_LINK_SUBSET;
+ if (old & 0x40) /* AA_EXEC_MMAP */
+ new |= AA_EXEC_MMAP;
+
+ return new;
+}
+
+static void compute_fperms_allow(struct aa_perms *perms, struct aa_dfa *dfa,
+ aa_state_t state)
+{
+ perms->allow |= AA_MAY_GETATTR;
+
+ /* change_profile wasn't determined by ownership in old mapping */
+ if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
+ perms->allow |= AA_MAY_CHANGE_PROFILE;
+ if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
+ perms->allow |= AA_MAY_ONEXEC;
+}
+
+static struct aa_perms compute_fperms_user(struct aa_dfa *dfa,
+ aa_state_t state)
+{
+ struct aa_perms perms = { };
+
+ perms.allow = map_old_perms(dfa_user_allow(dfa, state));
+ perms.audit = map_old_perms(dfa_user_audit(dfa, state));
+ perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
+ perms.xindex = dfa_user_xindex(dfa, state);
+
+ compute_fperms_allow(&perms, dfa, state);
+
+ return perms;
+}
+
+static struct aa_perms compute_fperms_other(struct aa_dfa *dfa,
+ aa_state_t state)
+{
+ struct aa_perms perms = { };
+
+ perms.allow = map_old_perms(dfa_other_allow(dfa, state));
+ perms.audit = map_old_perms(dfa_other_audit(dfa, state));
+ perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
+ perms.xindex = dfa_other_xindex(dfa, state);
+
+ compute_fperms_allow(&perms, dfa, state);
+
+ return perms;
+}
+
+/**
+ * aa_compute_fperms - convert dfa compressed perms to internal perms and store
+ * them so they can be retrieved later.
+ * @dfa: a dfa using fperms to remap to internal permissions
+ *
+ * Returns: remapped perm table
+ */
+static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
+{
+ aa_state_t state;
+ unsigned int state_count;
+ struct aa_perms *table;
+
+ AA_BUG(!dfa);
+
+ state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
+ /* DFAs are restricted from having a state_count of less than 2 */
+ table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ /* zero init so skip the trap state (state == 0) */
+ for (state = 1; state < state_count; state++) {
+ table[state * 2] = compute_fperms_user(dfa, state);
+ table[state * 2 + 1] = compute_fperms_other(dfa, state);
+ }
+
+ return table;
+}
+
+static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
+{
+ struct aa_perms *perms;
+ int state;
+ int state_count;
+
+ AA_BUG(!xmatch);
+
+ state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen;
+ /* DFAs are restricted from having a state_count of less than 2 */
+ perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
+
+ /* zero init so skip the trap state (state == 0) */
+ for (state = 1; state < state_count; state++)
+ perms[state].allow = dfa_user_allow(xmatch, state);
+
+ return perms;
+}
+
+static u32 map_other(u32 x)
+{
+ return ((x & 0x3) << 8) | /* SETATTR/GETATTR */
+ ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */
+ ((x & 0x60) << 19); /* SETOPT/GETOPT */
+}
+
+static u32 map_xbits(u32 x)
+{
+ return ((x & 0x1) << 7) |
+ ((x & 0x7e) << 9);
+}
+
+static struct aa_perms compute_perms_entry(struct aa_dfa *dfa,
+ aa_state_t state,
+ u32 version)
+{
+ struct aa_perms perms = { };
+
+ perms.allow = dfa_user_allow(dfa, state);
+ perms.audit = dfa_user_audit(dfa, state);
+ perms.quiet = dfa_user_quiet(dfa, state);
+
+ /*
+ * This mapping is convulated due to history.
+ * v1-v4: only file perms, which are handled by compute_fperms
+ * v5: added policydb which dropped user conditional to gain new
+ * perm bits, but had to map around the xbits because the
+ * userspace compiler was still munging them.
+ * v9: adds using the xbits in policydb because the compiler now
+ * supports treating policydb permission bits different.
+ * Unfortunately there is no way to force auditing on the
+ * perms represented by the xbits
+ */
+ perms.allow |= map_other(dfa_other_allow(dfa, state));
+ if (VERSION_LE(version, v8))
+ perms.allow |= AA_MAY_LOCK;
+ else
+ perms.allow |= map_xbits(dfa_user_xbits(dfa, state));
+
+ /*
+ * for v5-v9 perm mapping in the policydb, the other set is used
+ * to extend the general perm set
+ */
+ perms.audit |= map_other(dfa_other_audit(dfa, state));
+ perms.quiet |= map_other(dfa_other_quiet(dfa, state));
+ if (VERSION_GT(version, v8))
+ perms.quiet |= map_xbits(dfa_other_xbits(dfa, state));
+
+ return perms;
+}
+
+static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version)
+{
+ unsigned int state;
+ unsigned int state_count;
+ struct aa_perms *table;
+
+ AA_BUG(!dfa);
+
+ state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
+ /* DFAs are restricted from having a state_count of less than 2 */
+ table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ /* zero init so skip the trap state (state == 0) */
+ for (state = 1; state < state_count; state++)
+ table[state] = compute_perms_entry(dfa, state, version);
+
+ return table;
+}
+
+/**
+ * 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;
+}
+
+/* TODO: merge different dfa mappings into single map_policy fn */
+int aa_compat_map_xmatch(struct aa_policydb *policy)
+{
+ policy->perms = compute_xmatch_perms(policy->dfa);
+ if (!policy->perms)
+ return -ENOMEM;
+
+ remap_dfa_accept(policy->dfa, 1);
+
+ return 0;
+}
+
+int aa_compat_map_policy(struct aa_policydb *policy, u32 version)
+{
+ policy->perms = compute_perms(policy->dfa, version);
+ if (!policy->perms)
+ return -ENOMEM;
+
+ remap_dfa_accept(policy->dfa, 1);
+
+ return 0;
+}
+
+int aa_compat_map_file(struct aa_policydb *policy)
+{
+ policy->perms = compute_fperms(policy->dfa);
+ if (!policy->perms)
+ return -ENOMEM;
+
+ remap_dfa_accept(policy->dfa, 2);
+
+ return 0;
+}
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index c578d9af785e..63196df2841b 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -27,18 +27,8 @@
#include "include/path.h"
#include "include/policy.h"
#include "include/policy_unpack.h"
+#include "include/policy_compat.h"
-#define K_ABI_MASK 0x3ff
-#define FORCE_COMPLAIN_FLAG 0x800
-#define VERSION_LT(X, Y) (((X) & K_ABI_MASK) < ((Y) & K_ABI_MASK))
-#define VERSION_LE(X, Y) (((X) & K_ABI_MASK) <= ((Y) & K_ABI_MASK))
-#define VERSION_GT(X, Y) (((X) & K_ABI_MASK) > ((Y) & K_ABI_MASK))
-
-#define v5 5 /* base version */
-#define v6 6 /* per entry policydb mediation check */
-#define v7 7
-#define v8 8 /* full network masking */
-#define v9 9 /* xbits are used as permission bits in policydb */
/*
* The AppArmor interface treats data as a type byte followed by the
@@ -671,270 +661,6 @@ static int datacmp(struct rhashtable_compare_arg *arg, const void *obj)
return strcmp(data->key, *key);
}
-/* remap old accept table embedded permissions to separate permission table */
-static u32 dfa_map_xindex(u16 mask)
-{
- u16 old_index = (mask >> 10) & 0xf;
- u32 index = 0;
-
- if (mask & 0x100)
- index |= AA_X_UNSAFE;
- if (mask & 0x200)
- index |= AA_X_INHERIT;
- if (mask & 0x80)
- index |= AA_X_UNCONFINED;
-
- if (old_index == 1) {
- index |= AA_X_UNCONFINED;
- } else if (old_index == 2) {
- index |= AA_X_NAME;
- } else if (old_index == 3) {
- index |= AA_X_NAME | AA_X_CHILD;
- } else if (old_index) {
- index |= AA_X_TABLE;
- index |= old_index - 4;
- }
-
- return index;
-}
-
-/*
- * map old dfa inline permissions to new format
- */
-#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \
- ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
-#define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f)
-#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
-#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
-#define dfa_user_xindex(dfa, state) \
- (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
-
-#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \
- 0x7f) | \
- ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
-#define dfa_other_xbits(dfa, state) \
- ((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f)
-#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
-#define dfa_other_quiet(dfa, state) \
- ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
-#define dfa_other_xindex(dfa, state) \
- dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
-
-/**
- * map_old_perms - map old file perms layout to the new layout
- * @old: permission set in old mapping
- *
- * Returns: new permission mapping
- */
-static u32 map_old_perms(u32 old)
-{
- u32 new = old & 0xf;
-
- if (old & MAY_READ)
- new |= AA_MAY_GETATTR | AA_MAY_OPEN;
- if (old & MAY_WRITE)
- new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE |
- AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN;
- if (old & 0x10)
- new |= AA_MAY_LINK;
- /* the old mapping lock and link_subset flags where overlaid
- * and use was determined by part of a pair that they were in
- */
- if (old & 0x20)
- new |= AA_MAY_LOCK | AA_LINK_SUBSET;
- if (old & 0x40) /* AA_EXEC_MMAP */
- new |= AA_EXEC_MMAP;
-
- return new;
-}
-
-static void compute_fperms_allow(struct aa_perms *perms, struct aa_dfa *dfa,
- aa_state_t state)
-{
- perms->allow |= AA_MAY_GETATTR;
-
- /* change_profile wasn't determined by ownership in old mapping */
- if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
- perms->allow |= AA_MAY_CHANGE_PROFILE;
- if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
- perms->allow |= AA_MAY_ONEXEC;
-}
-
-static struct aa_perms compute_fperms_user(struct aa_dfa *dfa,
- aa_state_t state)
-{
- struct aa_perms perms = { };
-
- perms.allow = map_old_perms(dfa_user_allow(dfa, state));
- perms.audit = map_old_perms(dfa_user_audit(dfa, state));
- perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
- perms.xindex = dfa_user_xindex(dfa, state);
-
- compute_fperms_allow(&perms, dfa, state);
-
- return perms;
-}
-
-static struct aa_perms compute_fperms_other(struct aa_dfa *dfa,
- aa_state_t state)
-{
- struct aa_perms perms = { };
-
- perms.allow = map_old_perms(dfa_other_allow(dfa, state));
- perms.audit = map_old_perms(dfa_other_audit(dfa, state));
- perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
- perms.xindex = dfa_other_xindex(dfa, state);
-
- compute_fperms_allow(&perms, dfa, state);
-
- return perms;
-}
-
-/**
- * aa_compute_fperms - convert dfa compressed perms to internal perms and store
- * them so they can be retrieved later.
- * @dfa: a dfa using fperms to remap to internal permissions
- *
- * Returns: remapped perm table
- */
-static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
-{
- aa_state_t state;
- unsigned int state_count;
- struct aa_perms *table;
-
- AA_BUG(!dfa);
-
- state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
- /* DFAs are restricted from having a state_count of less than 2 */
- table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL);
- if (!table)
- return NULL;
-
- /* zero init so skip the trap state (state == 0) */
- for (state = 1; state < state_count; state++) {
- table[state * 2] = compute_fperms_user(dfa, state);
- table[state * 2 + 1] = compute_fperms_other(dfa, state);
- }
-
- return table;
-}
-
-static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
-{
- struct aa_perms *perms;
- int state;
- int state_count;
-
- AA_BUG(!xmatch);
-
- state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen;
- /* DFAs are restricted from having a state_count of less than 2 */
- perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
-
- /* zero init so skip the trap state (state == 0) */
- for (state = 1; state < state_count; state++)
- perms[state].allow = dfa_user_allow(xmatch, state);
-
- return perms;
-}
-
-static u32 map_other(u32 x)
-{
- return ((x & 0x3) << 8) | /* SETATTR/GETATTR */
- ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */
- ((x & 0x60) << 19); /* SETOPT/GETOPT */
-}
-
-static u32 map_xbits(u32 x)
-{
- return ((x & 0x1) << 7) |
- ((x & 0x7e) << 9);
-}
-
-static struct aa_perms compute_perms_entry(struct aa_dfa *dfa,
- aa_state_t state,
- u32 version)
-{
- struct aa_perms perms = { };
-
- perms.allow = dfa_user_allow(dfa, state);
- perms.audit = dfa_user_audit(dfa, state);
- perms.quiet = dfa_user_quiet(dfa, state);
-
- /*
- * This mapping is convulated due to history.
- * v1-v4: only file perms, which are handled by compute_fperms
- * v5: added policydb which dropped user conditional to gain new
- * perm bits, but had to map around the xbits because the
- * userspace compiler was still munging them.
- * v9: adds using the xbits in policydb because the compiler now
- * supports treating policydb permission bits different.
- * Unfortunately there is no way to force auditing on the
- * perms represented by the xbits
- */
- perms.allow |= map_other(dfa_other_allow(dfa, state));
- if (VERSION_LE(version, v8))
- perms.allow |= AA_MAY_LOCK;
- else
- perms.allow |= map_xbits(dfa_user_xbits(dfa, state));
-
- /*
- * for v5-v9 perm mapping in the policydb, the other set is used
- * to extend the general perm set
- */
- perms.audit |= map_other(dfa_other_audit(dfa, state));
- perms.quiet |= map_other(dfa_other_quiet(dfa, state));
- if (VERSION_GT(version, v8))
- perms.quiet |= map_xbits(dfa_other_xbits(dfa, state));
-
- return perms;
-}
-
-static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version)
-{
- unsigned int state;
- unsigned int state_count;
- struct aa_perms *table;
-
- AA_BUG(!dfa);
-
- state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
- /* DFAs are restricted from having a state_count of less than 2 */
- table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
- if (!table)
- return NULL;
-
- /* zero init so skip the trap state (state == 0) */
- for (state = 1; state < state_count; state++)
- table[state] = compute_perms_entry(dfa, state, version);
-
- return table;
-}
-
-/**
- * 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)
@@ -1001,12 +727,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
}
profile->xmatch_len = tmp;
profile->xmatch.start[AA_CLASS_XMATCH] = DFA_START;
- profile->xmatch.perms = compute_xmatch_perms(profile->xmatch.dfa);
- if (!profile->xmatch.perms) {
+ if (aa_compat_map_xmatch(&profile->xmatch)) {
info = "failed to convert xmatch permission table";
goto fail;
}
- remap_dfa_accept(profile->xmatch.dfa, 1);
}
/* disconnected attachment string is optional */
@@ -1131,14 +855,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
}
if (!unpack_nameX(e, AA_STRUCTEND, NULL))
goto fail;
- profile->policy.perms = compute_perms(profile->policy.dfa,
- e->version);
- if (!profile->policy.perms) {
+ if (aa_compat_map_policy(&profile->policy, e->version)) {
info = "failed to remap policydb permission table";
goto fail;
}
- /* Do not remap internal dfas */
- remap_dfa_accept(profile->policy.dfa, 1);
} else
profile->policy.dfa = aa_get_dfa(nulldfa);
@@ -1154,12 +874,10 @@ 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) {
+ if (aa_compat_map_file(&profile->file)) {
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;