Commit 98b824ff authored by John Johansen's avatar John Johansen

apparmor: refcount the pdb

With the move to permission tables the dfa is no longer a stand
alone entity when used, needing a minimum of a permission table.
However it still could be shared among different pdbs each using
a different permission table.

Instead of duping the permission table when sharing a pdb, add a
refcount to the pdb so it can be easily shared.
Reviewed-by: default avatarGeorgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 75c77e9e
...@@ -619,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, ...@@ -619,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
if (profile_unconfined(profile)) if (profile_unconfined(profile))
return; return;
if (rules->file.dfa && *match_str == AA_CLASS_FILE) { if (rules->file->dfa && *match_str == AA_CLASS_FILE) {
state = aa_dfa_match_len(rules->file.dfa, state = aa_dfa_match_len(rules->file->dfa,
rules->file.start[AA_CLASS_FILE], rules->file->start[AA_CLASS_FILE],
match_str + 1, match_len - 1); match_str + 1, match_len - 1);
if (state) { if (state) {
struct path_cond cond = { }; struct path_cond cond = { };
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); tmp = *(aa_lookup_fperms(rules->file, state, &cond));
} }
} else if (rules->policy.dfa) { } else if (rules->policy->dfa) {
if (!RULE_MEDIATES(rules, *match_str)) if (!RULE_MEDIATES(rules, *match_str))
return; /* no change to current perms */ return; /* no change to current perms */
state = aa_dfa_match_len(rules->policy.dfa, state = aa_dfa_match_len(rules->policy->dfa,
rules->policy.start[0], rules->policy->start[0],
match_str, match_len); match_str, match_len);
if (state) if (state)
tmp = *aa_lookup_perms(&rules->policy, state); tmp = *aa_lookup_perms(rules->policy, state);
} }
aa_apply_modes_to_perms(profile, &tmp); aa_apply_modes_to_perms(profile, &tmp);
aa_perms_accum_raw(perms, &tmp); aa_perms_accum_raw(perms, &tmp);
...@@ -1096,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v) ...@@ -1096,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
struct aa_profile *profile = labels_profile(label); struct aa_profile *profile = labels_profile(label);
if (profile->attach.xmatch_str) if (profile->attach.xmatch_str)
seq_printf(seq, "%s\n", profile->attach.xmatch_str); seq_printf(seq, "%s\n", profile->attach.xmatch_str);
else if (profile->attach.xmatch.dfa) else if (profile->attach.xmatch->dfa)
seq_puts(seq, "<unknown>\n"); seq_puts(seq, "<unknown>\n");
else else
seq_printf(seq, "%s\n", profile->base.name); seq_printf(seq, "%s\n", profile->base.name);
......
...@@ -77,7 +77,7 @@ static int may_change_ptraced_domain(const struct cred *to_cred, ...@@ -77,7 +77,7 @@ static int may_change_ptraced_domain(const struct cred *to_cred,
/**** TODO: dedup to aa_label_match - needs perm and dfa, merging /**** TODO: dedup to aa_label_match - needs perm and dfa, merging
* specifically this is an exact copy of aa_label_match except * specifically this is an exact copy of aa_label_match except
* aa_compute_perms is replaced with aa_compute_fperms * aa_compute_perms is replaced with aa_compute_fperms
* and policy.dfa with file.dfa * and policy->dfa with file->dfa
****/ ****/
/* match a profile and its associated ns component if needed /* match a profile and its associated ns component if needed
* Assumes visibility test has already been done. * Assumes visibility test has already been done.
...@@ -93,16 +93,16 @@ static inline aa_state_t match_component(struct aa_profile *profile, ...@@ -93,16 +93,16 @@ static inline aa_state_t match_component(struct aa_profile *profile,
const char *ns_name; const char *ns_name;
if (stack) if (stack)
state = aa_dfa_match(rules->file.dfa, state, "&"); state = aa_dfa_match(rules->file->dfa, state, "&");
if (profile->ns == tp->ns) if (profile->ns == tp->ns)
return aa_dfa_match(rules->file.dfa, state, tp->base.hname); return aa_dfa_match(rules->file->dfa, state, tp->base.hname);
/* try matching with namespace name and then profile */ /* try matching with namespace name and then profile */
ns_name = aa_ns_name(profile->ns, tp->ns, true); ns_name = aa_ns_name(profile->ns, tp->ns, true);
state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); state = aa_dfa_match_len(rules->file->dfa, state, ":", 1);
state = aa_dfa_match(rules->file.dfa, state, ns_name); state = aa_dfa_match(rules->file->dfa, state, ns_name);
state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); state = aa_dfa_match_len(rules->file->dfa, state, ":", 1);
return aa_dfa_match(rules->file.dfa, state, tp->base.hname); return aa_dfa_match(rules->file->dfa, state, tp->base.hname);
} }
/** /**
...@@ -150,12 +150,12 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -150,12 +150,12 @@ static int label_compound_match(struct aa_profile *profile,
label_for_each_cont(i, label, tp) { label_for_each_cont(i, label, tp) {
if (!aa_ns_visible(profile->ns, tp->ns, subns)) if (!aa_ns_visible(profile->ns, tp->ns, subns))
continue; continue;
state = aa_dfa_match(rules->file.dfa, state, "//&"); state = aa_dfa_match(rules->file->dfa, state, "//&");
state = match_component(profile, tp, false, state); state = match_component(profile, tp, false, state);
if (!state) if (!state)
goto fail; goto fail;
} }
*perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); *perms = *(aa_lookup_fperms(rules->file, state, &cond));
aa_apply_modes_to_perms(profile, perms); aa_apply_modes_to_perms(profile, perms);
if ((perms->allow & request) != request) if ((perms->allow & request) != request)
return -EACCES; return -EACCES;
...@@ -210,7 +210,7 @@ static int label_components_match(struct aa_profile *profile, ...@@ -210,7 +210,7 @@ static int label_components_match(struct aa_profile *profile,
return 0; return 0;
next: next:
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); tmp = *(aa_lookup_fperms(rules->file, state, &cond));
aa_apply_modes_to_perms(profile, &tmp); aa_apply_modes_to_perms(profile, &tmp);
aa_perms_accum(perms, &tmp); aa_perms_accum(perms, &tmp);
label_for_each_cont(i, label, tp) { label_for_each_cont(i, label, tp) {
...@@ -219,7 +219,7 @@ static int label_components_match(struct aa_profile *profile, ...@@ -219,7 +219,7 @@ static int label_components_match(struct aa_profile *profile,
state = match_component(profile, tp, stack, start); state = match_component(profile, tp, stack, start);
if (!state) if (!state)
goto fail; goto fail;
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); tmp = *(aa_lookup_fperms(rules->file, state, &cond));
aa_apply_modes_to_perms(profile, &tmp); aa_apply_modes_to_perms(profile, &tmp);
aa_perms_accum(perms, &tmp); aa_perms_accum(perms, &tmp);
} }
...@@ -317,7 +317,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, ...@@ -317,7 +317,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
might_sleep(); might_sleep();
/* transition from exec match to xattr set */ /* transition from exec match to xattr set */
state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); state = aa_dfa_outofband_transition(attach->xmatch->dfa, state);
d = bprm->file->f_path.dentry; d = bprm->file->f_path.dentry;
for (i = 0; i < attach->xattr_count; i++) { for (i = 0; i < attach->xattr_count; i++) {
...@@ -331,20 +331,20 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, ...@@ -331,20 +331,20 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
* that not present xattr can be distinguished from a 0 * that not present xattr can be distinguished from a 0
* length value or rule that matches any value * length value or rule that matches any value
*/ */
state = aa_dfa_null_transition(attach->xmatch.dfa, state = aa_dfa_null_transition(attach->xmatch->dfa,
state); state);
/* Check xattr value */ /* Check xattr value */
state = aa_dfa_match_len(attach->xmatch.dfa, state, state = aa_dfa_match_len(attach->xmatch->dfa, state,
value, size); value, size);
index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; index = ACCEPT_TABLE(attach->xmatch->dfa)[state];
perm = attach->xmatch.perms[index].allow; perm = attach->xmatch->perms[index].allow;
if (!(perm & MAY_EXEC)) { if (!(perm & MAY_EXEC)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
} }
/* transition to next element */ /* transition to next element */
state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); state = aa_dfa_outofband_transition(attach->xmatch->dfa, state);
if (size < 0) { if (size < 0) {
/* /*
* No xattr match, so verify if transition to * No xattr match, so verify if transition to
...@@ -413,16 +413,16 @@ static struct aa_label *find_attach(const struct linux_binprm *bprm, ...@@ -413,16 +413,16 @@ static struct aa_label *find_attach(const struct linux_binprm *bprm,
* as another profile, signal a conflict and refuse to * as another profile, signal a conflict and refuse to
* match. * match.
*/ */
if (attach->xmatch.dfa) { if (attach->xmatch->dfa) {
unsigned int count; unsigned int count;
aa_state_t state; aa_state_t state;
u32 index, perm; u32 index, perm;
state = aa_dfa_leftmatch(attach->xmatch.dfa, state = aa_dfa_leftmatch(attach->xmatch->dfa,
attach->xmatch.start[AA_CLASS_XMATCH], attach->xmatch->start[AA_CLASS_XMATCH],
name, &count); name, &count);
index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; index = ACCEPT_TABLE(attach->xmatch->dfa)[state];
perm = attach->xmatch.perms[index].allow; perm = attach->xmatch->perms[index].allow;
/* any accepting state means a valid match. */ /* any accepting state means a valid match. */
if (perm & MAY_EXEC) { if (perm & MAY_EXEC) {
int ret = 0; int ret = 0;
...@@ -525,7 +525,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, ...@@ -525,7 +525,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
/* TODO: move lookup parsing to unpack time so this is a straight /* TODO: move lookup parsing to unpack time so this is a straight
* index into the resultant label * index into the resultant label
*/ */
for (*name = rules->file.trans.table[index]; !label && *name; for (*name = rules->file->trans.table[index]; !label && *name;
*name = next_name(xtype, *name)) { *name = next_name(xtype, *name)) {
if (xindex & AA_X_CHILD) { if (xindex & AA_X_CHILD) {
struct aa_profile *new_profile; struct aa_profile *new_profile;
...@@ -579,7 +579,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile, ...@@ -579,7 +579,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
break; break;
case AA_X_TABLE: case AA_X_TABLE:
/* TODO: fix when perm mapping done at unload */ /* TODO: fix when perm mapping done at unload */
stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; stack = rules->file->trans.table[xindex & AA_X_INDEX_MASK];
if (*stack != '&') { if (*stack != '&') {
/* released by caller */ /* released by caller */
new = x_table_lookup(profile, xindex, lookupname); new = x_table_lookup(profile, xindex, lookupname);
...@@ -638,7 +638,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred, ...@@ -638,7 +638,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
typeof(*rules), list); typeof(*rules), list);
struct aa_label *new = NULL; struct aa_label *new = NULL;
const char *info = NULL, *name = NULL, *target = NULL; const char *info = NULL, *name = NULL, *target = NULL;
aa_state_t state = rules->file.start[AA_CLASS_FILE]; aa_state_t state = rules->file->start[AA_CLASS_FILE];
struct aa_perms perms = {}; struct aa_perms perms = {};
bool nonewprivs = false; bool nonewprivs = false;
int error = 0; int error = 0;
...@@ -672,7 +672,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred, ...@@ -672,7 +672,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
} }
/* find exec permissions for name */ /* find exec permissions for name */
state = aa_str_perms(&(rules->file), state, name, cond, &perms); state = aa_str_perms(rules->file, state, name, cond, &perms);
if (perms.allow & MAY_EXEC) { if (perms.allow & MAY_EXEC) {
/* exec permission determine how to transition */ /* exec permission determine how to transition */
new = x_to_label(profile, bprm, name, perms.xindex, &target, new = x_to_label(profile, bprm, name, perms.xindex, &target,
...@@ -738,7 +738,7 @@ static int profile_onexec(const struct cred *subj_cred, ...@@ -738,7 +738,7 @@ static int profile_onexec(const struct cred *subj_cred,
{ {
struct aa_ruleset *rules = list_first_entry(&profile->rules, struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list); typeof(*rules), list);
aa_state_t state = rules->file.start[AA_CLASS_FILE]; aa_state_t state = rules->file->start[AA_CLASS_FILE];
struct aa_perms perms = {}; struct aa_perms perms = {};
const char *xname = NULL, *info = "change_profile onexec"; const char *xname = NULL, *info = "change_profile onexec";
int error = -EACCES; int error = -EACCES;
...@@ -771,7 +771,7 @@ static int profile_onexec(const struct cred *subj_cred, ...@@ -771,7 +771,7 @@ static int profile_onexec(const struct cred *subj_cred,
} }
/* find exec permissions for name */ /* find exec permissions for name */
state = aa_str_perms(&(rules->file), state, xname, cond, &perms); state = aa_str_perms(rules->file, state, xname, cond, &perms);
if (!(perms.allow & AA_MAY_ONEXEC)) { if (!(perms.allow & AA_MAY_ONEXEC)) {
info = "no change_onexec valid for executable"; info = "no change_onexec valid for executable";
goto audit; goto audit;
...@@ -780,7 +780,7 @@ static int profile_onexec(const struct cred *subj_cred, ...@@ -780,7 +780,7 @@ static int profile_onexec(const struct cred *subj_cred,
* onexec permission is linked to exec with a standard pairing * onexec permission is linked to exec with a standard pairing
* exec\0change_profile * exec\0change_profile
*/ */
state = aa_dfa_null_transition(rules->file.dfa, state); state = aa_dfa_null_transition(rules->file->dfa, state);
error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC,
state, &perms); state, &perms);
if (error) { if (error) {
...@@ -1300,7 +1300,7 @@ static int change_profile_perms_wrapper(const char *op, const char *name, ...@@ -1300,7 +1300,7 @@ static int change_profile_perms_wrapper(const char *op, const char *name,
if (!error) if (!error)
error = change_profile_perms(profile, target, stack, request, error = change_profile_perms(profile, target, stack, request,
rules->file.start[AA_CLASS_FILE], rules->file->start[AA_CLASS_FILE],
perms); perms);
if (error) if (error)
error = aa_audit_file(subj_cred, profile, perms, op, request, error = aa_audit_file(subj_cred, profile, perms, op, request,
......
...@@ -236,7 +236,7 @@ static int __aa_path_perm(const char *op, const struct cred *subj_cred, ...@@ -236,7 +236,7 @@ static int __aa_path_perm(const char *op, const struct cred *subj_cred,
if (profile_unconfined(profile)) if (profile_unconfined(profile))
return 0; return 0;
aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE],
name, cond, perms); name, cond, perms);
if (request & ~perms->allow) if (request & ~perms->allow)
e = -EACCES; e = -EACCES;
...@@ -353,16 +353,16 @@ static int profile_path_link(const struct cred *subj_cred, ...@@ -353,16 +353,16 @@ static int profile_path_link(const struct cred *subj_cred,
error = -EACCES; error = -EACCES;
/* aa_str_perms - handles the case of the dfa being NULL */ /* aa_str_perms - handles the case of the dfa being NULL */
state = aa_str_perms(&(rules->file), state = aa_str_perms(rules->file,
rules->file.start[AA_CLASS_FILE], lname, rules->file->start[AA_CLASS_FILE], lname,
cond, &lperms); cond, &lperms);
if (!(lperms.allow & AA_MAY_LINK)) if (!(lperms.allow & AA_MAY_LINK))
goto audit; goto audit;
/* test to see if target can be paired with link */ /* test to see if target can be paired with link */
state = aa_dfa_null_transition(rules->file.dfa, state); state = aa_dfa_null_transition(rules->file->dfa, state);
aa_str_perms(&(rules->file), state, tname, cond, &perms); aa_str_perms(rules->file, state, tname, cond, &perms);
/* force audit/quiet masks for link are stored in the second entry /* force audit/quiet masks for link are stored in the second entry
* in the link pair. * in the link pair.
...@@ -384,7 +384,7 @@ static int profile_path_link(const struct cred *subj_cred, ...@@ -384,7 +384,7 @@ static int profile_path_link(const struct cred *subj_cred,
/* Do link perm subset test requiring allowed permission on link are /* Do link perm subset test requiring allowed permission on link are
* a subset of the allowed permissions on target. * a subset of the allowed permissions on target.
*/ */
aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE],
tname, cond, &perms); tname, cond, &perms);
/* AA_MAY_LINK is not considered in the subset test */ /* AA_MAY_LINK is not considered in the subset test */
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include "match.h" #include "match.h"
extern struct aa_dfa *stacksplitdfa;
/* /*
* DEBUG remains global (no per profile flag) since it is mostly used in sysctl * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
* which is not related to profile accesses. * which is not related to profile accesses.
......
...@@ -102,9 +102,6 @@ struct aa_dfa { ...@@ -102,9 +102,6 @@ struct aa_dfa {
struct table_header *tables[YYTD_ID_TSIZE]; struct table_header *tables[YYTD_ID_TSIZE];
}; };
extern struct aa_dfa *nulldfa;
extern struct aa_dfa *stacksplitdfa;
#define byte_to_byte(X) (X) #define byte_to_byte(X) (X)
#define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \ #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \
...@@ -122,9 +119,6 @@ static inline size_t table_size(size_t len, size_t el_size) ...@@ -122,9 +119,6 @@ static inline size_t table_size(size_t len, size_t el_size)
return ALIGN(sizeof(struct table_header) + len * el_size, 8); return ALIGN(sizeof(struct table_header) + len * el_size, 8);
} }
int aa_setup_dfa_engine(void);
void aa_teardown_dfa_engine(void);
#define aa_state_t unsigned int #define aa_state_t unsigned int
struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
......
...@@ -74,12 +74,14 @@ enum profile_mode { ...@@ -74,12 +74,14 @@ enum profile_mode {
/* struct aa_policydb - match engine for a policy /* struct aa_policydb - match engine for a policy
* count: refcount for the pdb
* dfa: dfa pattern match * dfa: dfa pattern match
* perms: table of permissions * perms: table of permissions
* strs: table of strings, index by x * strs: table of strings, index by x
* start: set of start states for the different classes of data * start: set of start states for the different classes of data
*/ */
struct aa_policydb { struct aa_policydb {
struct kref count;
struct aa_dfa *dfa; struct aa_dfa *dfa;
struct { struct {
struct aa_perms *perms; struct aa_perms *perms;
...@@ -89,13 +91,36 @@ struct aa_policydb { ...@@ -89,13 +91,36 @@ struct aa_policydb {
aa_state_t start[AA_CLASS_LAST + 1]; aa_state_t start[AA_CLASS_LAST + 1];
}; };
static inline void aa_destroy_policydb(struct aa_policydb *policy) extern struct aa_policydb *nullpdb;
struct aa_policydb *aa_alloc_pdb(gfp_t gfp);
void aa_pdb_free_kref(struct kref *kref);
/**
* aa_get_pdb - increment refcount on @pdb
* @pdb: policydb (MAYBE NULL)
*
* Returns: pointer to @pdb if @pdb is NULL will return NULL
* Requires: @pdb must be held with valid refcount when called
*/
static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb)
{ {
aa_put_dfa(policy->dfa); if (pdb)
if (policy->perms) kref_get(&(pdb->count));
kvfree(policy->perms);
aa_free_str_table(&policy->trans);
return pdb;
}
/**
* aa_put_pdb - put a pdb refcount
* @pdb: pdb to put refcount (MAYBE NULL)
*
* Requires: if @pdb != NULL that a valid refcount be held
*/
static inline void aa_put_pdb(struct aa_policydb *pdb)
{
if (pdb)
kref_put(&pdb->count, aa_pdb_free_kref);
} }
static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy,
...@@ -139,8 +164,8 @@ struct aa_ruleset { ...@@ -139,8 +164,8 @@ struct aa_ruleset {
int size; int size;
/* TODO: merge policy and file */ /* TODO: merge policy and file */
struct aa_policydb policy; struct aa_policydb *policy;
struct aa_policydb file; struct aa_policydb *file;
struct aa_caps caps; struct aa_caps caps;
struct aa_rlimit rlimits; struct aa_rlimit rlimits;
...@@ -159,7 +184,7 @@ struct aa_ruleset { ...@@ -159,7 +184,7 @@ struct aa_ruleset {
*/ */
struct aa_attachment { struct aa_attachment {
const char *xmatch_str; const char *xmatch_str;
struct aa_policydb xmatch; struct aa_policydb *xmatch;
unsigned int xmatch_len; unsigned int xmatch_len;
int xattr_count; int xattr_count;
char **xattrs; char **xattrs;
...@@ -267,10 +292,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules, ...@@ -267,10 +292,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules,
unsigned char class) unsigned char class)
{ {
if (class <= AA_CLASS_LAST) if (class <= AA_CLASS_LAST)
return rules->policy.start[class]; return rules->policy->start[class];
else else
return aa_dfa_match_len(rules->policy.dfa, return aa_dfa_match_len(rules->policy->dfa,
rules->policy.start[0], &class, 1); rules->policy->start[0], &class, 1);
} }
static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)
...@@ -280,7 +305,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) ...@@ -280,7 +305,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)
if (!state) if (!state)
return DFA_NOMATCH; return DFA_NOMATCH;
return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2);
} }
static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head,
......
...@@ -92,8 +92,8 @@ static int profile_signal_perm(const struct cred *cred, ...@@ -92,8 +92,8 @@ static int profile_signal_perm(const struct cred *cred,
ad->subj_cred = cred; ad->subj_cred = cred;
ad->peer = peer; ad->peer = peer;
/* TODO: secondary cache check <profile, profile, perm> */ /* TODO: secondary cache check <profile, profile, perm> */
state = aa_dfa_next(rules->policy.dfa, state = aa_dfa_next(rules->policy->dfa,
rules->policy.start[AA_CLASS_SIGNAL], rules->policy->start[AA_CLASS_SIGNAL],
ad->signal); ad->signal);
aa_label_match(profile, rules, peer, state, false, request, &perms); aa_label_match(profile, rules, peer, state, false, request, &perms);
aa_apply_modes_to_perms(profile, &perms); aa_apply_modes_to_perms(profile, &perms);
......
...@@ -1270,14 +1270,14 @@ static inline aa_state_t match_component(struct aa_profile *profile, ...@@ -1270,14 +1270,14 @@ static inline aa_state_t match_component(struct aa_profile *profile,
const char *ns_name; const char *ns_name;
if (profile->ns == tp->ns) if (profile->ns == tp->ns)
return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); return aa_dfa_match(rules->policy->dfa, state, tp->base.hname);
/* try matching with namespace name and then profile */ /* try matching with namespace name and then profile */
ns_name = aa_ns_name(profile->ns, tp->ns, true); ns_name = aa_ns_name(profile->ns, tp->ns, true);
state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1);
state = aa_dfa_match(rules->policy.dfa, state, ns_name); state = aa_dfa_match(rules->policy->dfa, state, ns_name);
state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1);
return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); return aa_dfa_match(rules->policy->dfa, state, tp->base.hname);
} }
/** /**
...@@ -1323,12 +1323,12 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -1323,12 +1323,12 @@ static int label_compound_match(struct aa_profile *profile,
label_for_each_cont(i, label, tp) { label_for_each_cont(i, label, tp) {
if (!aa_ns_visible(profile->ns, tp->ns, subns)) if (!aa_ns_visible(profile->ns, tp->ns, subns))
continue; continue;
state = aa_dfa_match(rules->policy.dfa, state, "//&"); state = aa_dfa_match(rules->policy->dfa, state, "//&");
state = match_component(profile, rules, tp, state); state = match_component(profile, rules, tp, state);
if (!state) if (!state)
goto fail; goto fail;
} }
*perms = *aa_lookup_perms(&rules->policy, state); *perms = *aa_lookup_perms(rules->policy, state);
aa_apply_modes_to_perms(profile, perms); aa_apply_modes_to_perms(profile, perms);
if ((perms->allow & request) != request) if ((perms->allow & request) != request)
return -EACCES; return -EACCES;
...@@ -1381,7 +1381,7 @@ static int label_components_match(struct aa_profile *profile, ...@@ -1381,7 +1381,7 @@ static int label_components_match(struct aa_profile *profile,
return 0; return 0;
next: next:
tmp = *aa_lookup_perms(&rules->policy, state); tmp = *aa_lookup_perms(rules->policy, state);
aa_apply_modes_to_perms(profile, &tmp); aa_apply_modes_to_perms(profile, &tmp);
aa_perms_accum(perms, &tmp); aa_perms_accum(perms, &tmp);
label_for_each_cont(i, label, tp) { label_for_each_cont(i, label, tp) {
...@@ -1390,7 +1390,7 @@ static int label_components_match(struct aa_profile *profile, ...@@ -1390,7 +1390,7 @@ static int label_components_match(struct aa_profile *profile,
state = match_component(profile, rules, tp, start); state = match_component(profile, rules, tp, start);
if (!state) if (!state)
goto fail; goto fail;
tmp = *aa_lookup_perms(&rules->policy, state); tmp = *aa_lookup_perms(rules->policy, state);
aa_apply_modes_to_perms(profile, &tmp); aa_apply_modes_to_perms(profile, &tmp);
aa_perms_accum(perms, &tmp); aa_perms_accum(perms, &tmp);
} }
......
...@@ -341,8 +341,8 @@ void aa_profile_match_label(struct aa_profile *profile, ...@@ -341,8 +341,8 @@ void aa_profile_match_label(struct aa_profile *profile,
/* TODO: doesn't yet handle extended types */ /* TODO: doesn't yet handle extended types */
aa_state_t state; aa_state_t state;
state = aa_dfa_next(rules->policy.dfa, state = aa_dfa_next(rules->policy->dfa,
rules->policy.start[AA_CLASS_LABEL], rules->policy->start[AA_CLASS_LABEL],
type); type);
aa_label_match(profile, rules, label, state, false, request, perms); aa_label_match(profile, rules, label, state, false, request, perms);
} }
......
...@@ -1887,6 +1887,69 @@ static int __init apparmor_nf_ip_init(void) ...@@ -1887,6 +1887,69 @@ static int __init apparmor_nf_ip_init(void)
__initcall(apparmor_nf_ip_init); __initcall(apparmor_nf_ip_init);
#endif #endif
static char nulldfa_src[] = {
#include "nulldfa.in"
};
struct aa_dfa *nulldfa;
static char stacksplitdfa_src[] = {
#include "stacksplitdfa.in"
};
struct aa_dfa *stacksplitdfa;
struct aa_policydb *nullpdb;
static int __init aa_setup_dfa_engine(void)
{
int error = -ENOMEM;
nullpdb = aa_alloc_pdb(GFP_KERNEL);
if (!nullpdb)
return -ENOMEM;
nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src),
TO_ACCEPT1_FLAG(YYTD_DATA32) |
TO_ACCEPT2_FLAG(YYTD_DATA32));
if (IS_ERR(nulldfa)) {
error = PTR_ERR(nulldfa);
goto fail;
}
nullpdb->dfa = aa_get_dfa(nulldfa);
nullpdb->perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL);
if (!nullpdb->perms)
goto fail;
nullpdb->size = 2;
stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src,
sizeof(stacksplitdfa_src),
TO_ACCEPT1_FLAG(YYTD_DATA32) |
TO_ACCEPT2_FLAG(YYTD_DATA32));
if (IS_ERR(stacksplitdfa)) {
error = PTR_ERR(stacksplitdfa);
goto fail;
}
return 0;
fail:
aa_put_pdb(nullpdb);
aa_put_dfa(nulldfa);
nullpdb = NULL;
nulldfa = NULL;
stacksplitdfa = NULL;
return error;
}
static void __init aa_teardown_dfa_engine(void)
{
aa_put_dfa(stacksplitdfa);
aa_put_dfa(nulldfa);
aa_put_pdb(nullpdb);
nullpdb = NULL;
stacksplitdfa = NULL;
nulldfa = NULL;
}
static int __init apparmor_init(void) static int __init apparmor_init(void)
{ {
int error; int error;
......
...@@ -21,50 +21,6 @@ ...@@ -21,50 +21,6 @@
#define base_idx(X) ((X) & 0xffffff) #define base_idx(X) ((X) & 0xffffff)
static char nulldfa_src[] = {
#include "nulldfa.in"
};
struct aa_dfa *nulldfa;
static char stacksplitdfa_src[] = {
#include "stacksplitdfa.in"
};
struct aa_dfa *stacksplitdfa;
int __init aa_setup_dfa_engine(void)
{
int error;
nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src),
TO_ACCEPT1_FLAG(YYTD_DATA32) |
TO_ACCEPT2_FLAG(YYTD_DATA32));
if (IS_ERR(nulldfa)) {
error = PTR_ERR(nulldfa);
nulldfa = NULL;
return error;
}
stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src,
sizeof(stacksplitdfa_src),
TO_ACCEPT1_FLAG(YYTD_DATA32) |
TO_ACCEPT2_FLAG(YYTD_DATA32));
if (IS_ERR(stacksplitdfa)) {
aa_put_dfa(nulldfa);
nulldfa = NULL;
error = PTR_ERR(stacksplitdfa);
stacksplitdfa = NULL;
return error;
}
return 0;
}
void __init aa_teardown_dfa_engine(void)
{
aa_put_dfa(stacksplitdfa);
aa_put_dfa(nulldfa);
}
/** /**
* unpack_table - unpack a dfa table (one of accept, default, base, next check) * unpack_table - unpack a dfa table (one of accept, default, base, next check)
* @blob: data to unpack (NOT NULL) * @blob: data to unpack (NOT NULL)
......
...@@ -332,8 +332,8 @@ static int match_mnt_path_str(const struct cred *subj_cred, ...@@ -332,8 +332,8 @@ static int match_mnt_path_str(const struct cred *subj_cred,
} }
error = -EACCES; error = -EACCES;
pos = do_match_mnt(&rules->policy, pos = do_match_mnt(rules->policy,
rules->policy.start[AA_CLASS_MOUNT], rules->policy->start[AA_CLASS_MOUNT],
mntpnt, devname, type, flags, data, binary, &perms); mntpnt, devname, type, flags, data, binary, &perms);
if (pos) { if (pos) {
info = mnt_info_table[pos]; info = mnt_info_table[pos];
...@@ -606,10 +606,10 @@ static int profile_umount(const struct cred *subj_cred, ...@@ -606,10 +606,10 @@ static int profile_umount(const struct cred *subj_cred,
if (error) if (error)
goto audit; goto audit;
state = aa_dfa_match(rules->policy.dfa, state = aa_dfa_match(rules->policy->dfa,
rules->policy.start[AA_CLASS_MOUNT], rules->policy->start[AA_CLASS_MOUNT],
name); name);
perms = *aa_lookup_perms(&rules->policy, state); perms = *aa_lookup_perms(rules->policy, state);
if (AA_MAY_UMOUNT & ~perms.allow) if (AA_MAY_UMOUNT & ~perms.allow)
error = -EACCES; error = -EACCES;
...@@ -680,12 +680,12 @@ static struct aa_label *build_pivotroot(const struct cred *subj_cred, ...@@ -680,12 +680,12 @@ static struct aa_label *build_pivotroot(const struct cred *subj_cred,
goto audit; goto audit;
error = -EACCES; error = -EACCES;
state = aa_dfa_match(rules->policy.dfa, state = aa_dfa_match(rules->policy->dfa,
rules->policy.start[AA_CLASS_MOUNT], rules->policy->start[AA_CLASS_MOUNT],
new_name); new_name);
state = aa_dfa_null_transition(rules->policy.dfa, state); state = aa_dfa_null_transition(rules->policy->dfa, state);
state = aa_dfa_match(rules->policy.dfa, state, old_name); state = aa_dfa_match(rules->policy->dfa, state, old_name);
perms = *aa_lookup_perms(&rules->policy, state); perms = *aa_lookup_perms(rules->policy, state);
if (AA_MAY_PIVOTROOT & perms.allow) if (AA_MAY_PIVOTROOT & perms.allow)
error = 0; error = 0;
......
...@@ -127,9 +127,9 @@ int aa_profile_af_perm(struct aa_profile *profile, ...@@ -127,9 +127,9 @@ int aa_profile_af_perm(struct aa_profile *profile,
buffer[0] = cpu_to_be16(family); buffer[0] = cpu_to_be16(family);
buffer[1] = cpu_to_be16((u16) type); buffer[1] = cpu_to_be16((u16) type);
state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer,
4); 4);
perms = *aa_lookup_perms(&rules->policy, state); perms = *aa_lookup_perms(rules->policy, state);
aa_apply_modes_to_perms(profile, &perms); aa_apply_modes_to_perms(profile, &perms);
return aa_check_perms(profile, &perms, request, ad, audit_net_cb); return aa_check_perms(profile, &perms, request, ad, audit_net_cb);
......
...@@ -98,6 +98,41 @@ const char *const aa_profile_mode_names[] = { ...@@ -98,6 +98,41 @@ const char *const aa_profile_mode_names[] = {
}; };
static void aa_free_pdb(struct aa_policydb *policy)
{
if (policy) {
aa_put_dfa(policy->dfa);
if (policy->perms)
kvfree(policy->perms);
aa_free_str_table(&policy->trans);
}
}
/**
* aa_pdb_free_kref - free aa_policydb by kref (called by aa_put_pdb)
* @kr: kref callback for freeing of a dfa (NOT NULL)
*/
void aa_pdb_free_kref(struct kref *kref)
{
struct aa_policydb *pdb = container_of(kref, struct aa_policydb, count);
aa_free_pdb(pdb);
}
struct aa_policydb *aa_alloc_pdb(gfp_t gfp)
{
struct aa_policydb *pdb = kzalloc(sizeof(struct aa_policydb), gfp);
if (!pdb)
return NULL;
kref_init(&pdb->count);
return pdb;
}
/** /**
* __add_profile - add a profiles to list and label tree * __add_profile - add a profiles to list and label tree
* @list: list to add it to (NOT NULL) * @list: list to add it to (NOT NULL)
...@@ -200,15 +235,15 @@ static void free_attachment(struct aa_attachment *attach) ...@@ -200,15 +235,15 @@ static void free_attachment(struct aa_attachment *attach)
for (i = 0; i < attach->xattr_count; i++) for (i = 0; i < attach->xattr_count; i++)
kfree_sensitive(attach->xattrs[i]); kfree_sensitive(attach->xattrs[i]);
kfree_sensitive(attach->xattrs); kfree_sensitive(attach->xattrs);
aa_destroy_policydb(&attach->xmatch); aa_put_pdb(attach->xmatch);
} }
static void free_ruleset(struct aa_ruleset *rules) static void free_ruleset(struct aa_ruleset *rules)
{ {
int i; int i;
aa_destroy_policydb(&rules->file); aa_put_pdb(rules->file);
aa_destroy_policydb(&rules->policy); aa_put_pdb(rules->policy);
aa_free_cap_rules(&rules->caps); aa_free_cap_rules(&rules->caps);
aa_free_rlimit_rules(&rules->rlimits); aa_free_rlimit_rules(&rules->rlimits);
...@@ -590,16 +625,8 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, ...@@ -590,16 +625,8 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
/* TODO: ideally we should inherit abi from parent */ /* TODO: ideally we should inherit abi from parent */
profile->label.flags |= FLAG_NULL; profile->label.flags |= FLAG_NULL;
rules = list_first_entry(&profile->rules, typeof(*rules), list); rules = list_first_entry(&profile->rules, typeof(*rules), list);
rules->file.dfa = aa_get_dfa(nulldfa); rules->file = aa_get_pdb(nullpdb);
rules->file.perms = kcalloc(2, sizeof(struct aa_perms), gfp); rules->policy = aa_get_pdb(nullpdb);
if (!rules->file.perms)
goto fail;
rules->file.size = 2;
rules->policy.dfa = aa_get_dfa(nulldfa);
rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), gfp);
if (!rules->policy.perms)
goto fail;
rules->policy.size = 2;
if (parent) { if (parent) {
profile->path_flags = parent->path_flags; profile->path_flags = parent->path_flags;
...@@ -610,11 +637,6 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, ...@@ -610,11 +637,6 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
} }
return profile; return profile;
fail:
aa_free_profile(profile);
return NULL;
} }
/** /**
......
...@@ -703,24 +703,29 @@ static ssize_t unpack_perms_table(struct aa_ext *e, struct aa_perms **perms) ...@@ -703,24 +703,29 @@ static ssize_t unpack_perms_table(struct aa_ext *e, struct aa_perms **perms)
return -EPROTO; return -EPROTO;
} }
static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
bool required_dfa, bool required_trans, bool required_dfa, bool required_trans,
const char **info) const char **info)
{ {
struct aa_policydb *pdb;
void *pos = e->pos; void *pos = e->pos;
int i, flags, error = -EPROTO; int i, flags, error = -EPROTO;
ssize_t size; ssize_t size;
size = unpack_perms_table(e, &policy->perms); pdb = aa_alloc_pdb(GFP_KERNEL);
if (!pdb)
return -ENOMEM;
size = unpack_perms_table(e, &pdb->perms);
if (size < 0) { if (size < 0) {
error = size; error = size;
policy->perms = NULL; pdb->perms = NULL;
*info = "failed to unpack - perms"; *info = "failed to unpack - perms";
goto fail; goto fail;
} }
policy->size = size; pdb->size = size;
if (policy->perms) { if (pdb->perms) {
/* perms table present accept is index */ /* perms table present accept is index */
flags = TO_ACCEPT1_FLAG(YYTD_DATA32); flags = TO_ACCEPT1_FLAG(YYTD_DATA32);
} else { } else {
...@@ -729,13 +734,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, ...@@ -729,13 +734,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
TO_ACCEPT2_FLAG(YYTD_DATA32); TO_ACCEPT2_FLAG(YYTD_DATA32);
} }
policy->dfa = unpack_dfa(e, flags); pdb->dfa = unpack_dfa(e, flags);
if (IS_ERR(policy->dfa)) { if (IS_ERR(pdb->dfa)) {
error = PTR_ERR(policy->dfa); error = PTR_ERR(pdb->dfa);
policy->dfa = NULL; pdb->dfa = NULL;
*info = "failed to unpack - dfa"; *info = "failed to unpack - dfa";
goto fail; goto fail;
} else if (!policy->dfa) { } else if (!pdb->dfa) {
if (required_dfa) { if (required_dfa) {
*info = "missing required dfa"; *info = "missing required dfa";
goto fail; goto fail;
...@@ -749,18 +754,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, ...@@ -749,18 +754,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
* sadly start was given different names for file and policydb * sadly start was given different names for file and policydb
* but since it is optional we can try both * but since it is optional we can try both
*/ */
if (!aa_unpack_u32(e, &policy->start[0], "start")) if (!aa_unpack_u32(e, &pdb->start[0], "start"))
/* default start state */ /* default start state */
policy->start[0] = DFA_START; pdb->start[0] = DFA_START;
if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) { if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) {
/* default start state for xmatch and file dfa */ /* default start state for xmatch and file dfa */
policy->start[AA_CLASS_FILE] = DFA_START; pdb->start[AA_CLASS_FILE] = DFA_START;
} /* setup class index */ } /* setup class index */
for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) { for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) {
policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0], pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0],
i); i);
} }
if (!unpack_trans_table(e, &policy->trans) && required_trans) { if (!unpack_trans_table(e, &pdb->trans) && required_trans) {
*info = "failed to unpack profile transition table"; *info = "failed to unpack profile transition table";
goto fail; goto fail;
} }
...@@ -768,9 +773,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, ...@@ -768,9 +773,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
/* TODO: move compat mapping here, requires dfa merging first */ /* TODO: move compat mapping here, requires dfa merging first */
/* TODO: move verify here, it has to be done after compat mappings */ /* TODO: move verify here, it has to be done after compat mappings */
out: out:
*policy = pdb;
return 0; return 0;
fail: fail:
aa_put_pdb(pdb);
e->pos = pos; e->pos = pos;
return error; return error;
} }
...@@ -854,15 +861,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -854,15 +861,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
} }
/* neither xmatch_len not xmatch_perms are optional if xmatch is set */ /* neither xmatch_len not xmatch_perms are optional if xmatch is set */
if (profile->attach.xmatch.dfa) { if (profile->attach.xmatch->dfa) {
if (!aa_unpack_u32(e, &tmp, NULL)) { if (!aa_unpack_u32(e, &tmp, NULL)) {
info = "missing xmatch len"; info = "missing xmatch len";
goto fail; goto fail;
} }
profile->attach.xmatch_len = tmp; profile->attach.xmatch_len = tmp;
profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START; profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START;
if (!profile->attach.xmatch.perms) { if (!profile->attach.xmatch->perms) {
error = aa_compat_map_xmatch(&profile->attach.xmatch); error = aa_compat_map_xmatch(profile->attach.xmatch);
if (error) { if (error) {
info = "failed to convert xmatch permission table"; info = "failed to convert xmatch permission table";
goto fail; goto fail;
...@@ -979,16 +986,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -979,16 +986,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
if (error) if (error)
goto fail; goto fail;
/* Fixup: drop when we get rid of start array */ /* Fixup: drop when we get rid of start array */
if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0],
AA_CLASS_FILE)) AA_CLASS_FILE))
rules->policy.start[AA_CLASS_FILE] = rules->policy->start[AA_CLASS_FILE] =
aa_dfa_next(rules->policy.dfa, aa_dfa_next(rules->policy->dfa,
rules->policy.start[0], rules->policy->start[0],
AA_CLASS_FILE); AA_CLASS_FILE);
if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
goto fail; goto fail;
if (!rules->policy.perms) { if (!rules->policy->perms) {
error = aa_compat_map_policy(&rules->policy, error = aa_compat_map_policy(rules->policy,
e->version); e->version);
if (error) { if (error) {
info = "failed to remap policydb permission table"; info = "failed to remap policydb permission table";
...@@ -996,44 +1003,25 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -996,44 +1003,25 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
} }
} }
} else { } else {
rules->policy.dfa = aa_get_dfa(nulldfa); rules->policy = aa_get_pdb(nullpdb);
rules->policy.perms = kcalloc(2, sizeof(struct aa_perms),
GFP_KERNEL);
if (!rules->policy.perms)
goto fail;
rules->policy.size = 2;
} }
/* get file rules */ /* get file rules */
error = unpack_pdb(e, &rules->file, false, true, &info); error = unpack_pdb(e, &rules->file, false, true, &info);
if (error) { if (error) {
goto fail; goto fail;
} else if (rules->file.dfa) { } else if (rules->file->dfa) {
if (!rules->file.perms) { if (!rules->file->perms) {
error = aa_compat_map_file(&rules->file); error = aa_compat_map_file(rules->file);
if (error) { if (error) {
info = "failed to remap file permission table"; info = "failed to remap file permission table";
goto fail; goto fail;
} }
} }
} else if (rules->policy.dfa && } else if (rules->policy->dfa &&
rules->policy.start[AA_CLASS_FILE]) { rules->policy->start[AA_CLASS_FILE]) {
rules->file.dfa = aa_get_dfa(rules->policy.dfa); rules->file = aa_get_pdb(rules->policy);
rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE];
rules->file.perms = kcalloc(rules->policy.size,
sizeof(struct aa_perms),
GFP_KERNEL);
if (!rules->file.perms)
goto fail;
memcpy(rules->file.perms, rules->policy.perms,
rules->policy.size * sizeof(struct aa_perms));
rules->file.size = rules->policy.size;
} else { } else {
rules->file.dfa = aa_get_dfa(nulldfa); rules->file = aa_get_pdb(nullpdb);
rules->file.perms = kcalloc(2, sizeof(struct aa_perms),
GFP_KERNEL);
if (!rules->file.perms)
goto fail;
rules->file.size = 2;
} }
error = -EPROTO; error = -EPROTO;
if (aa_unpack_nameX(e, AA_STRUCT, "data")) { if (aa_unpack_nameX(e, AA_STRUCT, "data")) {
...@@ -1240,32 +1228,32 @@ static int verify_profile(struct aa_profile *profile) ...@@ -1240,32 +1228,32 @@ static int verify_profile(struct aa_profile *profile)
if (!rules) if (!rules)
return 0; return 0;
if (rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa, if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa,
rules->file.size)) { rules->file->size)) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: file Invalid named transition", NULL, "Unpack: file Invalid named transition", NULL,
-EPROTO); -EPROTO);
return -EPROTO; return -EPROTO;
} }
if (rules->policy.dfa && if (rules->policy->dfa &&
!verify_dfa_accept_index(rules->policy.dfa, rules->policy.size)) { !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: policy Invalid named transition", NULL, "Unpack: policy Invalid named transition", NULL,
-EPROTO); -EPROTO);
return -EPROTO; return -EPROTO;
} }
if (!verify_perms(&rules->file)) { if (!verify_perms(rules->file)) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: Invalid perm index", NULL, -EPROTO); "Unpack: Invalid perm index", NULL, -EPROTO);
return -EPROTO; return -EPROTO;
} }
if (!verify_perms(&rules->policy)) { if (!verify_perms(rules->policy)) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: Invalid perm index", NULL, -EPROTO); "Unpack: Invalid perm index", NULL, -EPROTO);
return -EPROTO; return -EPROTO;
} }
if (!verify_perms(&profile->attach.xmatch)) { if (!verify_perms(profile->attach.xmatch)) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: Invalid perm index", NULL, -EPROTO); "Unpack: Invalid perm index", NULL, -EPROTO);
return -EPROTO; return -EPROTO;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment