Commit 1ad22fcc authored by John Johansen's avatar John Johansen

apparmor: rework profile->rules to be a list

Convert profile->rules to a list as the next step towards supporting
multiple rulesets in a profile. For this step only support a single
list entry item. The logic for iterating the list will come as a
separate step.
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 217af7e2
...@@ -611,7 +611,8 @@ static const struct file_operations aa_fs_ns_revision_fops = { ...@@ -611,7 +611,8 @@ 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_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_perms tmp = { }; struct aa_perms tmp = { };
aa_state_t state = DFA_NOMATCH; aa_state_t state = DFA_NOMATCH;
......
...@@ -64,7 +64,8 @@ static void audit_cb(struct audit_buffer *ab, void *va) ...@@ -64,7 +64,8 @@ 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 aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct audit_cache *ent; struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
...@@ -115,7 +116,8 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, ...@@ -115,7 +116,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
int error; int error;
if (cap_raised(rules->caps.allow, cap) && if (cap_raised(rules->caps.allow, cap) &&
......
...@@ -81,7 +81,8 @@ static inline aa_state_t match_component(struct aa_profile *profile, ...@@ -81,7 +81,8 @@ static inline aa_state_t match_component(struct aa_profile *profile,
struct aa_profile *tp, struct aa_profile *tp,
bool stack, aa_state_t state) bool stack, aa_state_t state)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
const char *ns_name; const char *ns_name;
if (stack) if (stack)
...@@ -118,7 +119,8 @@ static int label_compound_match(struct aa_profile *profile, ...@@ -118,7 +119,8 @@ static int label_compound_match(struct aa_profile *profile,
aa_state_t state, bool subns, u32 request, aa_state_t state, bool subns, u32 request,
struct aa_perms *perms) struct aa_perms *perms)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_profile *tp; struct aa_profile *tp;
struct label_it i; struct label_it i;
struct path_cond cond = { }; struct path_cond cond = { };
...@@ -179,7 +181,8 @@ static int label_components_match(struct aa_profile *profile, ...@@ -179,7 +181,8 @@ static int label_components_match(struct aa_profile *profile,
aa_state_t start, bool subns, u32 request, aa_state_t start, bool subns, u32 request,
struct aa_perms *perms) struct aa_perms *perms)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_profile *tp; struct aa_profile *tp;
struct label_it i; struct label_it i;
struct aa_perms tmp; struct aa_perms tmp;
...@@ -503,7 +506,8 @@ static const char *next_name(int xtype, const char *name) ...@@ -503,7 +506,8 @@ static const char *next_name(int xtype, const char *name)
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
const char **name) const char **name)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_label *label = NULL; struct aa_label *label = NULL;
u32 xtype = xindex & AA_X_TYPE_MASK; u32 xtype = xindex & AA_X_TYPE_MASK;
int index = xindex & AA_X_INDEX_MASK; int index = xindex & AA_X_INDEX_MASK;
...@@ -553,7 +557,8 @@ static struct aa_label *x_to_label(struct aa_profile *profile, ...@@ -553,7 +557,8 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
const char **lookupname, const char **lookupname,
const char **info) const char **info)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_label *new = NULL; struct aa_label *new = NULL;
struct aa_ns *ns = profile->ns; struct aa_ns *ns = profile->ns;
u32 xtype = xindex & AA_X_TYPE_MASK; u32 xtype = xindex & AA_X_TYPE_MASK;
...@@ -620,7 +625,8 @@ static struct aa_label *profile_transition(struct aa_profile *profile, ...@@ -620,7 +625,8 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
char *buffer, struct path_cond *cond, char *buffer, struct path_cond *cond,
bool *secure_exec) bool *secure_exec)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
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];
...@@ -719,7 +725,8 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, ...@@ -719,7 +725,8 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
char *buffer, struct path_cond *cond, char *buffer, struct path_cond *cond,
bool *secure_exec) bool *secure_exec)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
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";
...@@ -1259,7 +1266,8 @@ static int change_profile_perms_wrapper(const char *op, const char *name, ...@@ -1259,7 +1266,8 @@ static int change_profile_perms_wrapper(const char *op, const char *name,
struct aa_label *target, bool stack, struct aa_label *target, bool stack,
u32 request, struct aa_perms *perms) u32 request, struct aa_perms *perms)
{ {
struct aa_ruleset *rules = &profile->rules; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
const char *info = NULL; const char *info = NULL;
int error = 0; int error = 0;
......
...@@ -224,7 +224,8 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, ...@@ -224,7 +224,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
int e = 0; int e = 0;
if (profile_unconfined(profile)) if (profile_unconfined(profile))
...@@ -317,7 +318,8 @@ static int profile_path_link(struct aa_profile *profile, ...@@ -317,7 +318,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
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;
......
...@@ -124,6 +124,7 @@ struct aa_data { ...@@ -124,6 +124,7 @@ struct aa_data {
}; };
/* struct aa_ruleset - data covering mediation rules /* struct aa_ruleset - data covering mediation rules
* @list: list the rule is on
* @size: the memory consumed by this ruleset * @size: the memory consumed by this ruleset
* @policy: general match rules governing policy * @policy: general match rules governing policy
* @file: The set of rules governing basic file access and domain transitions * @file: The set of rules governing basic file access and domain transitions
...@@ -133,6 +134,8 @@ struct aa_data { ...@@ -133,6 +134,8 @@ struct aa_data {
* @secmark: secmark label match info * @secmark: secmark label match info
*/ */
struct aa_ruleset { struct aa_ruleset {
struct list_head list;
int size; int size;
/* TODO: merge policy and file */ /* TODO: merge policy and file */
...@@ -147,6 +150,7 @@ struct aa_ruleset { ...@@ -147,6 +150,7 @@ struct aa_ruleset {
}; };
/* struct aa_attachment - data and rules for a profiles attachment /* struct aa_attachment - data and rules for a profiles attachment
* @list:
* @xmatch_str: human readable attachment string * @xmatch_str: human readable attachment string
* @xmatch: optional extended matching for unconfined executables names * @xmatch: optional extended matching for unconfined executables names
* @xmatch_len: xmatch prefix len, used to determine xmatch priority * @xmatch_len: xmatch prefix len, used to determine xmatch priority
...@@ -204,7 +208,7 @@ struct aa_profile { ...@@ -204,7 +208,7 @@ struct aa_profile {
const char *disconnected; const char *disconnected;
struct aa_attachment attach; struct aa_attachment attach;
struct aa_ruleset rules; struct list_head rules;
struct aa_loaddata *rawdata; struct aa_loaddata *rawdata;
unsigned char *hash; unsigned char *hash;
...@@ -227,6 +231,7 @@ void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); ...@@ -227,6 +231,7 @@ void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
void aa_free_proxy_kref(struct kref *kref); void aa_free_proxy_kref(struct kref *kref);
struct aa_ruleset *aa_alloc_ruleset(gfp_t gfp);
struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy,
gfp_t gfp); gfp_t gfp);
struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
...@@ -285,6 +290,16 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) ...@@ -285,6 +290,16 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)
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,
unsigned char class)
{
struct aa_ruleset *rule;
/* TODO: change to list walk */
rule = list_first_entry(head, typeof(*rule), list);
return RULE_MEDIATES(rule, class);
}
/** /**
* aa_get_profile - increment refcount on profile @p * aa_get_profile - increment refcount on profile @p
* @p: profile (MAYBE NULL) * @p: profile (MAYBE NULL)
......
...@@ -78,12 +78,13 @@ static int profile_signal_perm(struct aa_profile *profile, ...@@ -78,12 +78,13 @@ 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_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_perms perms; struct aa_perms perms;
aa_state_t state; aa_state_t state;
if (profile_unconfined(profile) || if (profile_unconfined(profile) ||
!RULE_MEDIATES(rules, AA_CLASS_SIGNAL)) !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL))
return 0; return 0;
aad(sa)->peer = peer; aad(sa)->peer = peer;
......
...@@ -351,14 +351,16 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, ...@@ -351,14 +351,16 @@ 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,
struct common_audit_data *sa) struct common_audit_data *sa)
{ {
struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_perms perms; struct aa_perms perms;
aad(sa)->label = &profile->label; aad(sa)->label = &profile->label;
aad(sa)->peer = &target->label; aad(sa)->peer = &target->label;
aad(sa)->request = request; aad(sa)->request = request;
aa_profile_match_label(profile, &profile->rules, &target->label, type, aa_profile_match_label(profile, rules, &target->label, type, request,
request, &perms); &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);
......
...@@ -163,12 +163,15 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, ...@@ -163,12 +163,15 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
struct label_it i; struct label_it i;
label_for_each_confined(i, label, profile) { label_for_each_confined(i, label, profile) {
struct aa_ruleset *rules;
if (COMPLAIN_MODE(profile)) if (COMPLAIN_MODE(profile))
continue; continue;
rules = list_first_entry(&profile->rules,
typeof(*rules), list);
*effective = cap_intersect(*effective, *effective = cap_intersect(*effective,
profile->rules.caps.allow); rules->caps.allow);
*permitted = cap_intersect(*permitted, *permitted = cap_intersect(*permitted,
profile->rules.caps.allow); rules->caps.allow);
} }
} }
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -303,7 +303,8 @@ static int match_mnt_path_str(struct aa_profile *profile, ...@@ -303,7 +303,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
int pos, error; int pos, error;
AA_BUG(!profile); AA_BUG(!profile);
...@@ -359,12 +360,14 @@ static int match_mnt(struct aa_profile *profile, const struct path *path, ...@@ -359,12 +360,14 @@ static int match_mnt(struct aa_profile *profile, const struct path *path,
bool binary) bool binary)
{ {
const char *devname = NULL, *info = NULL; const char *devname = NULL, *info = NULL;
struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
int error = -EACCES; int error = -EACCES;
AA_BUG(!profile); AA_BUG(!profile);
AA_BUG(devpath && !devbuffer); AA_BUG(devpath && !devbuffer);
if (!RULE_MEDIATES(&profile->rules, AA_CLASS_MOUNT)) if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return 0; return 0;
if (devpath) { if (devpath) {
...@@ -566,7 +569,8 @@ int aa_new_mount(struct aa_label *label, const char *dev_name, ...@@ -566,7 +569,8 @@ 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_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
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;
...@@ -626,7 +630,8 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile, ...@@ -626,7 +630,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
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 = { };
......
...@@ -108,7 +108,8 @@ void audit_net_cb(struct audit_buffer *ab, void *va) ...@@ -108,7 +108,8 @@ 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_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_perms perms = { }; struct aa_perms perms = { };
aa_state_t state; aa_state_t state;
__be16 buffer[2]; __be16 buffer[2];
...@@ -217,7 +218,8 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, ...@@ -217,7 +218,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
if (rules->secmark_count == 0) if (rules->secmark_count == 0)
return 0; return 0;
......
...@@ -217,6 +217,17 @@ static void free_ruleset(struct aa_ruleset *rules) ...@@ -217,6 +217,17 @@ static void free_ruleset(struct aa_ruleset *rules)
kfree_sensitive(rules->secmark); kfree_sensitive(rules->secmark);
} }
struct aa_ruleset *aa_alloc_ruleset(gfp_t gfp)
{
struct aa_ruleset *rules;
rules = kzalloc(sizeof(*rules), gfp);
if (rules)
INIT_LIST_HEAD(&rules->list);
return rules;
}
/** /**
* 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)
...@@ -229,6 +240,7 @@ static void free_ruleset(struct aa_ruleset *rules) ...@@ -229,6 +240,7 @@ static void free_ruleset(struct aa_ruleset *rules)
*/ */
void aa_free_profile(struct aa_profile *profile) void aa_free_profile(struct aa_profile *profile)
{ {
struct aa_ruleset *rule, *tmp;
struct rhashtable *rht; struct rhashtable *rht;
AA_DEBUG("%s(%p)\n", __func__, profile); AA_DEBUG("%s(%p)\n", __func__, profile);
...@@ -244,7 +256,15 @@ void aa_free_profile(struct aa_profile *profile) ...@@ -244,7 +256,15 @@ void aa_free_profile(struct aa_profile *profile)
kfree_sensitive(profile->rename); kfree_sensitive(profile->rename);
free_attachment(&profile->attach); free_attachment(&profile->attach);
free_ruleset(&profile->rules);
/*
* at this point there are no tasks that can have a reference
* to rules
*/
list_for_each_entry_safe(rule, tmp, &profile->rules, list) {
list_del_init(&rule->list);
free_ruleset(rule);
}
kfree_sensitive(profile->dirname); kfree_sensitive(profile->dirname);
if (profile->data) { if (profile->data) {
...@@ -272,6 +292,7 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, ...@@ -272,6 +292,7 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
gfp_t gfp) gfp_t gfp)
{ {
struct aa_profile *profile; struct aa_profile *profile;
struct aa_ruleset *rules;
/* freed by free_profile - usually through aa_put_profile */ /* freed by free_profile - usually through aa_put_profile */
profile = kzalloc(struct_size(profile, label.vec, 2), gfp); profile = kzalloc(struct_size(profile, label.vec, 2), gfp);
...@@ -283,6 +304,14 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, ...@@ -283,6 +304,14 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
if (!aa_label_init(&profile->label, 1, gfp)) if (!aa_label_init(&profile->label, 1, gfp))
goto fail; goto fail;
INIT_LIST_HEAD(&profile->rules);
/* allocate the first ruleset, but leave it empty */
rules = aa_alloc_ruleset(gfp);
if (!rules)
goto fail;
list_add(&rules->list, &profile->rules);
/* update being set needed by fs interface */ /* update being set needed by fs interface */
if (!proxy) { if (!proxy) {
proxy = aa_alloc_proxy(&profile->label, gfp); proxy = aa_alloc_proxy(&profile->label, gfp);
...@@ -516,6 +545,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, ...@@ -516,6 +545,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
const char *base, gfp_t gfp) const char *base, gfp_t gfp)
{ {
struct aa_ruleset *rules;
struct aa_profile *p, *profile; struct aa_profile *p, *profile;
const char *bname; const char *bname;
char *name = NULL; char *name = NULL;
...@@ -558,8 +588,9 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, ...@@ -558,8 +588,9 @@ 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->rules.file.dfa = aa_get_dfa(nulldfa); rules = list_first_entry(&profile->rules, typeof(*rules), list);
profile->rules.policy.dfa = aa_get_dfa(nulldfa); rules->file.dfa = aa_get_dfa(nulldfa);
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);
......
...@@ -83,6 +83,7 @@ const char *aa_ns_name(struct aa_ns *curr, struct aa_ns *view, bool subns) ...@@ -83,6 +83,7 @@ const char *aa_ns_name(struct aa_ns *curr, struct aa_ns *view, bool subns)
static struct aa_profile *alloc_unconfined(const char *name) static struct aa_profile *alloc_unconfined(const char *name)
{ {
struct aa_profile *profile; struct aa_profile *profile;
struct aa_ruleset *rules;
profile = aa_alloc_profile(name, NULL, GFP_KERNEL); profile = aa_alloc_profile(name, NULL, GFP_KERNEL);
if (!profile) if (!profile)
...@@ -91,8 +92,9 @@ static struct aa_profile *alloc_unconfined(const char *name) ...@@ -91,8 +92,9 @@ 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->rules.file.dfa = aa_get_dfa(nulldfa); rules = list_first_entry(&profile->rules, typeof(*rules), list);
profile->rules.policy.dfa = aa_get_dfa(nulldfa); rules->file.dfa = aa_get_dfa(nulldfa);
rules->policy.dfa = aa_get_dfa(nulldfa);
return profile; return profile;
} }
......
...@@ -577,9 +577,8 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile) ...@@ -577,9 +577,8 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile)
return false; return false;
} }
static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) static bool unpack_secmark(struct aa_ext *e, struct aa_ruleset *rules)
{ {
struct aa_ruleset *rules = &profile->rules;
void *pos = e->pos; void *pos = e->pos;
u16 size; u16 size;
int i; int i;
...@@ -624,7 +623,7 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) ...@@ -624,7 +623,7 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
return false; return false;
} }
static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) static bool unpack_rlimits(struct aa_ext *e, struct aa_ruleset *rules)
{ {
void *pos = e->pos; void *pos = e->pos;
...@@ -635,7 +634,7 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) ...@@ -635,7 +634,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->rules.rlimits.mask = tmp; 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)
...@@ -645,7 +644,7 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) ...@@ -645,7 +644,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->rules.rlimits.limits[a].rlim_max = tmp2; 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;
...@@ -852,7 +851,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -852,7 +851,7 @@ 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; rules = list_first_entry(&profile->rules, typeof(*rules), list);
/* profile renaming is optional */ /* profile renaming is optional */
(void) unpack_str(e, &profile->rename, "rename"); (void) unpack_str(e, &profile->rename, "rename");
...@@ -971,12 +970,12 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) ...@@ -971,12 +970,12 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
goto fail; goto fail;
} }
if (!unpack_rlimits(e, profile)) { if (!unpack_rlimits(e, rules)) {
info = "failed to unpack profile rlimits"; info = "failed to unpack profile rlimits";
goto fail; goto fail;
} }
if (!unpack_secmark(e, profile)) { if (!unpack_secmark(e, rules)) {
info = "failed to unpack profile secmark rules"; info = "failed to unpack profile secmark rules";
goto fail; goto fail;
} }
...@@ -1208,23 +1207,26 @@ static bool verify_perms(struct aa_policydb *pdb) ...@@ -1208,23 +1207,26 @@ 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->rules.file.dfa && struct aa_ruleset *rules = list_first_entry(&profile->rules,
!verify_dfa_xindex(profile->rules.file.dfa, typeof(*rules), list);
profile->rules.file.trans.size)) || if (!rules)
(profile->rules.policy.dfa && return 0;
!verify_dfa_xindex(profile->rules.policy.dfa,
profile->rules.policy.trans.size))) { if ((rules->file.dfa && !verify_dfa_xindex(rules->file.dfa,
rules->file.trans.size)) ||
(rules->policy.dfa &&
!verify_dfa_xindex(rules->policy.dfa, 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->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(&profile->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;
......
...@@ -82,7 +82,8 @@ int aa_map_resource(int resource) ...@@ -82,7 +82,8 @@ 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; struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
int e = 0; int e = 0;
if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max > if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max >
...@@ -154,12 +155,15 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) ...@@ -154,12 +155,15 @@ 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->rules.rlimits.mask) { struct aa_ruleset *rules = list_first_entry(&old->rules,
typeof(*rules),
list);
if (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->rules.rlimits.mask & mask) { if (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,
...@@ -171,17 +175,20 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) ...@@ -171,17 +175,20 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l)
/* set any new hard limits as dictated by the new profile */ /* set any new hard limits as dictated by the new profile */
label_for_each_confined(i, new_l, new) { label_for_each_confined(i, new_l, new) {
struct aa_ruleset *rules = list_first_entry(&new->rules,
typeof(*rules),
list);
int j; int j;
if (!new->rules.rlimits.mask) if (!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->rules.rlimits.mask & mask)) if (!(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->rules.rlimits.limits[j].rlim_max); 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);
} }
......
...@@ -229,11 +229,13 @@ static int profile_ptrace_perm(struct aa_profile *profile, ...@@ -229,11 +229,13 @@ static int profile_ptrace_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 = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_perms perms = { }; struct aa_perms perms = { };
aad(sa)->peer = peer; aad(sa)->peer = peer;
aa_profile_match_label(profile, &profile->rules, peer, aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request,
AA_CLASS_PTRACE, request, &perms); &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 +245,7 @@ static int profile_tracee_perm(struct aa_profile *tracee, ...@@ -243,7 +245,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) ||
!RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) !ANY_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 +258,7 @@ static int profile_tracer_perm(struct aa_profile *tracer, ...@@ -256,7 +258,7 @@ static int profile_tracer_perm(struct aa_profile *tracer,
if (profile_unconfined(tracer)) if (profile_unconfined(tracer))
return 0; return 0;
if (RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) if (ANY_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