diff options
| -rw-r--r-- | security/apparmor/apparmorfs.c | 22 | ||||
| -rw-r--r-- | security/apparmor/domain.c | 68 | ||||
| -rw-r--r-- | security/apparmor/file.c | 8 | ||||
| -rw-r--r-- | security/apparmor/label.c | 2 | ||||
| -rw-r--r-- | security/apparmor/lib.c | 16 | ||||
| -rw-r--r-- | security/apparmor/lsm.c | 8 | ||||
| -rw-r--r-- | security/apparmor/mount.c | 13 | ||||
| -rw-r--r-- | security/apparmor/policy.c | 11 | ||||
| -rw-r--r-- | security/apparmor/policy_ns.c | 8 | ||||
| -rw-r--r-- | security/apparmor/policy_unpack.c | 2 | ||||
| -rw-r--r-- | security/apparmor/resource.c | 4 |
11 files changed, 91 insertions, 71 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index caaf51dda648..8542e9a55e1b 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c | |||
| @@ -533,7 +533,7 @@ static ssize_t ns_revision_read(struct file *file, char __user *buf, | |||
| 533 | long last_read; | 533 | long last_read; |
| 534 | int avail; | 534 | int avail; |
| 535 | 535 | ||
| 536 | mutex_lock(&rev->ns->lock); | 536 | mutex_lock_nested(&rev->ns->lock, rev->ns->level); |
| 537 | last_read = rev->last_read; | 537 | last_read = rev->last_read; |
| 538 | if (last_read == rev->ns->revision) { | 538 | if (last_read == rev->ns->revision) { |
| 539 | mutex_unlock(&rev->ns->lock); | 539 | mutex_unlock(&rev->ns->lock); |
| @@ -543,7 +543,7 @@ static ssize_t ns_revision_read(struct file *file, char __user *buf, | |||
| 543 | last_read != | 543 | last_read != |
| 544 | READ_ONCE(rev->ns->revision))) | 544 | READ_ONCE(rev->ns->revision))) |
| 545 | return -ERESTARTSYS; | 545 | return -ERESTARTSYS; |
| 546 | mutex_lock(&rev->ns->lock); | 546 | mutex_lock_nested(&rev->ns->lock, rev->ns->level); |
| 547 | } | 547 | } |
| 548 | 548 | ||
| 549 | avail = sprintf(buffer, "%ld\n", rev->ns->revision); | 549 | avail = sprintf(buffer, "%ld\n", rev->ns->revision); |
| @@ -577,7 +577,7 @@ static unsigned int ns_revision_poll(struct file *file, poll_table *pt) | |||
| 577 | unsigned int mask = 0; | 577 | unsigned int mask = 0; |
| 578 | 578 | ||
| 579 | if (rev) { | 579 | if (rev) { |
| 580 | mutex_lock(&rev->ns->lock); | 580 | mutex_lock_nested(&rev->ns->lock, rev->ns->level); |
| 581 | poll_wait(file, &rev->ns->wait, pt); | 581 | poll_wait(file, &rev->ns->wait, pt); |
| 582 | if (rev->last_read < rev->ns->revision) | 582 | if (rev->last_read < rev->ns->revision) |
| 583 | mask |= POLLIN | POLLRDNORM; | 583 | mask |= POLLIN | POLLRDNORM; |
| @@ -1643,7 +1643,7 @@ static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 1643 | */ | 1643 | */ |
| 1644 | inode_unlock(dir); | 1644 | inode_unlock(dir); |
| 1645 | error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count); | 1645 | error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count); |
| 1646 | mutex_lock(&parent->lock); | 1646 | mutex_lock_nested(&parent->lock, parent->level); |
| 1647 | inode_lock_nested(dir, I_MUTEX_PARENT); | 1647 | inode_lock_nested(dir, I_MUTEX_PARENT); |
| 1648 | if (error) | 1648 | if (error) |
| 1649 | goto out; | 1649 | goto out; |
| @@ -1692,7 +1692,7 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) | |||
| 1692 | inode_unlock(dir); | 1692 | inode_unlock(dir); |
| 1693 | inode_unlock(dentry->d_inode); | 1693 | inode_unlock(dentry->d_inode); |
| 1694 | 1694 | ||
| 1695 | mutex_lock(&parent->lock); | 1695 | mutex_lock_nested(&parent->lock, parent->level); |
| 1696 | ns = aa_get_ns(__aa_findn_ns(&parent->sub_ns, dentry->d_name.name, | 1696 | ns = aa_get_ns(__aa_findn_ns(&parent->sub_ns, dentry->d_name.name, |
| 1697 | dentry->d_name.len)); | 1697 | dentry->d_name.len)); |
| 1698 | if (!ns) { | 1698 | if (!ns) { |
| @@ -1747,7 +1747,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns) | |||
| 1747 | __aafs_profile_rmdir(child); | 1747 | __aafs_profile_rmdir(child); |
| 1748 | 1748 | ||
| 1749 | list_for_each_entry(sub, &ns->sub_ns, base.list) { | 1749 | list_for_each_entry(sub, &ns->sub_ns, base.list) { |
| 1750 | mutex_lock(&sub->lock); | 1750 | mutex_lock_nested(&sub->lock, sub->level); |
| 1751 | __aafs_ns_rmdir(sub); | 1751 | __aafs_ns_rmdir(sub); |
| 1752 | mutex_unlock(&sub->lock); | 1752 | mutex_unlock(&sub->lock); |
| 1753 | } | 1753 | } |
| @@ -1877,7 +1877,7 @@ int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name, | |||
| 1877 | 1877 | ||
| 1878 | /* subnamespaces */ | 1878 | /* subnamespaces */ |
| 1879 | list_for_each_entry(sub, &ns->sub_ns, base.list) { | 1879 | list_for_each_entry(sub, &ns->sub_ns, base.list) { |
| 1880 | mutex_lock(&sub->lock); | 1880 | mutex_lock_nested(&sub->lock, sub->level); |
| 1881 | error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL, NULL); | 1881 | error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL, NULL); |
| 1882 | mutex_unlock(&sub->lock); | 1882 | mutex_unlock(&sub->lock); |
| 1883 | if (error) | 1883 | if (error) |
| @@ -1921,7 +1921,7 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns) | |||
| 1921 | /* is next namespace a child */ | 1921 | /* is next namespace a child */ |
| 1922 | if (!list_empty(&ns->sub_ns)) { | 1922 | if (!list_empty(&ns->sub_ns)) { |
| 1923 | next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); | 1923 | next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); |
| 1924 | mutex_lock(&next->lock); | 1924 | mutex_lock_nested(&next->lock, next->level); |
| 1925 | return next; | 1925 | return next; |
| 1926 | } | 1926 | } |
| 1927 | 1927 | ||
| @@ -1931,7 +1931,7 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns) | |||
| 1931 | mutex_unlock(&ns->lock); | 1931 | mutex_unlock(&ns->lock); |
| 1932 | next = list_next_entry(ns, base.list); | 1932 | next = list_next_entry(ns, base.list); |
| 1933 | if (!list_entry_is_head(next, &parent->sub_ns, base.list)) { | 1933 | if (!list_entry_is_head(next, &parent->sub_ns, base.list)) { |
| 1934 | mutex_lock(&next->lock); | 1934 | mutex_lock_nested(&next->lock, next->level); |
| 1935 | return next; | 1935 | return next; |
| 1936 | } | 1936 | } |
| 1937 | ns = parent; | 1937 | ns = parent; |
| @@ -2039,7 +2039,7 @@ static void *p_start(struct seq_file *f, loff_t *pos) | |||
| 2039 | f->private = root; | 2039 | f->private = root; |
| 2040 | 2040 | ||
| 2041 | /* find the first profile */ | 2041 | /* find the first profile */ |
| 2042 | mutex_lock(&root->lock); | 2042 | mutex_lock_nested(&root->lock, root->level); |
| 2043 | profile = __first_profile(root, root); | 2043 | profile = __first_profile(root, root); |
| 2044 | 2044 | ||
| 2045 | /* skip to position */ | 2045 | /* skip to position */ |
| @@ -2491,7 +2491,7 @@ static int __init aa_create_aafs(void) | |||
| 2491 | ns_subrevision(root_ns) = dent; | 2491 | ns_subrevision(root_ns) = dent; |
| 2492 | 2492 | ||
| 2493 | /* policy tree referenced by magic policy symlink */ | 2493 | /* policy tree referenced by magic policy symlink */ |
| 2494 | mutex_lock(&root_ns->lock); | 2494 | mutex_lock_nested(&root_ns->lock, root_ns->level); |
| 2495 | error = __aafs_ns_mkdir(root_ns, aafs_mnt->mnt_root, ".policy", | 2495 | error = __aafs_ns_mkdir(root_ns, aafs_mnt->mnt_root, ".policy", |
| 2496 | aafs_mnt->mnt_root); | 2496 | aafs_mnt->mnt_root); |
| 2497 | mutex_unlock(&root_ns->lock); | 2497 | mutex_unlock(&root_ns->lock); |
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index dd754b7850a8..04ba9d0718ea 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,46 @@ 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 && |
| 329 | &profile->label == ns_unconfined(profile->ns)) | ||
| 326 | continue; | 330 | continue; |
| 327 | if (profile->xmatch && profile->xmatch_len > len) { | 331 | |
| 328 | unsigned int state = aa_dfa_match(profile->xmatch, | 332 | if (profile->xmatch) { |
| 329 | DFA_START, name); | 333 | if (profile->xmatch_len == len) { |
| 330 | u32 perm = dfa_user_allow(profile->xmatch, state); | 334 | conflict = true; |
| 331 | /* any accepting state means a valid match. */ | 335 | continue; |
| 332 | if (perm & MAY_EXEC) { | 336 | } else if (profile->xmatch_len > len) { |
| 333 | candidate = profile; | 337 | unsigned int state; |
| 334 | len = profile->xmatch_len; | 338 | u32 perm; |
| 339 | |||
| 340 | state = aa_dfa_match(profile->xmatch, | ||
| 341 | DFA_START, name); | ||
| 342 | perm = dfa_user_allow(profile->xmatch, state); | ||
| 343 | /* any accepting state means a valid match. */ | ||
| 344 | if (perm & MAY_EXEC) { | ||
| 345 | candidate = profile; | ||
| 346 | len = profile->xmatch_len; | ||
| 347 | conflict = false; | ||
| 348 | } | ||
| 335 | } | 349 | } |
| 336 | } else if (!strcmp(profile->base.name, name)) | 350 | } else if (!strcmp(profile->base.name, name)) |
| 337 | /* exact non-re match, no more searching required */ | 351 | /* exact non-re match, no more searching required */ |
| 338 | return profile; | 352 | return profile; |
| 339 | } | 353 | } |
| 340 | 354 | ||
| 355 | if (conflict) { | ||
| 356 | *info = "conflicting profile attachments"; | ||
| 357 | return NULL; | ||
| 358 | } | ||
| 359 | |||
| 341 | return candidate; | 360 | return candidate; |
| 342 | } | 361 | } |
| 343 | 362 | ||
| @@ -346,16 +365,17 @@ static struct aa_profile *__attach_match(const char *name, | |||
| 346 | * @ns: the current namespace (NOT NULL) | 365 | * @ns: the current namespace (NOT NULL) |
| 347 | * @list: list to search (NOT NULL) | 366 | * @list: list to search (NOT NULL) |
| 348 | * @name: the executable name to match against (NOT NULL) | 367 | * @name: the executable name to match against (NOT NULL) |
| 368 | * @info: info message if there was an error | ||
| 349 | * | 369 | * |
| 350 | * Returns: label or NULL if no match found | 370 | * Returns: label or NULL if no match found |
| 351 | */ | 371 | */ |
| 352 | static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list, | 372 | static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list, |
| 353 | const char *name) | 373 | const char *name, const char **info) |
| 354 | { | 374 | { |
| 355 | struct aa_profile *profile; | 375 | struct aa_profile *profile; |
| 356 | 376 | ||
| 357 | rcu_read_lock(); | 377 | rcu_read_lock(); |
| 358 | profile = aa_get_profile(__attach_match(name, list)); | 378 | profile = aa_get_profile(__attach_match(name, list, info)); |
| 359 | rcu_read_unlock(); | 379 | rcu_read_unlock(); |
| 360 | 380 | ||
| 361 | return profile ? &profile->label : NULL; | 381 | return profile ? &profile->label : NULL; |
| @@ -448,11 +468,11 @@ static struct aa_label *x_to_label(struct aa_profile *profile, | |||
| 448 | if (xindex & AA_X_CHILD) | 468 | if (xindex & AA_X_CHILD) |
| 449 | /* released by caller */ | 469 | /* released by caller */ |
| 450 | new = find_attach(ns, &profile->base.profiles, | 470 | new = find_attach(ns, &profile->base.profiles, |
| 451 | name); | 471 | name, info); |
| 452 | else | 472 | else |
| 453 | /* released by caller */ | 473 | /* released by caller */ |
| 454 | new = find_attach(ns, &ns->base.profiles, | 474 | new = find_attach(ns, &ns->base.profiles, |
| 455 | name); | 475 | name, info); |
| 456 | *lookupname = name; | 476 | *lookupname = name; |
| 457 | break; | 477 | break; |
| 458 | } | 478 | } |
| @@ -516,7 +536,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile, | |||
| 516 | 536 | ||
| 517 | if (profile_unconfined(profile)) { | 537 | if (profile_unconfined(profile)) { |
| 518 | new = find_attach(profile->ns, &profile->ns->base.profiles, | 538 | new = find_attach(profile->ns, &profile->ns->base.profiles, |
| 519 | name); | 539 | name, &info); |
| 520 | if (new) { | 540 | if (new) { |
| 521 | AA_DEBUG("unconfined attached to new label"); | 541 | AA_DEBUG("unconfined attached to new label"); |
| 522 | return new; | 542 | return new; |
| @@ -541,9 +561,21 @@ static struct aa_label *profile_transition(struct aa_profile *profile, | |||
| 541 | } | 561 | } |
| 542 | } else if (COMPLAIN_MODE(profile)) { | 562 | } else if (COMPLAIN_MODE(profile)) { |
| 543 | /* no exec permission - learning mode */ | 563 | /* no exec permission - learning mode */ |
| 544 | struct aa_profile *new_profile = aa_new_null_profile(profile, | 564 | struct aa_profile *new_profile = NULL; |
| 545 | false, name, | 565 | char *n = kstrdup(name, GFP_ATOMIC); |
| 546 | GFP_ATOMIC); | 566 | |
| 567 | if (n) { | ||
| 568 | /* name is ptr into buffer */ | ||
| 569 | long pos = name - buffer; | ||
| 570 | /* break per cpu buffer hold */ | ||
| 571 | put_buffers(buffer); | ||
| 572 | new_profile = aa_new_null_profile(profile, false, n, | ||
| 573 | GFP_KERNEL); | ||
| 574 | get_buffers(buffer); | ||
| 575 | name = buffer + pos; | ||
| 576 | strcpy((char *)name, n); | ||
| 577 | kfree(n); | ||
| 578 | } | ||
| 547 | if (!new_profile) { | 579 | if (!new_profile) { |
| 548 | error = -ENOMEM; | 580 | error = -ENOMEM; |
| 549 | info = "could not create null profile"; | 581 | info = "could not create null profile"; |
diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 3382518b87fa..e79bf44396a3 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c | |||
| @@ -226,18 +226,12 @@ static u32 map_old_perms(u32 old) | |||
| 226 | struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state, | 226 | struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state, |
| 227 | struct path_cond *cond) | 227 | struct path_cond *cond) |
| 228 | { | 228 | { |
| 229 | struct aa_perms perms; | ||
| 230 | |||
| 231 | /* FIXME: change over to new dfa format | 229 | /* FIXME: change over to new dfa format |
| 232 | * currently file perms are encoded in the dfa, new format | 230 | * currently file perms are encoded in the dfa, new format |
| 233 | * splits the permissions from the dfa. This mapping can be | 231 | * splits the permissions from the dfa. This mapping can be |
| 234 | * done at profile load | 232 | * done at profile load |
| 235 | */ | 233 | */ |
| 236 | perms.deny = 0; | 234 | struct aa_perms perms = { }; |
| 237 | perms.kill = perms.stop = 0; | ||
| 238 | perms.complain = perms.cond = 0; | ||
| 239 | perms.hide = 0; | ||
| 240 | perms.prompt = 0; | ||
| 241 | 235 | ||
| 242 | if (uid_eq(current_fsuid(), cond->uid)) { | 236 | if (uid_eq(current_fsuid(), cond->uid)) { |
| 243 | perms.allow = map_old_perms(dfa_user_allow(dfa, state)); | 237 | perms.allow = map_old_perms(dfa_user_allow(dfa, state)); |
diff --git a/security/apparmor/label.c b/security/apparmor/label.c index ad28e03a6f30..324fe5c60f87 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c | |||
| @@ -2115,7 +2115,7 @@ void __aa_labelset_update_subtree(struct aa_ns *ns) | |||
| 2115 | __labelset_update(ns); | 2115 | __labelset_update(ns); |
| 2116 | 2116 | ||
| 2117 | list_for_each_entry(child, &ns->sub_ns, base.list) { | 2117 | list_for_each_entry(child, &ns->sub_ns, base.list) { |
| 2118 | mutex_lock(&child->lock); | 2118 | mutex_lock_nested(&child->lock, child->level); |
| 2119 | __aa_labelset_update_subtree(child); | 2119 | __aa_labelset_update_subtree(child); |
| 2120 | mutex_unlock(&child->lock); | 2120 | mutex_unlock(&child->lock); |
| 2121 | } | 2121 | } |
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 08ca26bcca77..4d5e98e49d5e 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c | |||
| @@ -317,14 +317,11 @@ static u32 map_other(u32 x) | |||
| 317 | void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, | 317 | void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, |
| 318 | struct aa_perms *perms) | 318 | struct aa_perms *perms) |
| 319 | { | 319 | { |
| 320 | perms->deny = 0; | 320 | *perms = (struct aa_perms) { |
| 321 | perms->kill = perms->stop = 0; | 321 | .allow = dfa_user_allow(dfa, state), |
| 322 | perms->complain = perms->cond = 0; | 322 | .audit = dfa_user_audit(dfa, state), |
| 323 | perms->hide = 0; | 323 | .quiet = dfa_user_quiet(dfa, state), |
| 324 | perms->prompt = 0; | 324 | }; |
| 325 | perms->allow = dfa_user_allow(dfa, state); | ||
| 326 | perms->audit = dfa_user_audit(dfa, state); | ||
| 327 | perms->quiet = dfa_user_quiet(dfa, state); | ||
| 328 | 325 | ||
| 329 | /* for v5 perm mapping in the policydb, the other set is used | 326 | /* for v5 perm mapping in the policydb, the other set is used |
| 330 | * to extend the general perm set | 327 | * to extend the general perm set |
| @@ -426,7 +423,6 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, | |||
| 426 | void (*cb)(struct audit_buffer *, void *)) | 423 | void (*cb)(struct audit_buffer *, void *)) |
| 427 | { | 424 | { |
| 428 | int type, error; | 425 | int type, error; |
| 429 | bool stop = false; | ||
| 430 | u32 denied = request & (~perms->allow | perms->deny); | 426 | u32 denied = request & (~perms->allow | perms->deny); |
| 431 | 427 | ||
| 432 | if (likely(!denied)) { | 428 | if (likely(!denied)) { |
| @@ -447,8 +443,6 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, | |||
| 447 | else | 443 | else |
| 448 | type = AUDIT_APPARMOR_DENIED; | 444 | type = AUDIT_APPARMOR_DENIED; |
| 449 | 445 | ||
| 450 | if (denied & perms->stop) | ||
| 451 | stop = true; | ||
| 452 | if (denied == (denied & perms->hide)) | 446 | if (denied == (denied & perms->hide)) |
| 453 | error = -ENOENT; | 447 | error = -ENOENT; |
| 454 | 448 | ||
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 17893fde4487..9a65eeaf7dfa 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -846,7 +846,7 @@ module_param_call(audit, param_set_audit, param_get_audit, | |||
| 846 | /* Determines if audit header is included in audited messages. This | 846 | /* Determines if audit header is included in audited messages. This |
| 847 | * provides more context if the audit daemon is not running | 847 | * provides more context if the audit daemon is not running |
| 848 | */ | 848 | */ |
| 849 | bool aa_g_audit_header = 1; | 849 | bool aa_g_audit_header = true; |
| 850 | module_param_named(audit_header, aa_g_audit_header, aabool, | 850 | module_param_named(audit_header, aa_g_audit_header, aabool, |
| 851 | S_IRUSR | S_IWUSR); | 851 | S_IRUSR | S_IWUSR); |
| 852 | 852 | ||
| @@ -871,7 +871,7 @@ module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR); | |||
| 871 | * DEPRECATED: read only as strict checking of load is always done now | 871 | * DEPRECATED: read only as strict checking of load is always done now |
| 872 | * that none root users (user namespaces) can load policy. | 872 | * that none root users (user namespaces) can load policy. |
| 873 | */ | 873 | */ |
| 874 | bool aa_g_paranoid_load = 1; | 874 | bool aa_g_paranoid_load = true; |
| 875 | module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); | 875 | module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); |
| 876 | 876 | ||
| 877 | /* Boot time disable flag */ | 877 | /* Boot time disable flag */ |
| @@ -1119,7 +1119,7 @@ static int __init apparmor_init(void) | |||
| 1119 | 1119 | ||
| 1120 | if (!apparmor_enabled || !security_module_enable("apparmor")) { | 1120 | if (!apparmor_enabled || !security_module_enable("apparmor")) { |
| 1121 | aa_info_message("AppArmor disabled by boot time parameter"); | 1121 | aa_info_message("AppArmor disabled by boot time parameter"); |
| 1122 | apparmor_enabled = 0; | 1122 | apparmor_enabled = false; |
| 1123 | return 0; | 1123 | return 0; |
| 1124 | } | 1124 | } |
| 1125 | 1125 | ||
| @@ -1175,7 +1175,7 @@ alloc_out: | |||
| 1175 | aa_destroy_aafs(); | 1175 | aa_destroy_aafs(); |
| 1176 | aa_teardown_dfa_engine(); | 1176 | aa_teardown_dfa_engine(); |
| 1177 | 1177 | ||
| 1178 | apparmor_enabled = 0; | 1178 | apparmor_enabled = false; |
| 1179 | return error; | 1179 | return error; |
| 1180 | } | 1180 | } |
| 1181 | 1181 | ||
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index 82a64b58041d..ed9b4d0f9f7e 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c | |||
| @@ -216,13 +216,12 @@ static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state, | |||
| 216 | static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa, | 216 | static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa, |
| 217 | unsigned int state) | 217 | unsigned int state) |
| 218 | { | 218 | { |
| 219 | struct aa_perms perms; | 219 | struct aa_perms perms = { |
| 220 | 220 | .allow = dfa_user_allow(dfa, state), | |
| 221 | perms.kill = 0; | 221 | .audit = dfa_user_audit(dfa, state), |
| 222 | perms.allow = dfa_user_allow(dfa, state); | 222 | .quiet = dfa_user_quiet(dfa, state), |
| 223 | perms.audit = dfa_user_audit(dfa, state); | 223 | .xindex = dfa_user_xindex(dfa, state), |
| 224 | perms.quiet = dfa_user_quiet(dfa, state); | 224 | }; |
| 225 | perms.xindex = dfa_user_xindex(dfa, state); | ||
| 226 | 225 | ||
| 227 | return perms; | 226 | return perms; |
| 228 | } | 227 | } |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 4243b0c3f0e4..b0b58848c248 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
| @@ -502,7 +502,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, | |||
| 502 | { | 502 | { |
| 503 | struct aa_profile *p, *profile; | 503 | struct aa_profile *p, *profile; |
| 504 | const char *bname; | 504 | const char *bname; |
| 505 | char *name; | 505 | char *name = NULL; |
| 506 | 506 | ||
| 507 | AA_BUG(!parent); | 507 | AA_BUG(!parent); |
| 508 | 508 | ||
| @@ -545,7 +545,7 @@ name: | |||
| 545 | profile->file.dfa = aa_get_dfa(nulldfa); | 545 | profile->file.dfa = aa_get_dfa(nulldfa); |
| 546 | profile->policy.dfa = aa_get_dfa(nulldfa); | 546 | profile->policy.dfa = aa_get_dfa(nulldfa); |
| 547 | 547 | ||
| 548 | mutex_lock(&profile->ns->lock); | 548 | mutex_lock_nested(&profile->ns->lock, profile->ns->level); |
| 549 | p = __find_child(&parent->base.profiles, bname); | 549 | p = __find_child(&parent->base.profiles, bname); |
| 550 | if (p) { | 550 | if (p) { |
| 551 | aa_free_profile(profile); | 551 | aa_free_profile(profile); |
| @@ -562,6 +562,7 @@ out: | |||
| 562 | return profile; | 562 | return profile; |
| 563 | 563 | ||
| 564 | fail: | 564 | fail: |
| 565 | kfree(name); | ||
| 565 | aa_free_profile(profile); | 566 | aa_free_profile(profile); |
| 566 | return NULL; | 567 | return NULL; |
| 567 | } | 568 | } |
| @@ -905,7 +906,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, | |||
| 905 | } else | 906 | } else |
| 906 | ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label)); | 907 | ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label)); |
| 907 | 908 | ||
| 908 | mutex_lock(&ns->lock); | 909 | mutex_lock_nested(&ns->lock, ns->level); |
| 909 | /* check for duplicate rawdata blobs: space and file dedup */ | 910 | /* check for duplicate rawdata blobs: space and file dedup */ |
| 910 | list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { | 911 | list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { |
| 911 | if (aa_rawdata_eq(rawdata_ent, udata)) { | 912 | if (aa_rawdata_eq(rawdata_ent, udata)) { |
| @@ -1116,13 +1117,13 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj, | |||
| 1116 | 1117 | ||
| 1117 | if (!name) { | 1118 | if (!name) { |
| 1118 | /* remove namespace - can only happen if fqname[0] == ':' */ | 1119 | /* remove namespace - can only happen if fqname[0] == ':' */ |
| 1119 | mutex_lock(&ns->parent->lock); | 1120 | mutex_lock_nested(&ns->parent->lock, ns->level); |
| 1120 | __aa_remove_ns(ns); | 1121 | __aa_remove_ns(ns); |
| 1121 | __aa_bump_ns_revision(ns); | 1122 | __aa_bump_ns_revision(ns); |
| 1122 | mutex_unlock(&ns->parent->lock); | 1123 | mutex_unlock(&ns->parent->lock); |
| 1123 | } else { | 1124 | } else { |
| 1124 | /* remove profile */ | 1125 | /* remove profile */ |
| 1125 | mutex_lock(&ns->lock); | 1126 | mutex_lock_nested(&ns->lock, ns->level); |
| 1126 | profile = aa_get_profile(__lookup_profile(&ns->base, name)); | 1127 | profile = aa_get_profile(__lookup_profile(&ns->base, name)); |
| 1127 | if (!profile) { | 1128 | if (!profile) { |
| 1128 | error = -ENOENT; | 1129 | error = -ENOENT; |
diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c index 62a3589c62ab..b1e629cba70b 100644 --- a/security/apparmor/policy_ns.c +++ b/security/apparmor/policy_ns.c | |||
| @@ -256,7 +256,8 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, | |||
| 256 | ns = alloc_ns(parent->base.hname, name); | 256 | ns = alloc_ns(parent->base.hname, name); |
| 257 | if (!ns) | 257 | if (!ns) |
| 258 | return NULL; | 258 | return NULL; |
| 259 | mutex_lock(&ns->lock); | 259 | ns->level = parent->level + 1; |
| 260 | mutex_lock_nested(&ns->lock, ns->level); | ||
| 260 | error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir); | 261 | error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir); |
| 261 | if (error) { | 262 | if (error) { |
| 262 | AA_ERROR("Failed to create interface for ns %s\n", | 263 | AA_ERROR("Failed to create interface for ns %s\n", |
| @@ -266,7 +267,6 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, | |||
| 266 | return ERR_PTR(error); | 267 | return ERR_PTR(error); |
| 267 | } | 268 | } |
| 268 | ns->parent = aa_get_ns(parent); | 269 | ns->parent = aa_get_ns(parent); |
| 269 | ns->level = parent->level + 1; | ||
| 270 | list_add_rcu(&ns->base.list, &parent->sub_ns); | 270 | list_add_rcu(&ns->base.list, &parent->sub_ns); |
| 271 | /* add list ref */ | 271 | /* add list ref */ |
| 272 | aa_get_ns(ns); | 272 | aa_get_ns(ns); |
| @@ -313,7 +313,7 @@ struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name) | |||
| 313 | { | 313 | { |
| 314 | struct aa_ns *ns; | 314 | struct aa_ns *ns; |
| 315 | 315 | ||
| 316 | mutex_lock(&parent->lock); | 316 | mutex_lock_nested(&parent->lock, parent->level); |
| 317 | /* try and find the specified ns and if it doesn't exist create it */ | 317 | /* try and find the specified ns and if it doesn't exist create it */ |
| 318 | /* released by caller */ | 318 | /* released by caller */ |
| 319 | ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); | 319 | ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); |
| @@ -336,7 +336,7 @@ static void destroy_ns(struct aa_ns *ns) | |||
| 336 | if (!ns) | 336 | if (!ns) |
| 337 | return; | 337 | return; |
| 338 | 338 | ||
| 339 | mutex_lock(&ns->lock); | 339 | mutex_lock_nested(&ns->lock, ns->level); |
| 340 | /* release all profiles in this namespace */ | 340 | /* release all profiles in this namespace */ |
| 341 | __aa_profile_list_release(&ns->base.profiles); | 341 | __aa_profile_list_release(&ns->base.profiles); |
| 342 | 342 | ||
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 4ede87c30f8b..59a1a25b7d43 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c | |||
| @@ -157,7 +157,7 @@ static void do_loaddata_free(struct work_struct *work) | |||
| 157 | struct aa_ns *ns = aa_get_ns(d->ns); | 157 | struct aa_ns *ns = aa_get_ns(d->ns); |
| 158 | 158 | ||
| 159 | if (ns) { | 159 | if (ns) { |
| 160 | mutex_lock(&ns->lock); | 160 | mutex_lock_nested(&ns->lock, ns->level); |
| 161 | __aa_fs_remove_rawdata(d); | 161 | __aa_fs_remove_rawdata(d); |
| 162 | mutex_unlock(&ns->lock); | 162 | mutex_unlock(&ns->lock); |
| 163 | aa_put_ns(ns); | 163 | aa_put_ns(ns); |
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index d8bc842594ed..cf4d234febe9 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c | |||
| @@ -47,7 +47,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) | |||
| 47 | /** | 47 | /** |
| 48 | * audit_resource - audit setting resource limit | 48 | * audit_resource - audit setting resource limit |
| 49 | * @profile: profile being enforced (NOT NULL) | 49 | * @profile: profile being enforced (NOT NULL) |
| 50 | * @resoure: rlimit being auditing | 50 | * @resource: rlimit being auditing |
| 51 | * @value: value being set | 51 | * @value: value being set |
| 52 | * @error: error value | 52 | * @error: error value |
| 53 | * | 53 | * |
| @@ -128,7 +128,7 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, | |||
| 128 | error = fn_for_each(label, profile, | 128 | error = fn_for_each(label, profile, |
| 129 | audit_resource(profile, resource, | 129 | audit_resource(profile, resource, |
| 130 | new_rlim->rlim_max, peer, | 130 | new_rlim->rlim_max, peer, |
| 131 | "cap_sys_resoure", -EACCES)); | 131 | "cap_sys_resource", -EACCES)); |
| 132 | else | 132 | else |
| 133 | error = fn_for_each_confined(label, profile, | 133 | error = fn_for_each_confined(label, profile, |
| 134 | profile_setrlimit(profile, resource, new_rlim)); | 134 | profile_setrlimit(profile, resource, new_rlim)); |
