Commit 217af7e2 authored by John Johansen's avatar John Johansen

apparmor: refactor profile rules and attachments

In preparation for moving from a single set of rules and a single
attachment to multiple rulesets and attachments separate from the
profile refactor attachment information and ruleset info into their
own structures.
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 3bf3d728
...@@ -611,30 +611,29 @@ static const struct file_operations aa_fs_ns_revision_fops = { ...@@ -611,30 +611,29 @@ static const struct file_operations aa_fs_ns_revision_fops = {
static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
const char *match_str, size_t match_len) const char *match_str, size_t match_len)
{ {
struct aa_ruleset *rules = &profile->rules;
struct aa_perms tmp = { }; struct aa_perms tmp = { };
struct aa_dfa *dfa;
aa_state_t state = DFA_NOMATCH; aa_state_t state = DFA_NOMATCH;
if (profile_unconfined(profile)) if (profile_unconfined(profile))
return; return;
if (profile->file.dfa && *match_str == AA_CLASS_FILE) { if (rules->file.dfa && *match_str == AA_CLASS_FILE) {
dfa = profile->file.dfa; state = aa_dfa_match_len(rules->file.dfa,
state = aa_dfa_match_len(dfa, rules->file.start[AA_CLASS_FILE],
profile->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(&(profile->file), state, &cond)); tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
} }
} else if (profile->policy.dfa) { } else if (rules->policy.dfa) {
if (!PROFILE_MEDIATES(profile, *match_str)) if (!RULE_MEDIATES(rules, *match_str))
return; /* no change to current perms */ return; /* no change to current perms */
dfa = profile->policy.dfa; state = aa_dfa_match_len(rules->policy.dfa,
state = aa_dfa_match_len(dfa, profile->policy.start[0], rules->policy.start[0],
match_str, match_len); match_str, match_len);
if (state) if (state)
tmp = *aa_lookup_perms(&profile->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);
...@@ -1093,9 +1092,9 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v) ...@@ -1093,9 +1092,9 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
struct aa_proxy *proxy = seq->private; struct aa_proxy *proxy = seq->private;
struct aa_label *label = aa_get_label_rcu(&proxy->label); struct aa_label *label = aa_get_label_rcu(&proxy->label);
struct aa_profile *profile = labels_profile(label); struct aa_profile *profile = labels_profile(label);
if (profile->attach) if (profile->attach.xmatch_str)
seq_printf(seq, "%s\n", profile->attach); seq_printf(seq, "%s\n", profile->attach.xmatch_str);
else if (profile->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);
......
...@@ -64,6 +64,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) ...@@ -64,6 +64,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
int cap, int error) int cap, int error)
{ {
struct aa_ruleset *rules = &profile->rules;
struct audit_cache *ent; struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
...@@ -72,13 +73,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, ...@@ -72,13 +73,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
if (likely(!error)) { if (likely(!error)) {
/* test if auditing is being forced */ /* test if auditing is being forced */
if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
!cap_raised(profile->caps.audit, cap))) !cap_raised(rules->caps.audit, cap)))
return 0; return 0;
type = AUDIT_APPARMOR_AUDIT; type = AUDIT_APPARMOR_AUDIT;
} else if (KILL_MODE(profile) || } else if (KILL_MODE(profile) ||
cap_raised(profile->caps.kill, cap)) { cap_raised(rules->caps.kill, cap)) {
type = AUDIT_APPARMOR_KILL; type = AUDIT_APPARMOR_KILL;
} else if (cap_raised(profile->caps.quiet, cap) && } else if (cap_raised(rules->caps.quiet, cap) &&
AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL) { AUDIT_MODE(profile) != AUDIT_ALL) {
/* quiet auditing */ /* quiet auditing */
...@@ -114,10 +115,11 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, ...@@ -114,10 +115,11 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
static int profile_capable(struct aa_profile *profile, int cap, static int profile_capable(struct aa_profile *profile, int cap,
unsigned int opts, struct common_audit_data *sa) unsigned int opts, struct common_audit_data *sa)
{ {
struct aa_ruleset *rules = &profile->rules;
int error; int error;
if (cap_raised(profile->caps.allow, cap) && if (cap_raised(rules->caps.allow, cap) &&
!cap_raised(profile->caps.denied, cap)) !cap_raised(rules->caps.denied, cap))
error = 0; error = 0;
else else
error = -EPERM; error = -EPERM;
......
This diff is collapsed.
...@@ -224,11 +224,12 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, ...@@ -224,11 +224,12 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name,
u32 request, struct path_cond *cond, int flags, u32 request, struct path_cond *cond, int flags,
struct aa_perms *perms) struct aa_perms *perms)
{ {
struct aa_ruleset *rules = &profile->rules;
int e = 0; int e = 0;
if (profile_unconfined(profile)) if (profile_unconfined(profile))
return 0; return 0;
aa_str_perms(&(profile->file), profile->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;
...@@ -316,6 +317,7 @@ static int profile_path_link(struct aa_profile *profile, ...@@ -316,6 +317,7 @@ static int profile_path_link(struct aa_profile *profile,
const struct path *target, char *buffer2, const struct path *target, char *buffer2,
struct path_cond *cond) struct path_cond *cond)
{ {
struct aa_ruleset *rules = &profile->rules;
const char *lname, *tname = NULL; const char *lname, *tname = NULL;
struct aa_perms lperms = {}, perms; struct aa_perms lperms = {}, perms;
const char *info = NULL; const char *info = NULL;
...@@ -336,16 +338,16 @@ static int profile_path_link(struct aa_profile *profile, ...@@ -336,16 +338,16 @@ static int profile_path_link(struct aa_profile *profile,
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(&(profile->file), state = aa_str_perms(&(rules->file),
profile->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(profile->file.dfa, state); state = aa_dfa_null_transition(rules->file.dfa, state);
aa_str_perms(&(profile->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.
...@@ -367,7 +369,7 @@ static int profile_path_link(struct aa_profile *profile, ...@@ -367,7 +369,7 @@ static int profile_path_link(struct aa_profile *profile,
/* 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(&(profile->file), profile->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 */
......
...@@ -261,7 +261,7 @@ for ((I).i = (I).j = 0; \ ...@@ -261,7 +261,7 @@ for ((I).i = (I).j = 0; \
struct label_it i; \ struct label_it i; \
int ret = 0; \ int ret = 0; \
label_for_each(i, (L), profile) { \ label_for_each(i, (L), profile) { \
if (PROFILE_MEDIATES(profile, (C))) { \ if (RULE_MEDIATES(&profile->rules, (C))) { \
ret = 1; \ ret = 1; \
break; \ break; \
} \ } \
...@@ -357,9 +357,10 @@ static inline const char *aa_label_str_split(const char *str) ...@@ -357,9 +357,10 @@ static inline const char *aa_label_str_split(const char *str)
struct aa_perms; struct aa_perms;
int aa_label_match(struct aa_profile *profile, struct aa_label *label, struct aa_ruleset;
aa_state_t state, bool subns, u32 request, int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules,
struct aa_perms *perms); struct aa_label *label, aa_state_t state, bool subns,
u32 request, struct aa_perms *perms);
/** /**
......
...@@ -207,7 +207,8 @@ void aa_apply_modes_to_perms(struct aa_profile *profile, ...@@ -207,7 +207,8 @@ void aa_apply_modes_to_perms(struct aa_profile *profile,
struct aa_perms *perms); struct aa_perms *perms);
void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend); void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend);
void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend); void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend);
void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, void aa_profile_match_label(struct aa_profile *profile,
struct aa_ruleset *rules, struct aa_label *label,
int type, u32 request, struct aa_perms *perms); int type, u32 request, struct aa_perms *perms);
int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
u32 request, int type, u32 *deny, u32 request, int type, u32 *deny,
......
...@@ -123,6 +123,43 @@ struct aa_data { ...@@ -123,6 +123,43 @@ struct aa_data {
struct rhash_head head; struct rhash_head head;
}; };
/* struct aa_ruleset - data covering mediation rules
* @size: the memory consumed by this ruleset
* @policy: general match rules governing policy
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
* @rlimits: rlimits for the profile
* @secmark_count: number of secmark entries
* @secmark: secmark label match info
*/
struct aa_ruleset {
int size;
/* TODO: merge policy and file */
struct aa_policydb policy;
struct aa_policydb file;
struct aa_caps caps;
struct aa_rlimit rlimits;
int secmark_count;
struct aa_secmark *secmark;
};
/* struct aa_attachment - data and rules for a profiles attachment
* @xmatch_str: human readable attachment string
* @xmatch: optional extended matching for unconfined executables names
* @xmatch_len: xmatch prefix len, used to determine xmatch priority
* @xattr_count: number of xattrs in table
* @xattrs: table of xattrs
*/
struct aa_attachment {
const char *xmatch_str;
struct aa_policydb xmatch;
unsigned int xmatch_len;
int xattr_count;
char **xattrs;
};
/* struct aa_profile - basic confinement data /* struct aa_profile - basic confinement data
* @base - base components of the profile (name, refcount, lists, lock ...) * @base - base components of the profile (name, refcount, lists, lock ...)
...@@ -130,18 +167,13 @@ struct aa_data { ...@@ -130,18 +167,13 @@ struct aa_data {
* @parent: parent of profile * @parent: parent of profile
* @ns: namespace the profile is in * @ns: namespace the profile is in
* @rename: optional profile name that this profile renamed * @rename: optional profile name that this profile renamed
* @attach: human readable attachment string *
* @xmatch: optional extended matching for unconfined executables names
* @xmatch_len: xmatch prefix len, used to determine xmatch priority
* @audit: the auditing mode of the profile * @audit: the auditing mode of the profile
* @mode: the enforcement mode of the profile * @mode: the enforcement mode of the profile
* @path_flags: flags controlling path generation behavior * @path_flags: flags controlling path generation behavior
* @disconnected: what to prepend if attach_disconnected is specified * @disconnected: what to prepend if attach_disconnected is specified
* @size: the memory consumed by this profiles rules * @attach: attachment rules for the profile
* @policy: general match rules governing policy * @rules: rules to be enforced
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
* @rlimits: rlimits for the profile
* *
* @dents: dentries for the profiles file entries in apparmorfs * @dents: dentries for the profiles file entries in apparmorfs
* @dirname: name of the profile dir in apparmorfs * @dirname: name of the profile dir in apparmorfs
...@@ -166,27 +198,13 @@ struct aa_profile { ...@@ -166,27 +198,13 @@ struct aa_profile {
struct aa_ns *ns; struct aa_ns *ns;
const char *rename; const char *rename;
const char *attach;
struct aa_policydb xmatch;
unsigned int xmatch_len;
enum audit_mode audit; enum audit_mode audit;
long mode; long mode;
u32 path_flags; u32 path_flags;
const char *disconnected; const char *disconnected;
int size;
struct aa_policydb policy; struct aa_attachment attach;
struct aa_policydb file; struct aa_ruleset rules;
struct aa_caps caps;
int xattr_count;
char **xattrs;
struct aa_rlimit rlimits;
int secmark_count;
struct aa_secmark *secmark;
struct aa_loaddata *rawdata; struct aa_loaddata *rawdata;
unsigned char *hash; unsigned char *hash;
...@@ -247,24 +265,24 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) ...@@ -247,24 +265,24 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
return labels_profile(aa_get_newest_label(&p->label)); return labels_profile(aa_get_newest_label(&p->label));
} }
static inline aa_state_t PROFILE_MEDIATES(struct aa_profile *profile, 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 profile->policy.start[class]; return rules->policy.start[class];
else else
return aa_dfa_match_len(profile->policy.dfa, return aa_dfa_match_len(rules->policy.dfa,
profile->policy.start[0], &class, 1); rules->policy.start[0], &class, 1);
} }
static inline aa_state_t PROFILE_MEDIATES_AF(struct aa_profile *profile, static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)
u16 AF) { {
aa_state_t state = PROFILE_MEDIATES(profile, AA_CLASS_NET); aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NET);
__be16 be_af = cpu_to_be16(AF); __be16 be_af = cpu_to_be16(AF);
if (!state) if (!state)
return DFA_NOMATCH; return DFA_NOMATCH;
return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2);
} }
/** /**
......
...@@ -78,19 +78,20 @@ static int profile_signal_perm(struct aa_profile *profile, ...@@ -78,19 +78,20 @@ static int profile_signal_perm(struct aa_profile *profile,
struct aa_label *peer, u32 request, struct aa_label *peer, u32 request,
struct common_audit_data *sa) struct common_audit_data *sa)
{ {
struct aa_ruleset *rules = &profile->rules;
struct aa_perms perms; struct aa_perms perms;
aa_state_t state; aa_state_t state;
if (profile_unconfined(profile) || if (profile_unconfined(profile) ||
!PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL)) !RULE_MEDIATES(rules, AA_CLASS_SIGNAL))
return 0; return 0;
aad(sa)->peer = peer; aad(sa)->peer = peer;
/* TODO: secondary cache check <profile, profile, perm> */ /* TODO: secondary cache check <profile, profile, perm> */
state = aa_dfa_next(profile->policy.dfa, state = aa_dfa_next(rules->policy.dfa,
profile->policy.start[AA_CLASS_SIGNAL], rules->policy.start[AA_CLASS_SIGNAL],
aad(sa)->signal); aad(sa)->signal);
aa_label_match(profile, 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);
return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); return aa_check_perms(profile, &perms, request, sa, audit_signal_cb);
} }
......
...@@ -1266,20 +1266,21 @@ static inline bool label_is_visible(struct aa_profile *profile, ...@@ -1266,20 +1266,21 @@ static inline bool label_is_visible(struct aa_profile *profile,
* visibility test. * visibility test.
*/ */
static inline aa_state_t match_component(struct aa_profile *profile, static inline aa_state_t match_component(struct aa_profile *profile,
struct aa_ruleset *rules,
struct aa_profile *tp, struct aa_profile *tp,
aa_state_t state) aa_state_t state)
{ {
const char *ns_name; const char *ns_name;
if (profile->ns == tp->ns) if (profile->ns == tp->ns)
return aa_dfa_match(profile->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(profile->policy.dfa, state, ":", 1); state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1);
state = aa_dfa_match(profile->policy.dfa, state, ns_name); state = aa_dfa_match(rules->policy.dfa, state, ns_name);
state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1);
return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); return aa_dfa_match(rules->policy.dfa, state, tp->base.hname);
} }
/** /**
...@@ -1298,6 +1299,7 @@ static inline aa_state_t match_component(struct aa_profile *profile, ...@@ -1298,6 +1299,7 @@ static inline aa_state_t match_component(struct aa_profile *profile,
* check to be stacked. * check to be stacked.
*/ */
static int label_compound_match(struct aa_profile *profile, static int label_compound_match(struct aa_profile *profile,
struct aa_ruleset *rules,
struct aa_label *label, struct aa_label *label,
aa_state_t state, bool subns, u32 request, aa_state_t state, bool subns, u32 request,
struct aa_perms *perms) struct aa_perms *perms)
...@@ -1309,7 +1311,7 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -1309,7 +1311,7 @@ static int label_compound_match(struct aa_profile *profile,
label_for_each(i, label, tp) { label_for_each(i, label, tp) {
if (!aa_ns_visible(profile->ns, tp->ns, subns)) if (!aa_ns_visible(profile->ns, tp->ns, subns))
continue; continue;
state = match_component(profile, tp, state); state = match_component(profile, rules, tp, state);
if (!state) if (!state)
goto fail; goto fail;
goto next; goto next;
...@@ -1323,12 +1325,12 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -1323,12 +1325,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(profile->policy.dfa, state, "//&"); state = aa_dfa_match(rules->policy.dfa, state, "//&");
state = match_component(profile, tp, state); state = match_component(profile, rules, tp, state);
if (!state) if (!state)
goto fail; goto fail;
} }
*perms = *aa_lookup_perms(&profile->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;
...@@ -1343,6 +1345,7 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -1343,6 +1345,7 @@ static int label_compound_match(struct aa_profile *profile,
/** /**
* label_components_match - find perms for all subcomponents of a label * label_components_match - find perms for all subcomponents of a label
* @profile: profile to find perms for * @profile: profile to find perms for
* @rules: ruleset to search
* @label: label to check access permissions for * @label: label to check access permissions for
* @start: state to start match in * @start: state to start match in
* @subns: whether to do permission checks on components in a subns * @subns: whether to do permission checks on components in a subns
...@@ -1356,6 +1359,7 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -1356,6 +1359,7 @@ static int label_compound_match(struct aa_profile *profile,
* check to be stacked. * check to be stacked.
*/ */
static int label_components_match(struct aa_profile *profile, static int label_components_match(struct aa_profile *profile,
struct aa_ruleset *rules,
struct aa_label *label, aa_state_t start, struct aa_label *label, aa_state_t start,
bool subns, u32 request, bool subns, u32 request,
struct aa_perms *perms) struct aa_perms *perms)
...@@ -1369,7 +1373,7 @@ static int label_components_match(struct aa_profile *profile, ...@@ -1369,7 +1373,7 @@ static int label_components_match(struct aa_profile *profile,
label_for_each(i, label, tp) { label_for_each(i, label, tp) {
if (!aa_ns_visible(profile->ns, tp->ns, subns)) if (!aa_ns_visible(profile->ns, tp->ns, subns))
continue; continue;
state = match_component(profile, tp, start); state = match_component(profile, rules, tp, start);
if (!state) if (!state)
goto fail; goto fail;
goto next; goto next;
...@@ -1379,16 +1383,16 @@ static int label_components_match(struct aa_profile *profile, ...@@ -1379,16 +1383,16 @@ static int label_components_match(struct aa_profile *profile,
return 0; return 0;
next: next:
tmp = *aa_lookup_perms(&profile->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) {
if (!aa_ns_visible(profile->ns, tp->ns, subns)) if (!aa_ns_visible(profile->ns, tp->ns, subns))
continue; continue;
state = match_component(profile, tp, start); state = match_component(profile, rules, tp, start);
if (!state) if (!state)
goto fail; goto fail;
tmp = *aa_lookup_perms(&profile->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);
} }
...@@ -1406,6 +1410,7 @@ static int label_components_match(struct aa_profile *profile, ...@@ -1406,6 +1410,7 @@ static int label_components_match(struct aa_profile *profile,
/** /**
* aa_label_match - do a multi-component label match * aa_label_match - do a multi-component label match
* @profile: profile to match against (NOT NULL) * @profile: profile to match against (NOT NULL)
* @rules: ruleset to search
* @label: label to match (NOT NULL) * @label: label to match (NOT NULL)
* @state: state to start in * @state: state to start in
* @subns: whether to match subns components * @subns: whether to match subns components
...@@ -1414,18 +1419,18 @@ static int label_components_match(struct aa_profile *profile, ...@@ -1414,18 +1419,18 @@ static int label_components_match(struct aa_profile *profile,
* *
* Returns: the state the match finished in, may be the none matching state * Returns: the state the match finished in, may be the none matching state
*/ */
int aa_label_match(struct aa_profile *profile, struct aa_label *label, int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules,
aa_state_t state, bool subns, u32 request, struct aa_label *label, aa_state_t state, bool subns,
struct aa_perms *perms) u32 request, struct aa_perms *perms)
{ {
int error = label_compound_match(profile, label, state, subns, request, int error = label_compound_match(profile, rules, label, state, subns,
perms); request, perms);
if (!error) if (!error)
return error; return error;
*perms = allperms; *perms = allperms;
return label_components_match(profile, label, state, subns, request, return label_components_match(profile, rules, label, state, subns,
perms); request, perms);
} }
......
...@@ -331,16 +331,18 @@ void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) ...@@ -331,16 +331,18 @@ void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
perms->prompt = ALL_PERMS_MASK; perms->prompt = ALL_PERMS_MASK;
} }
void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, void aa_profile_match_label(struct aa_profile *profile,
struct aa_ruleset *rules,
struct aa_label *label,
int type, u32 request, struct aa_perms *perms) int type, u32 request, struct aa_perms *perms)
{ {
/* 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(profile->policy.dfa, state = aa_dfa_next(rules->policy.dfa,
profile->policy.start[AA_CLASS_LABEL], rules->policy.start[AA_CLASS_LABEL],
type); type);
aa_label_match(profile, label, state, false, request, perms); aa_label_match(profile, rules, label, state, false, request, perms);
} }
...@@ -355,7 +357,8 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, ...@@ -355,7 +357,8 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
aad(sa)->peer = &target->label; aad(sa)->peer = &target->label;
aad(sa)->request = request; aad(sa)->request = request;
aa_profile_match_label(profile, &target->label, type, request, &perms); aa_profile_match_label(profile, &profile->rules, &target->label, type,
request, &perms);
aa_apply_modes_to_perms(profile, &perms); aa_apply_modes_to_perms(profile, &perms);
*deny |= request & perms.deny; *deny |= request & perms.deny;
return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
......
...@@ -166,9 +166,9 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, ...@@ -166,9 +166,9 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
if (COMPLAIN_MODE(profile)) if (COMPLAIN_MODE(profile))
continue; continue;
*effective = cap_intersect(*effective, *effective = cap_intersect(*effective,
profile->caps.allow); profile->rules.caps.allow);
*permitted = cap_intersect(*permitted, *permitted = cap_intersect(*permitted,
profile->caps.allow); profile->rules.caps.allow);
} }
} }
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -303,13 +303,14 @@ static int match_mnt_path_str(struct aa_profile *profile, ...@@ -303,13 +303,14 @@ static int match_mnt_path_str(struct aa_profile *profile,
{ {
struct aa_perms perms = { }; struct aa_perms perms = { };
const char *mntpnt = NULL, *info = NULL; const char *mntpnt = NULL, *info = NULL;
struct aa_ruleset *rules = &profile->rules;
int pos, error; int pos, error;
AA_BUG(!profile); AA_BUG(!profile);
AA_BUG(!mntpath); AA_BUG(!mntpath);
AA_BUG(!buffer); AA_BUG(!buffer);
if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return 0; return 0;
error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer, error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
...@@ -324,8 +325,8 @@ static int match_mnt_path_str(struct aa_profile *profile, ...@@ -324,8 +325,8 @@ static int match_mnt_path_str(struct aa_profile *profile,
} }
error = -EACCES; error = -EACCES;
pos = do_match_mnt(&profile->policy, pos = do_match_mnt(&rules->policy,
profile->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];
...@@ -363,7 +364,7 @@ static int match_mnt(struct aa_profile *profile, const struct path *path, ...@@ -363,7 +364,7 @@ static int match_mnt(struct aa_profile *profile, const struct path *path,
AA_BUG(!profile); AA_BUG(!profile);
AA_BUG(devpath && !devbuffer); AA_BUG(devpath && !devbuffer);
if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) if (!RULE_MEDIATES(&profile->rules, AA_CLASS_MOUNT))
return 0; return 0;
if (devpath) { if (devpath) {
...@@ -565,6 +566,7 @@ int aa_new_mount(struct aa_label *label, const char *dev_name, ...@@ -565,6 +566,7 @@ int aa_new_mount(struct aa_label *label, const char *dev_name,
static int profile_umount(struct aa_profile *profile, const struct path *path, static int profile_umount(struct aa_profile *profile, const struct path *path,
char *buffer) char *buffer)
{ {
struct aa_ruleset *rules = &profile->rules;
struct aa_perms perms = { }; struct aa_perms perms = { };
const char *name = NULL, *info = NULL; const char *name = NULL, *info = NULL;
aa_state_t state; aa_state_t state;
...@@ -573,7 +575,7 @@ static int profile_umount(struct aa_profile *profile, const struct path *path, ...@@ -573,7 +575,7 @@ static int profile_umount(struct aa_profile *profile, const struct path *path,
AA_BUG(!profile); AA_BUG(!profile);
AA_BUG(!path); AA_BUG(!path);
if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return 0; return 0;
error = aa_path_name(path, path_flags(profile, path), buffer, &name, error = aa_path_name(path, path_flags(profile, path), buffer, &name,
...@@ -581,10 +583,10 @@ static int profile_umount(struct aa_profile *profile, const struct path *path, ...@@ -581,10 +583,10 @@ static int profile_umount(struct aa_profile *profile, const struct path *path,
if (error) if (error)
goto audit; goto audit;
state = aa_dfa_match(profile->policy.dfa, state = aa_dfa_match(rules->policy.dfa,
profile->policy.start[AA_CLASS_MOUNT], rules->policy.start[AA_CLASS_MOUNT],
name); name);
perms = *aa_lookup_perms(&profile->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;
...@@ -624,6 +626,7 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile, ...@@ -624,6 +626,7 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile,
const struct path *old_path, const struct path *old_path,
char *old_buffer) char *old_buffer)
{ {
struct aa_ruleset *rules = &profile->rules;
const char *old_name, *new_name = NULL, *info = NULL; const char *old_name, *new_name = NULL, *info = NULL;
const char *trans_name = NULL; const char *trans_name = NULL;
struct aa_perms perms = { }; struct aa_perms perms = { };
...@@ -635,7 +638,7 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile, ...@@ -635,7 +638,7 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile,
AA_BUG(!old_path); AA_BUG(!old_path);
if (profile_unconfined(profile) || if (profile_unconfined(profile) ||
!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) !RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return aa_get_newest_label(&profile->label); return aa_get_newest_label(&profile->label);
error = aa_path_name(old_path, path_flags(profile, old_path), error = aa_path_name(old_path, path_flags(profile, old_path),
...@@ -650,12 +653,12 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile, ...@@ -650,12 +653,12 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile,
goto audit; goto audit;
error = -EACCES; error = -EACCES;
state = aa_dfa_match(profile->policy.dfa, state = aa_dfa_match(rules->policy.dfa,
profile->policy.start[AA_CLASS_MOUNT], rules->policy.start[AA_CLASS_MOUNT],
new_name); new_name);
state = aa_dfa_null_transition(profile->policy.dfa, state); state = aa_dfa_null_transition(rules->policy.dfa, state);
state = aa_dfa_match(profile->policy.dfa, state, old_name); state = aa_dfa_match(rules->policy.dfa, state, old_name);
perms = *aa_lookup_perms(&profile->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;
......
...@@ -108,6 +108,7 @@ void audit_net_cb(struct audit_buffer *ab, void *va) ...@@ -108,6 +108,7 @@ void audit_net_cb(struct audit_buffer *ab, void *va)
int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
u32 request, u16 family, int type) u32 request, u16 family, int type)
{ {
struct aa_ruleset *rules = &profile->rules;
struct aa_perms perms = { }; struct aa_perms perms = { };
aa_state_t state; aa_state_t state;
__be16 buffer[2]; __be16 buffer[2];
...@@ -117,15 +118,15 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, ...@@ -117,15 +118,15 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
if (profile_unconfined(profile)) if (profile_unconfined(profile))
return 0; return 0;
state = PROFILE_MEDIATES(profile, AA_CLASS_NET); state = RULE_MEDIATES(rules, AA_CLASS_NET);
if (!state) if (!state)
return 0; return 0;
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(profile->policy.dfa, state, (char *) &buffer, state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer,
4); 4);
perms = *aa_lookup_perms(&profile->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, sa, audit_net_cb); return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
...@@ -216,25 +217,26 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, ...@@ -216,25 +217,26 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid,
{ {
int i, ret; int i, ret;
struct aa_perms perms = { }; struct aa_perms perms = { };
struct aa_ruleset *rules = &profile->rules;
if (profile->secmark_count == 0) if (rules->secmark_count == 0)
return 0; return 0;
for (i = 0; i < profile->secmark_count; i++) { for (i = 0; i < rules->secmark_count; i++) {
if (!profile->secmark[i].secid) { if (!rules->secmark[i].secid) {
ret = apparmor_secmark_init(&profile->secmark[i]); ret = apparmor_secmark_init(&rules->secmark[i]);
if (ret) if (ret)
return ret; return ret;
} }
if (profile->secmark[i].secid == secid || if (rules->secmark[i].secid == secid ||
profile->secmark[i].secid == AA_SECID_WILDCARD) { rules->secmark[i].secid == AA_SECID_WILDCARD) {
if (profile->secmark[i].deny) if (rules->secmark[i].deny)
perms.deny = ALL_PERMS_MASK; perms.deny = ALL_PERMS_MASK;
else else
perms.allow = ALL_PERMS_MASK; perms.allow = ALL_PERMS_MASK;
if (profile->secmark[i].audit) if (rules->secmark[i].audit)
perms.audit = ALL_PERMS_MASK; perms.audit = ALL_PERMS_MASK;
} }
} }
......
...@@ -193,6 +193,30 @@ static void aa_free_data(void *ptr, void *arg) ...@@ -193,6 +193,30 @@ static void aa_free_data(void *ptr, void *arg)
kfree_sensitive(data); kfree_sensitive(data);
} }
static void free_attachment(struct aa_attachment *attach)
{
int i;
for (i = 0; i < attach->xattr_count; i++)
kfree_sensitive(attach->xattrs[i]);
kfree_sensitive(attach->xattrs);
aa_destroy_policydb(&attach->xmatch);
}
static void free_ruleset(struct aa_ruleset *rules)
{
int i;
aa_destroy_policydb(&rules->file);
aa_destroy_policydb(&rules->policy);
aa_free_cap_rules(&rules->caps);
aa_free_rlimit_rules(&rules->rlimits);
for (i = 0; i < rules->secmark_count; i++)
kfree_sensitive(rules->secmark[i].label);
kfree_sensitive(rules->secmark);
}
/** /**
* aa_free_profile - free a profile * aa_free_profile - free a profile
* @profile: the profile to free (MAYBE NULL) * @profile: the profile to free (MAYBE NULL)
...@@ -206,7 +230,6 @@ static void aa_free_data(void *ptr, void *arg) ...@@ -206,7 +230,6 @@ static void aa_free_data(void *ptr, void *arg)
void aa_free_profile(struct aa_profile *profile) void aa_free_profile(struct aa_profile *profile)
{ {
struct rhashtable *rht; struct rhashtable *rht;
int i;
AA_DEBUG("%s(%p)\n", __func__, profile); AA_DEBUG("%s(%p)\n", __func__, profile);
...@@ -220,19 +243,10 @@ void aa_free_profile(struct aa_profile *profile) ...@@ -220,19 +243,10 @@ void aa_free_profile(struct aa_profile *profile)
aa_put_ns(profile->ns); aa_put_ns(profile->ns);
kfree_sensitive(profile->rename); kfree_sensitive(profile->rename);
aa_destroy_policydb(&profile->file); free_attachment(&profile->attach);
aa_free_cap_rules(&profile->caps); free_ruleset(&profile->rules);
aa_free_rlimit_rules(&profile->rlimits);
for (i = 0; i < profile->xattr_count; i++)
kfree_sensitive(profile->xattrs[i]);
kfree_sensitive(profile->xattrs);
for (i = 0; i < profile->secmark_count; i++)
kfree_sensitive(profile->secmark[i].label);
kfree_sensitive(profile->secmark);
kfree_sensitive(profile->dirname); kfree_sensitive(profile->dirname);
aa_destroy_policydb(&profile->xmatch);
aa_destroy_policydb(&profile->policy);
if (profile->data) { if (profile->data) {
rht = profile->data; rht = profile->data;
profile->data = NULL; profile->data = NULL;
...@@ -544,8 +558,8 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, ...@@ -544,8 +558,8 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
/* released on free_profile */ /* released on free_profile */
rcu_assign_pointer(profile->parent, aa_get_profile(parent)); rcu_assign_pointer(profile->parent, aa_get_profile(parent));
profile->ns = aa_get_ns(parent->ns); profile->ns = aa_get_ns(parent->ns);
profile->file.dfa = aa_get_dfa(nulldfa); profile->rules.file.dfa = aa_get_dfa(nulldfa);
profile->policy.dfa = aa_get_dfa(nulldfa); profile->rules.policy.dfa = aa_get_dfa(nulldfa);
mutex_lock_nested(&profile->ns->lock, profile->ns->level); mutex_lock_nested(&profile->ns->lock, profile->ns->level);
p = __find_child(&parent->base.profiles, bname); p = __find_child(&parent->base.profiles, bname);
......
...@@ -91,8 +91,8 @@ static struct aa_profile *alloc_unconfined(const char *name) ...@@ -91,8 +91,8 @@ static struct aa_profile *alloc_unconfined(const char *name)
profile->label.flags |= FLAG_IX_ON_NAME_ERROR | profile->label.flags |= FLAG_IX_ON_NAME_ERROR |
FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED;
profile->mode = APPARMOR_UNCONFINED; profile->mode = APPARMOR_UNCONFINED;
profile->file.dfa = aa_get_dfa(nulldfa); profile->rules.file.dfa = aa_get_dfa(nulldfa);
profile->policy.dfa = aa_get_dfa(nulldfa); profile->rules.policy.dfa = aa_get_dfa(nulldfa);
return profile; return profile;
} }
......
...@@ -556,12 +556,12 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile) ...@@ -556,12 +556,12 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile)
if (unpack_array(e, NULL, &size) != TRI_TRUE) if (unpack_array(e, NULL, &size) != TRI_TRUE)
goto fail; goto fail;
profile->xattr_count = size; profile->attach.xattr_count = size;
profile->xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL); profile->attach.xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL);
if (!profile->xattrs) if (!profile->attach.xattrs)
goto fail; goto fail;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
if (!unpack_strdup(e, &profile->xattrs[i], NULL)) if (!unpack_strdup(e, &profile->attach.xattrs[i], NULL))
goto fail; goto fail;
} }
if (!unpack_nameX(e, AA_ARRAYEND, NULL)) if (!unpack_nameX(e, AA_ARRAYEND, NULL))
...@@ -579,6 +579,7 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile) ...@@ -579,6 +579,7 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile)
static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
{ {
struct aa_ruleset *rules = &profile->rules;
void *pos = e->pos; void *pos = e->pos;
u16 size; u16 size;
int i; int i;
...@@ -587,19 +588,19 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) ...@@ -587,19 +588,19 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
if (unpack_array(e, NULL, &size) != TRI_TRUE) if (unpack_array(e, NULL, &size) != TRI_TRUE)
goto fail; goto fail;
profile->secmark = kcalloc(size, sizeof(struct aa_secmark), rules->secmark = kcalloc(size, sizeof(struct aa_secmark),
GFP_KERNEL); GFP_KERNEL);
if (!profile->secmark) if (!rules->secmark)
goto fail; goto fail;
profile->secmark_count = size; rules->secmark_count = size;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
if (!unpack_u8(e, &profile->secmark[i].audit, NULL)) if (!unpack_u8(e, &rules->secmark[i].audit, NULL))
goto fail; goto fail;
if (!unpack_u8(e, &profile->secmark[i].deny, NULL)) if (!unpack_u8(e, &rules->secmark[i].deny, NULL))
goto fail; goto fail;
if (!unpack_strdup(e, &profile->secmark[i].label, NULL)) if (!unpack_strdup(e, &rules->secmark[i].label, NULL))
goto fail; goto fail;
} }
if (!unpack_nameX(e, AA_ARRAYEND, NULL)) if (!unpack_nameX(e, AA_ARRAYEND, NULL))
...@@ -611,12 +612,12 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) ...@@ -611,12 +612,12 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
return true; return true;
fail: fail:
if (profile->secmark) { if (rules->secmark) {
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
kfree(profile->secmark[i].label); kfree(rules->secmark[i].label);
kfree(profile->secmark); kfree(rules->secmark);
profile->secmark_count = 0; rules->secmark_count = 0;
profile->secmark = NULL; rules->secmark = NULL;
} }
e->pos = pos; e->pos = pos;
...@@ -634,7 +635,7 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) ...@@ -634,7 +635,7 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
u32 tmp = 0; u32 tmp = 0;
if (!unpack_u32(e, &tmp, NULL)) if (!unpack_u32(e, &tmp, NULL))
goto fail; goto fail;
profile->rlimits.mask = tmp; profile->rules.rlimits.mask = tmp;
if (unpack_array(e, NULL, &size) != TRI_TRUE || if (unpack_array(e, NULL, &size) != TRI_TRUE ||
size > RLIM_NLIMITS) size > RLIM_NLIMITS)
...@@ -644,7 +645,7 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) ...@@ -644,7 +645,7 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
int a = aa_map_resource(i); int a = aa_map_resource(i);
if (!unpack_u64(e, &tmp2, NULL)) if (!unpack_u64(e, &tmp2, NULL))
goto fail; goto fail;
profile->rlimits.limits[a].rlim_max = tmp2; profile->rules.rlimits.limits[a].rlim_max = tmp2;
} }
if (!unpack_nameX(e, AA_ARRAYEND, NULL)) if (!unpack_nameX(e, AA_ARRAYEND, NULL))
goto fail; goto fail;
...@@ -816,6 +817,7 @@ static int datacmp(struct rhashtable_compare_arg *arg, const void *obj) ...@@ -816,6 +817,7 @@ static int datacmp(struct rhashtable_compare_arg *arg, const void *obj)
*/ */
static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
{ {
struct aa_ruleset *rules;
struct aa_profile *profile = NULL; struct aa_profile *profile = NULL;
const char *tmpname, *tmpns = NULL, *name = NULL; const char *tmpname, *tmpns = NULL, *name = NULL;
const char *info = "failed to unpack profile"; const char *info = "failed to unpack profile";
...@@ -850,27 +852,30 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -850,27 +852,30 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
profile = aa_alloc_profile(name, NULL, GFP_KERNEL); profile = aa_alloc_profile(name, NULL, GFP_KERNEL);
if (!profile) if (!profile)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
rules = &profile->rules;
/* profile renaming is optional */ /* profile renaming is optional */
(void) unpack_str(e, &profile->rename, "rename"); (void) unpack_str(e, &profile->rename, "rename");
/* attachment string is optional */ /* attachment string is optional */
(void) unpack_str(e, &profile->attach, "attach"); (void) unpack_str(e, &profile->attach.xmatch_str, "attach");
/* xmatch is optional and may be NULL */ /* xmatch is optional and may be NULL */
error = unpack_pdb(e, &profile->xmatch, false, false, &info); error = unpack_pdb(e, &profile->attach.xmatch, false, false, &info);
if (error) if (error) {
info = "bad xmatch";
goto fail; goto fail;
}
/* 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->xmatch.dfa) { if (profile->attach.xmatch.dfa) {
if (!unpack_u32(e, &tmp, NULL)) { if (!unpack_u32(e, &tmp, NULL)) {
info = "missing xmatch len"; info = "missing xmatch len";
goto fail; goto fail;
} }
profile->xmatch_len = tmp; profile->attach.xmatch_len = tmp;
profile->xmatch.start[AA_CLASS_XMATCH] = DFA_START; profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START;
if (aa_compat_map_xmatch(&profile->xmatch)) { if (aa_compat_map_xmatch(&profile->attach.xmatch)) {
info = "failed to convert xmatch permission table"; info = "failed to convert xmatch permission table";
goto fail; goto fail;
} }
...@@ -926,11 +931,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -926,11 +931,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
profile->path_flags = PATH_MEDIATE_DELETED; profile->path_flags = PATH_MEDIATE_DELETED;
info = "failed to unpack profile capabilities"; info = "failed to unpack profile capabilities";
if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) if (!unpack_u32(e, &(rules->caps.allow.cap[0]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) if (!unpack_u32(e, &(rules->caps.audit.cap[0]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL)) if (!unpack_u32(e, &(rules->caps.quiet.cap[0]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &tmpcap.cap[0], NULL)) if (!unpack_u32(e, &tmpcap.cap[0], NULL))
goto fail; goto fail;
...@@ -938,11 +943,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -938,11 +943,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
info = "failed to unpack upper profile capabilities"; info = "failed to unpack upper profile capabilities";
if (unpack_nameX(e, AA_STRUCT, "caps64")) { if (unpack_nameX(e, AA_STRUCT, "caps64")) {
/* optional upper half of 64 bit caps */ /* optional upper half of 64 bit caps */
if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) if (!unpack_u32(e, &(rules->caps.allow.cap[1]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL)) if (!unpack_u32(e, &(rules->caps.audit.cap[1]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL)) if (!unpack_u32(e, &(rules->caps.quiet.cap[1]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &(tmpcap.cap[1]), NULL)) if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
goto fail; goto fail;
...@@ -953,9 +958,9 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -953,9 +958,9 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
info = "failed to unpack extended profile capabilities"; info = "failed to unpack extended profile capabilities";
if (unpack_nameX(e, AA_STRUCT, "capsx")) { if (unpack_nameX(e, AA_STRUCT, "capsx")) {
/* optional extended caps mediation mask */ /* optional extended caps mediation mask */
if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) if (!unpack_u32(e, &(rules->caps.extended.cap[0]), NULL))
goto fail; goto fail;
if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) if (!unpack_u32(e, &(rules->caps.extended.cap[1]), NULL))
goto fail; goto fail;
if (!unpack_nameX(e, AA_STRUCTEND, NULL)) if (!unpack_nameX(e, AA_STRUCTEND, NULL))
goto fail; goto fail;
...@@ -979,40 +984,41 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -979,40 +984,41 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
if (unpack_nameX(e, AA_STRUCT, "policydb")) { if (unpack_nameX(e, AA_STRUCT, "policydb")) {
/* generic policy dfa - optional and may be NULL */ /* generic policy dfa - optional and may be NULL */
info = "failed to unpack policydb"; info = "failed to unpack policydb";
error = unpack_pdb(e, &profile->policy, true, false, &info); error = unpack_pdb(e, &rules->policy, true, false,
&info);
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(profile->policy.dfa, profile->policy.start[0], if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0],
AA_CLASS_FILE)) AA_CLASS_FILE))
profile->policy.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE] =
aa_dfa_next(profile->policy.dfa, aa_dfa_next(rules->policy.dfa,
profile->policy.start[0], rules->policy.start[0],
AA_CLASS_FILE); AA_CLASS_FILE);
if (!unpack_nameX(e, AA_STRUCTEND, NULL)) if (!unpack_nameX(e, AA_STRUCTEND, NULL))
goto fail; goto fail;
if (aa_compat_map_policy(&profile->policy, e->version)) { if (aa_compat_map_policy(&rules->policy, e->version)) {
info = "failed to remap policydb permission table"; info = "failed to remap policydb permission table";
goto fail; goto fail;
} }
} else } else
profile->policy.dfa = aa_get_dfa(nulldfa); rules->policy.dfa = aa_get_dfa(nulldfa);
/* get file rules */ /* get file rules */
error = unpack_pdb(e, &profile->file, false, true, &info); error = unpack_pdb(e, &rules->file, false, true, &info);
if (error) { if (error) {
goto fail; goto fail;
} else if (profile->file.dfa) { } else if (rules->file.dfa) {
if (aa_compat_map_file(&profile->file)) { if (aa_compat_map_file(&rules->file)) {
info = "failed to remap file permission table"; info = "failed to remap file permission table";
goto fail; goto fail;
} }
} else if (profile->policy.dfa && } else if (rules->policy.dfa &&
profile->policy.start[AA_CLASS_FILE]) { rules->policy.start[AA_CLASS_FILE]) {
profile->file.dfa = aa_get_dfa(profile->policy.dfa); rules->file.dfa = aa_get_dfa(rules->policy.dfa);
profile->file.start[AA_CLASS_FILE] = profile->policy.start[AA_CLASS_FILE]; rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE];
} else } else
profile->file.dfa = aa_get_dfa(nulldfa); rules->file.dfa = aa_get_dfa(nulldfa);
if (unpack_nameX(e, AA_STRUCT, "data")) { if (unpack_nameX(e, AA_STRUCT, "data")) {
info = "out of memory"; info = "out of memory";
...@@ -1202,28 +1208,28 @@ static bool verify_perms(struct aa_policydb *pdb) ...@@ -1202,28 +1208,28 @@ static bool verify_perms(struct aa_policydb *pdb)
*/ */
static int verify_profile(struct aa_profile *profile) static int verify_profile(struct aa_profile *profile)
{ {
if ((profile->file.dfa && if ((profile->rules.file.dfa &&
!verify_dfa_xindex(profile->file.dfa, !verify_dfa_xindex(profile->rules.file.dfa,
profile->file.trans.size)) || profile->rules.file.trans.size)) ||
(profile->policy.dfa && (profile->rules.policy.dfa &&
!verify_dfa_xindex(profile->policy.dfa, !verify_dfa_xindex(profile->rules.policy.dfa,
profile->policy.trans.size))) { profile->rules.policy.trans.size))) {
audit_iface(profile, NULL, NULL, audit_iface(profile, NULL, NULL,
"Unpack: Invalid named transition", NULL, -EPROTO); "Unpack: Invalid named transition", NULL, -EPROTO);
return -EPROTO; return -EPROTO;
} }
if (!verify_perms(&profile->file)) { if (!verify_perms(&profile->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(&profile->policy)) { if (!verify_perms(&profile->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->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;
......
...@@ -82,10 +82,11 @@ int aa_map_resource(int resource) ...@@ -82,10 +82,11 @@ int aa_map_resource(int resource)
static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, static int profile_setrlimit(struct aa_profile *profile, unsigned int resource,
struct rlimit *new_rlim) struct rlimit *new_rlim)
{ {
struct aa_ruleset *rules = &profile->rules;
int e = 0; int e = 0;
if (profile->rlimits.mask & (1 << resource) && new_rlim->rlim_max > if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max >
profile->rlimits.limits[resource].rlim_max) rules->rlimits.limits[resource].rlim_max)
e = -EACCES; e = -EACCES;
return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL, return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL,
e); e);
...@@ -153,12 +154,12 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) ...@@ -153,12 +154,12 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l)
* to the lesser of the tasks hard limit and the init tasks soft limit * to the lesser of the tasks hard limit and the init tasks soft limit
*/ */
label_for_each_confined(i, old_l, old) { label_for_each_confined(i, old_l, old) {
if (old->rlimits.mask) { if (old->rules.rlimits.mask) {
int j; int j;
for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, for (j = 0, mask = 1; j < RLIM_NLIMITS; j++,
mask <<= 1) { mask <<= 1) {
if (old->rlimits.mask & mask) { if (old->rules.rlimits.mask & mask) {
rlim = current->signal->rlim + j; rlim = current->signal->rlim + j;
initrlim = init_task.signal->rlim + j; initrlim = init_task.signal->rlim + j;
rlim->rlim_cur = min(rlim->rlim_max, rlim->rlim_cur = min(rlim->rlim_max,
...@@ -172,15 +173,15 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) ...@@ -172,15 +173,15 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l)
label_for_each_confined(i, new_l, new) { label_for_each_confined(i, new_l, new) {
int j; int j;
if (!new->rlimits.mask) if (!new->rules.rlimits.mask)
continue; continue;
for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) { for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) {
if (!(new->rlimits.mask & mask)) if (!(new->rules.rlimits.mask & mask))
continue; continue;
rlim = current->signal->rlim + j; rlim = current->signal->rlim + j;
rlim->rlim_max = min(rlim->rlim_max, rlim->rlim_max = min(rlim->rlim_max,
new->rlimits.limits[j].rlim_max); new->rules.rlimits.limits[j].rlim_max);
/* soft limit should not exceed hard limit */ /* soft limit should not exceed hard limit */
rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
} }
......
...@@ -223,7 +223,7 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) ...@@ -223,7 +223,7 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
FLAGS_NONE, GFP_ATOMIC); FLAGS_NONE, GFP_ATOMIC);
} }
/* assumes check for PROFILE_MEDIATES is already done */ /* assumes check for RULE_MEDIATES is already done */
/* TODO: conditionals */ /* TODO: conditionals */
static int profile_ptrace_perm(struct aa_profile *profile, static int profile_ptrace_perm(struct aa_profile *profile,
struct aa_label *peer, u32 request, struct aa_label *peer, u32 request,
...@@ -232,8 +232,8 @@ static int profile_ptrace_perm(struct aa_profile *profile, ...@@ -232,8 +232,8 @@ static int profile_ptrace_perm(struct aa_profile *profile,
struct aa_perms perms = { }; struct aa_perms perms = { };
aad(sa)->peer = peer; aad(sa)->peer = peer;
aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, aa_profile_match_label(profile, &profile->rules, peer,
&perms); AA_CLASS_PTRACE, request, &perms);
aa_apply_modes_to_perms(profile, &perms); aa_apply_modes_to_perms(profile, &perms);
return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb);
} }
...@@ -243,7 +243,7 @@ static int profile_tracee_perm(struct aa_profile *tracee, ...@@ -243,7 +243,7 @@ static int profile_tracee_perm(struct aa_profile *tracee,
struct common_audit_data *sa) struct common_audit_data *sa)
{ {
if (profile_unconfined(tracee) || unconfined(tracer) || if (profile_unconfined(tracee) || unconfined(tracer) ||
!PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) !RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE))
return 0; return 0;
return profile_ptrace_perm(tracee, tracer, request, sa); return profile_ptrace_perm(tracee, tracer, request, sa);
...@@ -256,7 +256,7 @@ static int profile_tracer_perm(struct aa_profile *tracer, ...@@ -256,7 +256,7 @@ static int profile_tracer_perm(struct aa_profile *tracer,
if (profile_unconfined(tracer)) if (profile_unconfined(tracer))
return 0; return 0;
if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) if (RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE))
return profile_ptrace_perm(tracer, tracee, request, sa); return profile_ptrace_perm(tracer, tracee, request, sa);
/* profile uses the old style capability check for ptrace */ /* profile uses the old style capability check for ptrace */
......
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