aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,
305 * __attach_match_ - find an attachment match 305 * __attach_match_ - find an attachment match
306 * @name - to match against (NOT NULL) 306 * @name - to match against (NOT NULL)
307 * @head - profile list to walk (NOT NULL) 307 * @head - profile list to walk (NOT NULL)
308 * @info - info message if there was an error (NOT NULL)
308 * 309 *
309 * Do a linear search on the profiles in the list. There is a matching 310 * Do a linear search on the profiles in the list. There is a matching
310 * preference where an exact match is preferred over a name which uses 311 * 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,
316 * Returns: profile or NULL if no match found 317 * Returns: profile or NULL if no match found
317 */ 318 */
318static struct aa_profile *__attach_match(const char *name, 319static struct aa_profile *__attach_match(const char *name,
319 struct list_head *head) 320 struct list_head *head,
321 const char **info)
320{ 322{
321 int len = 0; 323 int len = 0;
324 bool conflict = false;
322 struct aa_profile *profile, *candidate = NULL; 325 struct aa_profile *profile, *candidate = NULL;
323 326
324 list_for_each_entry_rcu(profile, head, base.list) { 327 list_for_each_entry_rcu(profile, head, base.list) {
325 if (profile->label.flags & FLAG_NULL) 328 if (profile->label.flags & FLAG_NULL)
326 continue; 329 continue;
327 if (profile->xmatch && profile->xmatch_len > len) { 330 if (profile->xmatch) {
328 unsigned int state = aa_dfa_match(profile->xmatch, 331 if (profile->xmatch_len == len) {
329 DFA_START, name); 332 conflict = true;
330 u32 perm = dfa_user_allow(profile->xmatch, state); 333 continue;
331 /* any accepting state means a valid match. */ 334 } else if (profile->xmatch_len > len) {
332 if (perm & MAY_EXEC) { 335 unsigned int state;
333 candidate = profile; 336 u32 perm;
334 len = profile->xmatch_len; 337
338 state = aa_dfa_match(profile->xmatch,
339 DFA_START, name);
340 perm = dfa_user_allow(profile->xmatch, state);
341 /* any accepting state means a valid match. */
342 if (perm & MAY_EXEC) {
343 candidate = profile;
344 len = profile->xmatch_len;
345 conflict = false;
346 }
335 } 347 }
336 } else if (!strcmp(profile->base.name, name)) 348 } else if (!strcmp(profile->base.name, name))
337 /* exact non-re match, no more searching required */ 349 /* exact non-re match, no more searching required */
338 return profile; 350 return profile;
339 } 351 }
340 352
353 if (conflict) {
354 *info = "conflicting profile attachments";
355 return NULL;
356 }
357
341 return candidate; 358 return candidate;
342} 359}
343 360
@@ -346,16 +363,17 @@ static struct aa_profile *__attach_match(const char *name,
346 * @ns: the current namespace (NOT NULL) 363 * @ns: the current namespace (NOT NULL)
347 * @list: list to search (NOT NULL) 364 * @list: list to search (NOT NULL)
348 * @name: the executable name to match against (NOT NULL) 365 * @name: the executable name to match against (NOT NULL)
366 * @info: info message if there was an error
349 * 367 *
350 * Returns: label or NULL if no match found 368 * Returns: label or NULL if no match found
351 */ 369 */
352static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list, 370static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list,
353 const char *name) 371 const char *name, const char **info)
354{ 372{
355 struct aa_profile *profile; 373 struct aa_profile *profile;
356 374
357 rcu_read_lock(); 375 rcu_read_lock();
358 profile = aa_get_profile(__attach_match(name, list)); 376 profile = aa_get_profile(__attach_match(name, list, info));
359 rcu_read_unlock(); 377 rcu_read_unlock();
360 378
361 return profile ? &profile->label : NULL; 379 return profile ? &profile->label : NULL;
@@ -448,11 +466,11 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
448 if (xindex & AA_X_CHILD) 466 if (xindex & AA_X_CHILD)
449 /* released by caller */ 467 /* released by caller */
450 new = find_attach(ns, &profile->base.profiles, 468 new = find_attach(ns, &profile->base.profiles,
451 name); 469 name, info);
452 else 470 else
453 /* released by caller */ 471 /* released by caller */
454 new = find_attach(ns, &ns->base.profiles, 472 new = find_attach(ns, &ns->base.profiles,
455 name); 473 name, info);
456 *lookupname = name; 474 *lookupname = name;
457 break; 475 break;
458 } 476 }
@@ -516,7 +534,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
516 534
517 if (profile_unconfined(profile)) { 535 if (profile_unconfined(profile)) {
518 new = find_attach(profile->ns, &profile->ns->base.profiles, 536 new = find_attach(profile->ns, &profile->ns->base.profiles,
519 name); 537 name, &info);
520 if (new) { 538 if (new) {
521 AA_DEBUG("unconfined attached to new label"); 539 AA_DEBUG("unconfined attached to new label");
522 return new; 540 return new;