Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'apparmor-pr-2020-01-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull apparmor fixes from John Johansen:

- performance regression: only get a label reference if the fast path
check fails

- fix aa_xattrs_match() may sleep while holding a RCU lock

- fix bind mounts aborting with -ENOMEM

* tag 'apparmor-pr-2020-01-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
apparmor: fix aa_xattrs_match() may sleep while holding a RCU lock
apparmor: only get a label reference if the fast path check fails
apparmor: fix bind mounts aborting with -ENOMEM

+54 -46
+1 -1
security/apparmor/apparmorfs.c
··· 623 623 624 624 void __aa_bump_ns_revision(struct aa_ns *ns) 625 625 { 626 - ns->revision++; 626 + WRITE_ONCE(ns->revision, ns->revision + 1); 627 627 wake_up_interruptible(&ns->wait); 628 628 } 629 629
+42 -38
security/apparmor/domain.c
··· 317 317 318 318 if (!bprm || !profile->xattr_count) 319 319 return 0; 320 + might_sleep(); 320 321 321 322 /* transition from exec match to xattr set */ 322 323 state = aa_dfa_null_transition(profile->xmatch, state); ··· 362 361 } 363 362 364 363 /** 365 - * __attach_match_ - find an attachment match 364 + * find_attach - do attachment search for unconfined processes 366 365 * @bprm - binprm structure of transitioning task 367 - * @name - to match against (NOT NULL) 366 + * @ns: the current namespace (NOT NULL) 368 367 * @head - profile list to walk (NOT NULL) 368 + * @name - to match against (NOT NULL) 369 369 * @info - info message if there was an error (NOT NULL) 370 370 * 371 371 * Do a linear search on the profiles in the list. There is a matching ··· 376 374 * 377 375 * Requires: @head not be shared or have appropriate locks held 378 376 * 379 - * Returns: profile or NULL if no match found 377 + * Returns: label or NULL if no match found 380 378 */ 381 - static struct aa_profile *__attach_match(const struct linux_binprm *bprm, 382 - const char *name, 383 - struct list_head *head, 384 - const char **info) 379 + static struct aa_label *find_attach(const struct linux_binprm *bprm, 380 + struct aa_ns *ns, struct list_head *head, 381 + const char *name, const char **info) 385 382 { 386 383 int candidate_len = 0, candidate_xattrs = 0; 387 384 bool conflict = false; ··· 389 388 AA_BUG(!name); 390 389 AA_BUG(!head); 391 390 391 + rcu_read_lock(); 392 + restart: 392 393 list_for_each_entry_rcu(profile, head, base.list) { 393 394 if (profile->label.flags & FLAG_NULL && 394 395 &profile->label == ns_unconfined(profile->ns)) ··· 416 413 perm = dfa_user_allow(profile->xmatch, state); 417 414 /* any accepting state means a valid match. */ 418 415 if (perm & MAY_EXEC) { 419 - int ret; 416 + int ret = 0; 420 417 421 418 if (count < candidate_len) 422 419 continue; 423 420 424 - ret = aa_xattrs_match(bprm, profile, state); 425 - /* Fail matching if the xattrs don't match */ 426 - if (ret < 0) 427 - continue; 421 + if (bprm && profile->xattr_count) { 422 + long rev = READ_ONCE(ns->revision); 428 423 424 + if (!aa_get_profile_not0(profile)) 425 + goto restart; 426 + rcu_read_unlock(); 427 + ret = aa_xattrs_match(bprm, profile, 428 + state); 429 + rcu_read_lock(); 430 + aa_put_profile(profile); 431 + if (rev != 432 + READ_ONCE(ns->revision)) 433 + /* policy changed */ 434 + goto restart; 435 + /* 436 + * Fail matching if the xattrs don't 437 + * match 438 + */ 439 + if (ret < 0) 440 + continue; 441 + } 429 442 /* 430 443 * TODO: allow for more flexible best match 431 444 * ··· 464 445 candidate_xattrs = ret; 465 446 conflict = false; 466 447 } 467 - } else if (!strcmp(profile->base.name, name)) 448 + } else if (!strcmp(profile->base.name, name)) { 468 449 /* 469 450 * old exact non-re match, without conditionals such 470 451 * as xattrs. no more searching required 471 452 */ 472 - return profile; 453 + candidate = profile; 454 + goto out; 455 + } 473 456 } 474 457 475 - if (conflict) { 476 - *info = "conflicting profile attachments"; 458 + if (!candidate || conflict) { 459 + if (conflict) 460 + *info = "conflicting profile attachments"; 461 + rcu_read_unlock(); 477 462 return NULL; 478 463 } 479 464 480 - return candidate; 481 - } 482 - 483 - /** 484 - * find_attach - do attachment search for unconfined processes 485 - * @bprm - binprm structure of transitioning task 486 - * @ns: the current namespace (NOT NULL) 487 - * @list: list to search (NOT NULL) 488 - * @name: the executable name to match against (NOT NULL) 489 - * @info: info message if there was an error 490 - * 491 - * Returns: label or NULL if no match found 492 - */ 493 - static struct aa_label *find_attach(const struct linux_binprm *bprm, 494 - struct aa_ns *ns, struct list_head *list, 495 - const char *name, const char **info) 496 - { 497 - struct aa_profile *profile; 498 - 499 - rcu_read_lock(); 500 - profile = aa_get_profile(__attach_match(bprm, name, list, info)); 465 + out: 466 + candidate = aa_get_newest_profile(candidate); 501 467 rcu_read_unlock(); 502 468 503 - return profile ? &profile->label : NULL; 469 + return &candidate->label; 504 470 } 505 471 506 472 static const char *next_name(int xtype, const char *name)
+8 -4
security/apparmor/file.c
··· 618 618 fctx = file_ctx(file); 619 619 620 620 rcu_read_lock(); 621 - flabel = aa_get_newest_label(rcu_dereference(fctx->label)); 622 - rcu_read_unlock(); 621 + flabel = rcu_dereference(fctx->label); 623 622 AA_BUG(!flabel); 624 623 625 624 /* revalidate access, if task is unconfined, or the cached cred ··· 630 631 */ 631 632 denied = request & ~fctx->allow; 632 633 if (unconfined(label) || unconfined(flabel) || 633 - (!denied && aa_label_is_subset(flabel, label))) 634 + (!denied && aa_label_is_subset(flabel, label))) { 635 + rcu_read_unlock(); 634 636 goto done; 637 + } 635 638 639 + flabel = aa_get_newest_label(flabel); 640 + rcu_read_unlock(); 636 641 /* TODO: label cross check */ 637 642 638 643 if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) ··· 646 643 else if (S_ISSOCK(file_inode(file)->i_mode)) 647 644 error = __file_sock_perm(op, label, flabel, file, request, 648 645 denied); 649 - done: 650 646 aa_put_label(flabel); 647 + 648 + done: 651 649 return error; 652 650 } 653 651
+1 -1
security/apparmor/mount.c
··· 442 442 buffer = aa_get_buffer(false); 443 443 old_buffer = aa_get_buffer(false); 444 444 error = -ENOMEM; 445 - if (!buffer || old_buffer) 445 + if (!buffer || !old_buffer) 446 446 goto out; 447 447 448 448 error = fn_for_each_confined(label, profile,
+2 -2
security/apparmor/policy.c
··· 1125 1125 if (!name) { 1126 1126 /* remove namespace - can only happen if fqname[0] == ':' */ 1127 1127 mutex_lock_nested(&ns->parent->lock, ns->level); 1128 - __aa_remove_ns(ns); 1129 1128 __aa_bump_ns_revision(ns); 1129 + __aa_remove_ns(ns); 1130 1130 mutex_unlock(&ns->parent->lock); 1131 1131 } else { 1132 1132 /* remove profile */ ··· 1138 1138 goto fail_ns_lock; 1139 1139 } 1140 1140 name = profile->base.hname; 1141 + __aa_bump_ns_revision(ns); 1141 1142 __remove_profile(profile); 1142 1143 __aa_labelset_update_subtree(ns); 1143 - __aa_bump_ns_revision(ns); 1144 1144 mutex_unlock(&ns->lock); 1145 1145 } 1146 1146