diff options
| -rw-r--r-- | security/apparmor/domain.c | 46 |
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 | */ |
| 318 | static struct aa_profile *__attach_match(const char *name, | 319 | static 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 | */ |
| 352 | static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list, | 370 | static 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; |
