summaryrefslogtreecommitdiff
path: root/security/apparmor/domain.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/domain.c')
-rw-r--r--security/apparmor/domain.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index dd754b7850a8..9527adc11c6d 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -305,6 +305,7 @@ static int change_profile_perms(struct aa_profile *profile,
* __attach_match_ - find an attachment match
* @name - to match against (NOT NULL)
* @head - profile list to walk (NOT NULL)
+ * @info - info message if there was an error (NOT NULL)
*
* Do a linear search on the profiles in the list. There is a matching
* preference where an exact match is preferred over a name which uses
@@ -316,28 +317,44 @@ static int change_profile_perms(struct aa_profile *profile,
* Returns: profile or NULL if no match found
*/
static struct aa_profile *__attach_match(const char *name,
- struct list_head *head)
+ struct list_head *head,
+ const char **info)
{
int len = 0;
+ bool conflict = false;
struct aa_profile *profile, *candidate = NULL;
list_for_each_entry_rcu(profile, head, base.list) {
if (profile->label.flags & FLAG_NULL)
continue;
- if (profile->xmatch && profile->xmatch_len > len) {
- unsigned int state = aa_dfa_match(profile->xmatch,
- DFA_START, name);
- u32 perm = dfa_user_allow(profile->xmatch, state);
- /* any accepting state means a valid match. */
- if (perm & MAY_EXEC) {
- candidate = profile;
- len = profile->xmatch_len;
+ if (profile->xmatch) {
+ if (profile->xmatch_len == len) {
+ conflict = true;
+ continue;
+ } else if (profile->xmatch_len > len) {
+ unsigned int state;
+ u32 perm;
+
+ state = aa_dfa_match(profile->xmatch,
+ DFA_START, name);
+ perm = dfa_user_allow(profile->xmatch, state);
+ /* any accepting state means a valid match. */
+ if (perm & MAY_EXEC) {
+ candidate = profile;
+ len = profile->xmatch_len;
+ conflict = false;
+ }
}
} else if (!strcmp(profile->base.name, name))
/* exact non-re match, no more searching required */
return profile;
}
+ if (conflict) {
+ *info = "conflicting profile attachments";
+ return NULL;
+ }
+
return candidate;
}
@@ -346,16 +363,17 @@ static struct aa_profile *__attach_match(const char *name,
* @ns: the current namespace (NOT NULL)
* @list: list to search (NOT NULL)
* @name: the executable name to match against (NOT NULL)
+ * @info: info message if there was an error
*
* Returns: label or NULL if no match found
*/
static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list,
- const char *name)
+ const char *name, const char **info)
{
struct aa_profile *profile;
rcu_read_lock();
- profile = aa_get_profile(__attach_match(name, list));
+ profile = aa_get_profile(__attach_match(name, list, info));
rcu_read_unlock();
return profile ? &profile->label : NULL;
@@ -448,11 +466,11 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
if (xindex & AA_X_CHILD)
/* released by caller */
new = find_attach(ns, &profile->base.profiles,
- name);
+ name, info);
else
/* released by caller */
new = find_attach(ns, &ns->base.profiles,
- name);
+ name, info);
*lookupname = name;
break;
}
@@ -516,7 +534,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
if (profile_unconfined(profile)) {
new = find_attach(profile->ns, &profile->ns->base.profiles,
- name);
+ name, &info);
if (new) {
AA_DEBUG("unconfined attached to new label");
return new;