diff options
author | James Morris <james.l.morris@oracle.com> | 2012-06-10 08:52:10 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-06-10 08:52:10 -0400 |
commit | 66dd07b88a1c9d446f32253da606b87324fa620e (patch) | |
tree | 4e0971bdd543585c7ab46716ae808a7fd82f9c35 /security | |
parent | f52c44cd27b4a0be37ef97f0466e4095ebebef3f (diff) | |
parent | cfaf025112d3856637ff34a767ef785ef5cf2ca9 (diff) |
Merge commit 'v3.5-rc2' into next
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/lsm.c | 15 | ||||
-rw-r--r-- | security/capability.c | 3 | ||||
-rw-r--r-- | security/commoncap.c | 78 | ||||
-rw-r--r-- | security/device_cgroup.c | 10 | ||||
-rw-r--r-- | security/keys/compat.c | 2 | ||||
-rw-r--r-- | security/keys/internal.h | 2 | ||||
-rw-r--r-- | security/keys/key.c | 2 | ||||
-rw-r--r-- | security/keys/keyctl.c | 77 | ||||
-rw-r--r-- | security/keys/permission.c | 5 | ||||
-rw-r--r-- | security/keys/process_keys.c | 22 | ||||
-rw-r--r-- | security/keys/request_key.c | 13 | ||||
-rw-r--r-- | security/security.c | 51 | ||||
-rw-r--r-- | security/selinux/hooks.c | 15 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 13 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 36 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 15 |
16 files changed, 173 insertions, 186 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 032daab449b0..8ea39aabe948 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -490,17 +490,9 @@ static int common_mmap(int op, struct file *file, unsigned long prot, | |||
490 | return common_file_perm(op, file, mask); | 490 | return common_file_perm(op, file, mask); |
491 | } | 491 | } |
492 | 492 | ||
493 | static int apparmor_file_mmap(struct file *file, unsigned long reqprot, | 493 | static int apparmor_mmap_file(struct file *file, unsigned long reqprot, |
494 | unsigned long prot, unsigned long flags, | 494 | unsigned long prot, unsigned long flags) |
495 | unsigned long addr, unsigned long addr_only) | ||
496 | { | 495 | { |
497 | int rc = 0; | ||
498 | |||
499 | /* do DAC check */ | ||
500 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
501 | if (rc || addr_only) | ||
502 | return rc; | ||
503 | |||
504 | return common_mmap(OP_FMMAP, file, prot, flags); | 496 | return common_mmap(OP_FMMAP, file, prot, flags); |
505 | } | 497 | } |
506 | 498 | ||
@@ -646,7 +638,8 @@ static struct security_operations apparmor_ops = { | |||
646 | .file_permission = apparmor_file_permission, | 638 | .file_permission = apparmor_file_permission, |
647 | .file_alloc_security = apparmor_file_alloc_security, | 639 | .file_alloc_security = apparmor_file_alloc_security, |
648 | .file_free_security = apparmor_file_free_security, | 640 | .file_free_security = apparmor_file_free_security, |
649 | .file_mmap = apparmor_file_mmap, | 641 | .mmap_file = apparmor_mmap_file, |
642 | .mmap_addr = cap_mmap_addr, | ||
650 | .file_mprotect = apparmor_file_mprotect, | 643 | .file_mprotect = apparmor_file_mprotect, |
651 | .file_lock = apparmor_file_lock, | 644 | .file_lock = apparmor_file_lock, |
652 | 645 | ||
diff --git a/security/capability.c b/security/capability.c index fca889676c5e..61095df8b89a 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -949,7 +949,8 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
949 | set_to_cap_if_null(ops, file_alloc_security); | 949 | set_to_cap_if_null(ops, file_alloc_security); |
950 | set_to_cap_if_null(ops, file_free_security); | 950 | set_to_cap_if_null(ops, file_free_security); |
951 | set_to_cap_if_null(ops, file_ioctl); | 951 | set_to_cap_if_null(ops, file_ioctl); |
952 | set_to_cap_if_null(ops, file_mmap); | 952 | set_to_cap_if_null(ops, mmap_addr); |
953 | set_to_cap_if_null(ops, mmap_file); | ||
953 | set_to_cap_if_null(ops, file_mprotect); | 954 | set_to_cap_if_null(ops, file_mprotect); |
954 | set_to_cap_if_null(ops, file_lock); | 955 | set_to_cap_if_null(ops, file_lock); |
955 | set_to_cap_if_null(ops, file_fcntl); | 956 | set_to_cap_if_null(ops, file_fcntl); |
diff --git a/security/commoncap.c b/security/commoncap.c index f80d11609391..6dbae4650abe 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -77,12 +77,12 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, | |||
77 | int cap, int audit) | 77 | int cap, int audit) |
78 | { | 78 | { |
79 | for (;;) { | 79 | for (;;) { |
80 | /* The creator of the user namespace has all caps. */ | 80 | /* The owner of the user namespace has all caps. */ |
81 | if (targ_ns != &init_user_ns && targ_ns->creator == cred->user) | 81 | if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, cred->euid)) |
82 | return 0; | 82 | return 0; |
83 | 83 | ||
84 | /* Do we have the necessary capabilities? */ | 84 | /* Do we have the necessary capabilities? */ |
85 | if (targ_ns == cred->user->user_ns) | 85 | if (targ_ns == cred->user_ns) |
86 | return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; | 86 | return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; |
87 | 87 | ||
88 | /* Have we tried all of the parent namespaces? */ | 88 | /* Have we tried all of the parent namespaces? */ |
@@ -93,7 +93,7 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, | |||
93 | *If you have a capability in a parent user ns, then you have | 93 | *If you have a capability in a parent user ns, then you have |
94 | * it over all children user namespaces as well. | 94 | * it over all children user namespaces as well. |
95 | */ | 95 | */ |
96 | targ_ns = targ_ns->creator->user_ns; | 96 | targ_ns = targ_ns->parent; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* We never get here */ | 99 | /* We never get here */ |
@@ -137,10 +137,10 @@ int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) | |||
137 | rcu_read_lock(); | 137 | rcu_read_lock(); |
138 | cred = current_cred(); | 138 | cred = current_cred(); |
139 | child_cred = __task_cred(child); | 139 | child_cred = __task_cred(child); |
140 | if (cred->user->user_ns == child_cred->user->user_ns && | 140 | if (cred->user_ns == child_cred->user_ns && |
141 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) | 141 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) |
142 | goto out; | 142 | goto out; |
143 | if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE)) | 143 | if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE)) |
144 | goto out; | 144 | goto out; |
145 | ret = -EPERM; | 145 | ret = -EPERM; |
146 | out: | 146 | out: |
@@ -169,10 +169,10 @@ int cap_ptrace_traceme(struct task_struct *parent) | |||
169 | rcu_read_lock(); | 169 | rcu_read_lock(); |
170 | cred = __task_cred(parent); | 170 | cred = __task_cred(parent); |
171 | child_cred = current_cred(); | 171 | child_cred = current_cred(); |
172 | if (cred->user->user_ns == child_cred->user->user_ns && | 172 | if (cred->user_ns == child_cred->user_ns && |
173 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) | 173 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) |
174 | goto out; | 174 | goto out; |
175 | if (has_ns_capability(parent, child_cred->user->user_ns, CAP_SYS_PTRACE)) | 175 | if (has_ns_capability(parent, child_cred->user_ns, CAP_SYS_PTRACE)) |
176 | goto out; | 176 | goto out; |
177 | ret = -EPERM; | 177 | ret = -EPERM; |
178 | out: | 178 | out: |
@@ -215,7 +215,7 @@ static inline int cap_inh_is_capped(void) | |||
215 | /* they are so limited unless the current task has the CAP_SETPCAP | 215 | /* they are so limited unless the current task has the CAP_SETPCAP |
216 | * capability | 216 | * capability |
217 | */ | 217 | */ |
218 | if (cap_capable(current_cred(), current_cred()->user->user_ns, | 218 | if (cap_capable(current_cred(), current_cred()->user_ns, |
219 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) | 219 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) |
220 | return 0; | 220 | return 0; |
221 | return 1; | 221 | return 1; |
@@ -473,19 +473,22 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
473 | struct cred *new = bprm->cred; | 473 | struct cred *new = bprm->cred; |
474 | bool effective, has_cap = false; | 474 | bool effective, has_cap = false; |
475 | int ret; | 475 | int ret; |
476 | kuid_t root_uid; | ||
476 | 477 | ||
477 | effective = false; | 478 | effective = false; |
478 | ret = get_file_caps(bprm, &effective, &has_cap); | 479 | ret = get_file_caps(bprm, &effective, &has_cap); |
479 | if (ret < 0) | 480 | if (ret < 0) |
480 | return ret; | 481 | return ret; |
481 | 482 | ||
483 | root_uid = make_kuid(new->user_ns, 0); | ||
484 | |||
482 | if (!issecure(SECURE_NOROOT)) { | 485 | if (!issecure(SECURE_NOROOT)) { |
483 | /* | 486 | /* |
484 | * If the legacy file capability is set, then don't set privs | 487 | * If the legacy file capability is set, then don't set privs |
485 | * for a setuid root binary run by a non-root user. Do set it | 488 | * for a setuid root binary run by a non-root user. Do set it |
486 | * for a root user just to cause least surprise to an admin. | 489 | * for a root user just to cause least surprise to an admin. |
487 | */ | 490 | */ |
488 | if (has_cap && new->uid != 0 && new->euid == 0) { | 491 | if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) { |
489 | warn_setuid_and_fcaps_mixed(bprm->filename); | 492 | warn_setuid_and_fcaps_mixed(bprm->filename); |
490 | goto skip; | 493 | goto skip; |
491 | } | 494 | } |
@@ -496,12 +499,12 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
496 | * | 499 | * |
497 | * If only the real uid is 0, we do not set the effective bit. | 500 | * If only the real uid is 0, we do not set the effective bit. |
498 | */ | 501 | */ |
499 | if (new->euid == 0 || new->uid == 0) { | 502 | if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) { |
500 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | 503 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ |
501 | new->cap_permitted = cap_combine(old->cap_bset, | 504 | new->cap_permitted = cap_combine(old->cap_bset, |
502 | old->cap_inheritable); | 505 | old->cap_inheritable); |
503 | } | 506 | } |
504 | if (new->euid == 0) | 507 | if (uid_eq(new->euid, root_uid)) |
505 | effective = true; | 508 | effective = true; |
506 | } | 509 | } |
507 | skip: | 510 | skip: |
@@ -516,8 +519,8 @@ skip: | |||
516 | * | 519 | * |
517 | * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. | 520 | * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. |
518 | */ | 521 | */ |
519 | if ((new->euid != old->uid || | 522 | if ((!uid_eq(new->euid, old->uid) || |
520 | new->egid != old->gid || | 523 | !gid_eq(new->egid, old->gid) || |
521 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && | 524 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && |
522 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { | 525 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { |
523 | /* downgrade; they get no more than they had, and maybe less */ | 526 | /* downgrade; they get no more than they had, and maybe less */ |
@@ -553,7 +556,7 @@ skip: | |||
553 | */ | 556 | */ |
554 | if (!cap_isclear(new->cap_effective)) { | 557 | if (!cap_isclear(new->cap_effective)) { |
555 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || | 558 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || |
556 | new->euid != 0 || new->uid != 0 || | 559 | !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) || |
557 | issecure(SECURE_NOROOT)) { | 560 | issecure(SECURE_NOROOT)) { |
558 | ret = audit_log_bprm_fcaps(bprm, new, old); | 561 | ret = audit_log_bprm_fcaps(bprm, new, old); |
559 | if (ret < 0) | 562 | if (ret < 0) |
@@ -578,16 +581,17 @@ skip: | |||
578 | int cap_bprm_secureexec(struct linux_binprm *bprm) | 581 | int cap_bprm_secureexec(struct linux_binprm *bprm) |
579 | { | 582 | { |
580 | const struct cred *cred = current_cred(); | 583 | const struct cred *cred = current_cred(); |
584 | kuid_t root_uid = make_kuid(cred->user_ns, 0); | ||
581 | 585 | ||
582 | if (cred->uid != 0) { | 586 | if (!uid_eq(cred->uid, root_uid)) { |
583 | if (bprm->cap_effective) | 587 | if (bprm->cap_effective) |
584 | return 1; | 588 | return 1; |
585 | if (!cap_isclear(cred->cap_permitted)) | 589 | if (!cap_isclear(cred->cap_permitted)) |
586 | return 1; | 590 | return 1; |
587 | } | 591 | } |
588 | 592 | ||
589 | return (cred->euid != cred->uid || | 593 | return (!uid_eq(cred->euid, cred->uid) || |
590 | cred->egid != cred->gid); | 594 | !gid_eq(cred->egid, cred->gid)); |
591 | } | 595 | } |
592 | 596 | ||
593 | /** | 597 | /** |
@@ -677,15 +681,21 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) | |||
677 | */ | 681 | */ |
678 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) | 682 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) |
679 | { | 683 | { |
680 | if ((old->uid == 0 || old->euid == 0 || old->suid == 0) && | 684 | kuid_t root_uid = make_kuid(old->user_ns, 0); |
681 | (new->uid != 0 && new->euid != 0 && new->suid != 0) && | 685 | |
686 | if ((uid_eq(old->uid, root_uid) || | ||
687 | uid_eq(old->euid, root_uid) || | ||
688 | uid_eq(old->suid, root_uid)) && | ||
689 | (!uid_eq(new->uid, root_uid) && | ||
690 | !uid_eq(new->euid, root_uid) && | ||
691 | !uid_eq(new->suid, root_uid)) && | ||
682 | !issecure(SECURE_KEEP_CAPS)) { | 692 | !issecure(SECURE_KEEP_CAPS)) { |
683 | cap_clear(new->cap_permitted); | 693 | cap_clear(new->cap_permitted); |
684 | cap_clear(new->cap_effective); | 694 | cap_clear(new->cap_effective); |
685 | } | 695 | } |
686 | if (old->euid == 0 && new->euid != 0) | 696 | if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid)) |
687 | cap_clear(new->cap_effective); | 697 | cap_clear(new->cap_effective); |
688 | if (old->euid != 0 && new->euid == 0) | 698 | if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid)) |
689 | new->cap_effective = new->cap_permitted; | 699 | new->cap_effective = new->cap_permitted; |
690 | } | 700 | } |
691 | 701 | ||
@@ -718,11 +728,12 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) | |||
718 | * if not, we might be a bit too harsh here. | 728 | * if not, we might be a bit too harsh here. |
719 | */ | 729 | */ |
720 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 730 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
721 | if (old->fsuid == 0 && new->fsuid != 0) | 731 | kuid_t root_uid = make_kuid(old->user_ns, 0); |
732 | if (uid_eq(old->fsuid, root_uid) && !uid_eq(new->fsuid, root_uid)) | ||
722 | new->cap_effective = | 733 | new->cap_effective = |
723 | cap_drop_fs_set(new->cap_effective); | 734 | cap_drop_fs_set(new->cap_effective); |
724 | 735 | ||
725 | if (old->fsuid != 0 && new->fsuid == 0) | 736 | if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid)) |
726 | new->cap_effective = | 737 | new->cap_effective = |
727 | cap_raise_fs_set(new->cap_effective, | 738 | cap_raise_fs_set(new->cap_effective, |
728 | new->cap_permitted); | 739 | new->cap_permitted); |
@@ -875,7 +886,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
875 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ | 886 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
876 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 887 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
877 | || (cap_capable(current_cred(), | 888 | || (cap_capable(current_cred(), |
878 | current_cred()->user->user_ns, CAP_SETPCAP, | 889 | current_cred()->user_ns, CAP_SETPCAP, |
879 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ | 890 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ |
880 | /* | 891 | /* |
881 | * [1] no changing of bits that are locked | 892 | * [1] no changing of bits that are locked |
@@ -947,22 +958,15 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) | |||
947 | } | 958 | } |
948 | 959 | ||
949 | /* | 960 | /* |
950 | * cap_file_mmap - check if able to map given addr | 961 | * cap_mmap_addr - check if able to map given addr |
951 | * @file: unused | ||
952 | * @reqprot: unused | ||
953 | * @prot: unused | ||
954 | * @flags: unused | ||
955 | * @addr: address attempting to be mapped | 962 | * @addr: address attempting to be mapped |
956 | * @addr_only: unused | ||
957 | * | 963 | * |
958 | * If the process is attempting to map memory below dac_mmap_min_addr they need | 964 | * If the process is attempting to map memory below dac_mmap_min_addr they need |
959 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the | 965 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the |
960 | * capability security module. Returns 0 if this mapping should be allowed | 966 | * capability security module. Returns 0 if this mapping should be allowed |
961 | * -EPERM if not. | 967 | * -EPERM if not. |
962 | */ | 968 | */ |
963 | int cap_file_mmap(struct file *file, unsigned long reqprot, | 969 | int cap_mmap_addr(unsigned long addr) |
964 | unsigned long prot, unsigned long flags, | ||
965 | unsigned long addr, unsigned long addr_only) | ||
966 | { | 970 | { |
967 | int ret = 0; | 971 | int ret = 0; |
968 | 972 | ||
@@ -975,3 +979,9 @@ int cap_file_mmap(struct file *file, unsigned long reqprot, | |||
975 | } | 979 | } |
976 | return ret; | 980 | return ret; |
977 | } | 981 | } |
982 | |||
983 | int cap_mmap_file(struct file *file, unsigned long reqprot, | ||
984 | unsigned long prot, unsigned long flags) | ||
985 | { | ||
986 | return 0; | ||
987 | } | ||
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index c43a3323feea..442204cc22d9 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -447,22 +447,16 @@ static struct cftype dev_cgroup_files[] = { | |||
447 | .read_seq_string = devcgroup_seq_read, | 447 | .read_seq_string = devcgroup_seq_read, |
448 | .private = DEVCG_LIST, | 448 | .private = DEVCG_LIST, |
449 | }, | 449 | }, |
450 | { } /* terminate */ | ||
450 | }; | 451 | }; |
451 | 452 | ||
452 | static int devcgroup_populate(struct cgroup_subsys *ss, | ||
453 | struct cgroup *cgroup) | ||
454 | { | ||
455 | return cgroup_add_files(cgroup, ss, dev_cgroup_files, | ||
456 | ARRAY_SIZE(dev_cgroup_files)); | ||
457 | } | ||
458 | |||
459 | struct cgroup_subsys devices_subsys = { | 453 | struct cgroup_subsys devices_subsys = { |
460 | .name = "devices", | 454 | .name = "devices", |
461 | .can_attach = devcgroup_can_attach, | 455 | .can_attach = devcgroup_can_attach, |
462 | .create = devcgroup_create, | 456 | .create = devcgroup_create, |
463 | .destroy = devcgroup_destroy, | 457 | .destroy = devcgroup_destroy, |
464 | .populate = devcgroup_populate, | ||
465 | .subsys_id = devices_subsys_id, | 458 | .subsys_id = devices_subsys_id, |
459 | .base_cftypes = dev_cgroup_files, | ||
466 | }; | 460 | }; |
467 | 461 | ||
468 | int __devcgroup_inode_permission(struct inode *inode, int mask) | 462 | int __devcgroup_inode_permission(struct inode *inode, int mask) |
diff --git a/security/keys/compat.c b/security/keys/compat.c index e35ae1d208a8..1c261763f479 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -38,7 +38,7 @@ static long compat_keyctl_instantiate_key_iov( | |||
38 | 38 | ||
39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
40 | ARRAY_SIZE(iovstack), | 40 | ARRAY_SIZE(iovstack), |
41 | iovstack, &iov, 1); | 41 | iovstack, &iov); |
42 | if (ret < 0) | 42 | if (ret < 0) |
43 | return ret; | 43 | return ret; |
44 | if (ret == 0) | 44 | if (ret == 0) |
diff --git a/security/keys/internal.h b/security/keys/internal.h index f173be2ce3ea..c990b8c8ef1d 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/key-type.h> | 16 | #include <linux/key-type.h> |
17 | #include <linux/task_work.h> | ||
17 | 18 | ||
18 | #ifdef __KDEBUG | 19 | #ifdef __KDEBUG |
19 | #define kenter(FMT, ...) \ | 20 | #define kenter(FMT, ...) \ |
@@ -148,6 +149,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | |||
148 | #define KEY_LOOKUP_FOR_UNLINK 0x04 | 149 | #define KEY_LOOKUP_FOR_UNLINK 0x04 |
149 | 150 | ||
150 | extern long join_session_keyring(const char *name); | 151 | extern long join_session_keyring(const char *name); |
152 | extern void key_change_session_keyring(struct task_work *twork); | ||
151 | 153 | ||
152 | extern struct work_struct key_gc_work; | 154 | extern struct work_struct key_gc_work; |
153 | extern unsigned key_gc_delay; | 155 | extern unsigned key_gc_delay; |
diff --git a/security/keys/key.c b/security/keys/key.c index c9bf66ac36e0..50d96d4e06f2 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -253,7 +253,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
253 | quotalen = desclen + type->def_datalen; | 253 | quotalen = desclen + type->def_datalen; |
254 | 254 | ||
255 | /* get hold of the key tracking for this user */ | 255 | /* get hold of the key tracking for this user */ |
256 | user = key_user_lookup(uid, cred->user->user_ns); | 256 | user = key_user_lookup(uid, cred->user_ns); |
257 | if (!user) | 257 | if (!user) |
258 | goto no_memory_1; | 258 | goto no_memory_1; |
259 | 259 | ||
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b61c063888b9..3bdc419b272f 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -84,7 +84,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
84 | vm = false; | 84 | vm = false; |
85 | if (_payload) { | 85 | if (_payload) { |
86 | ret = -ENOMEM; | 86 | ret = -ENOMEM; |
87 | payload = kmalloc(plen, GFP_KERNEL); | 87 | payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN); |
88 | if (!payload) { | 88 | if (!payload) { |
89 | if (plen <= PAGE_SIZE) | 89 | if (plen <= PAGE_SIZE) |
90 | goto error2; | 90 | goto error2; |
@@ -1110,7 +1110,7 @@ long keyctl_instantiate_key_iov(key_serial_t id, | |||
1110 | goto no_payload; | 1110 | goto no_payload; |
1111 | 1111 | ||
1112 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 1112 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
1113 | ARRAY_SIZE(iovstack), iovstack, &iov, 1); | 1113 | ARRAY_SIZE(iovstack), iovstack, &iov); |
1114 | if (ret < 0) | 1114 | if (ret < 0) |
1115 | return ret; | 1115 | return ret; |
1116 | if (ret == 0) | 1116 | if (ret == 0) |
@@ -1454,50 +1454,57 @@ long keyctl_get_security(key_serial_t keyid, | |||
1454 | */ | 1454 | */ |
1455 | long keyctl_session_to_parent(void) | 1455 | long keyctl_session_to_parent(void) |
1456 | { | 1456 | { |
1457 | #ifdef TIF_NOTIFY_RESUME | ||
1458 | struct task_struct *me, *parent; | 1457 | struct task_struct *me, *parent; |
1459 | const struct cred *mycred, *pcred; | 1458 | const struct cred *mycred, *pcred; |
1460 | struct cred *cred, *oldcred; | 1459 | struct task_work *newwork, *oldwork; |
1461 | key_ref_t keyring_r; | 1460 | key_ref_t keyring_r; |
1461 | struct cred *cred; | ||
1462 | int ret; | 1462 | int ret; |
1463 | 1463 | ||
1464 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); | 1464 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); |
1465 | if (IS_ERR(keyring_r)) | 1465 | if (IS_ERR(keyring_r)) |
1466 | return PTR_ERR(keyring_r); | 1466 | return PTR_ERR(keyring_r); |
1467 | 1467 | ||
1468 | ret = -ENOMEM; | ||
1469 | newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL); | ||
1470 | if (!newwork) | ||
1471 | goto error_keyring; | ||
1472 | |||
1468 | /* our parent is going to need a new cred struct, a new tgcred struct | 1473 | /* our parent is going to need a new cred struct, a new tgcred struct |
1469 | * and new security data, so we allocate them here to prevent ENOMEM in | 1474 | * and new security data, so we allocate them here to prevent ENOMEM in |
1470 | * our parent */ | 1475 | * our parent */ |
1471 | ret = -ENOMEM; | ||
1472 | cred = cred_alloc_blank(); | 1476 | cred = cred_alloc_blank(); |
1473 | if (!cred) | 1477 | if (!cred) |
1474 | goto error_keyring; | 1478 | goto error_newwork; |
1475 | 1479 | ||
1476 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); | 1480 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); |
1477 | keyring_r = NULL; | 1481 | init_task_work(newwork, key_change_session_keyring, cred); |
1478 | 1482 | ||
1479 | me = current; | 1483 | me = current; |
1480 | rcu_read_lock(); | 1484 | rcu_read_lock(); |
1481 | write_lock_irq(&tasklist_lock); | 1485 | write_lock_irq(&tasklist_lock); |
1482 | 1486 | ||
1483 | parent = me->real_parent; | ||
1484 | ret = -EPERM; | 1487 | ret = -EPERM; |
1488 | oldwork = NULL; | ||
1489 | parent = me->real_parent; | ||
1485 | 1490 | ||
1486 | /* the parent mustn't be init and mustn't be a kernel thread */ | 1491 | /* the parent mustn't be init and mustn't be a kernel thread */ |
1487 | if (parent->pid <= 1 || !parent->mm) | 1492 | if (parent->pid <= 1 || !parent->mm) |
1488 | goto not_permitted; | 1493 | goto unlock; |
1489 | 1494 | ||
1490 | /* the parent must be single threaded */ | 1495 | /* the parent must be single threaded */ |
1491 | if (!thread_group_empty(parent)) | 1496 | if (!thread_group_empty(parent)) |
1492 | goto not_permitted; | 1497 | goto unlock; |
1493 | 1498 | ||
1494 | /* the parent and the child must have different session keyrings or | 1499 | /* the parent and the child must have different session keyrings or |
1495 | * there's no point */ | 1500 | * there's no point */ |
1496 | mycred = current_cred(); | 1501 | mycred = current_cred(); |
1497 | pcred = __task_cred(parent); | 1502 | pcred = __task_cred(parent); |
1498 | if (mycred == pcred || | 1503 | if (mycred == pcred || |
1499 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) | 1504 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) { |
1500 | goto already_same; | 1505 | ret = 0; |
1506 | goto unlock; | ||
1507 | } | ||
1501 | 1508 | ||
1502 | /* the parent must have the same effective ownership and mustn't be | 1509 | /* the parent must have the same effective ownership and mustn't be |
1503 | * SUID/SGID */ | 1510 | * SUID/SGID */ |
@@ -1507,50 +1514,40 @@ long keyctl_session_to_parent(void) | |||
1507 | pcred->gid != mycred->egid || | 1514 | pcred->gid != mycred->egid || |
1508 | pcred->egid != mycred->egid || | 1515 | pcred->egid != mycred->egid || |
1509 | pcred->sgid != mycred->egid) | 1516 | pcred->sgid != mycred->egid) |
1510 | goto not_permitted; | 1517 | goto unlock; |
1511 | 1518 | ||
1512 | /* the keyrings must have the same UID */ | 1519 | /* the keyrings must have the same UID */ |
1513 | if ((pcred->tgcred->session_keyring && | 1520 | if ((pcred->tgcred->session_keyring && |
1514 | pcred->tgcred->session_keyring->uid != mycred->euid) || | 1521 | pcred->tgcred->session_keyring->uid != mycred->euid) || |
1515 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1522 | mycred->tgcred->session_keyring->uid != mycred->euid) |
1516 | goto not_permitted; | 1523 | goto unlock; |
1517 | 1524 | ||
1518 | /* if there's an already pending keyring replacement, then we replace | 1525 | /* cancel an already pending keyring replacement */ |
1519 | * that */ | 1526 | oldwork = task_work_cancel(parent, key_change_session_keyring); |
1520 | oldcred = parent->replacement_session_keyring; | ||
1521 | 1527 | ||
1522 | /* the replacement session keyring is applied just prior to userspace | 1528 | /* the replacement session keyring is applied just prior to userspace |
1523 | * restarting */ | 1529 | * restarting */ |
1524 | parent->replacement_session_keyring = cred; | 1530 | ret = task_work_add(parent, newwork, true); |
1525 | cred = NULL; | 1531 | if (!ret) |
1526 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); | 1532 | newwork = NULL; |
1527 | 1533 | unlock: | |
1528 | write_unlock_irq(&tasklist_lock); | ||
1529 | rcu_read_unlock(); | ||
1530 | if (oldcred) | ||
1531 | put_cred(oldcred); | ||
1532 | return 0; | ||
1533 | |||
1534 | already_same: | ||
1535 | ret = 0; | ||
1536 | not_permitted: | ||
1537 | write_unlock_irq(&tasklist_lock); | 1534 | write_unlock_irq(&tasklist_lock); |
1538 | rcu_read_unlock(); | 1535 | rcu_read_unlock(); |
1539 | put_cred(cred); | 1536 | if (oldwork) { |
1537 | put_cred(oldwork->data); | ||
1538 | kfree(oldwork); | ||
1539 | } | ||
1540 | if (newwork) { | ||
1541 | put_cred(newwork->data); | ||
1542 | kfree(newwork); | ||
1543 | } | ||
1540 | return ret; | 1544 | return ret; |
1541 | 1545 | ||
1546 | error_newwork: | ||
1547 | kfree(newwork); | ||
1542 | error_keyring: | 1548 | error_keyring: |
1543 | key_ref_put(keyring_r); | 1549 | key_ref_put(keyring_r); |
1544 | return ret; | 1550 | return ret; |
1545 | |||
1546 | #else /* !TIF_NOTIFY_RESUME */ | ||
1547 | /* | ||
1548 | * To be removed when TIF_NOTIFY_RESUME has been implemented on | ||
1549 | * m68k/xtensa | ||
1550 | */ | ||
1551 | #warning TIF_NOTIFY_RESUME not implemented | ||
1552 | return -EOPNOTSUPP; | ||
1553 | #endif /* !TIF_NOTIFY_RESUME */ | ||
1554 | } | 1551 | } |
1555 | 1552 | ||
1556 | /* | 1553 | /* |
diff --git a/security/keys/permission.c b/security/keys/permission.c index 57d96363d7f1..0b4d019e027d 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -36,7 +36,7 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
36 | 36 | ||
37 | key = key_ref_to_ptr(key_ref); | 37 | key = key_ref_to_ptr(key_ref); |
38 | 38 | ||
39 | if (key->user->user_ns != cred->user->user_ns) | 39 | if (key->user->user_ns != cred->user_ns) |
40 | goto use_other_perms; | 40 | goto use_other_perms; |
41 | 41 | ||
42 | /* use the second 8-bits of permissions for keys the caller owns */ | 42 | /* use the second 8-bits of permissions for keys the caller owns */ |
@@ -53,7 +53,8 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
53 | goto use_these_perms; | 53 | goto use_these_perms; |
54 | } | 54 | } |
55 | 55 | ||
56 | ret = groups_search(cred->group_info, key->gid); | 56 | ret = groups_search(cred->group_info, |
57 | make_kgid(current_user_ns(), key->gid)); | ||
57 | if (ret) { | 58 | if (ret) { |
58 | kperm = key->perm >> 8; | 59 | kperm = key->perm >> 8; |
59 | goto use_these_perms; | 60 | goto use_these_perms; |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index e137fcd7042c..4ad54eea1ea4 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -834,23 +834,17 @@ error: | |||
834 | * Replace a process's session keyring on behalf of one of its children when | 834 | * Replace a process's session keyring on behalf of one of its children when |
835 | * the target process is about to resume userspace execution. | 835 | * the target process is about to resume userspace execution. |
836 | */ | 836 | */ |
837 | void key_replace_session_keyring(void) | 837 | void key_change_session_keyring(struct task_work *twork) |
838 | { | 838 | { |
839 | const struct cred *old; | 839 | const struct cred *old = current_cred(); |
840 | struct cred *new; | 840 | struct cred *new = twork->data; |
841 | |||
842 | if (!current->replacement_session_keyring) | ||
843 | return; | ||
844 | 841 | ||
845 | write_lock_irq(&tasklist_lock); | 842 | kfree(twork); |
846 | new = current->replacement_session_keyring; | 843 | if (unlikely(current->flags & PF_EXITING)) { |
847 | current->replacement_session_keyring = NULL; | 844 | put_cred(new); |
848 | write_unlock_irq(&tasklist_lock); | ||
849 | |||
850 | if (!new) | ||
851 | return; | 845 | return; |
846 | } | ||
852 | 847 | ||
853 | old = current_cred(); | ||
854 | new-> uid = old-> uid; | 848 | new-> uid = old-> uid; |
855 | new-> euid = old-> euid; | 849 | new-> euid = old-> euid; |
856 | new-> suid = old-> suid; | 850 | new-> suid = old-> suid; |
@@ -860,7 +854,7 @@ void key_replace_session_keyring(void) | |||
860 | new-> sgid = old-> sgid; | 854 | new-> sgid = old-> sgid; |
861 | new->fsgid = old->fsgid; | 855 | new->fsgid = old->fsgid; |
862 | new->user = get_uid(old->user); | 856 | new->user = get_uid(old->user); |
863 | new->user_ns = new->user->user_ns; | 857 | new->user_ns = get_user_ns(new->user_ns); |
864 | new->group_info = get_group_info(old->group_info); | 858 | new->group_info = get_group_info(old->group_info); |
865 | 859 | ||
866 | new->securebits = old->securebits; | 860 | new->securebits = old->securebits; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index cc3790315d2f..000e75017520 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -93,16 +93,9 @@ static void umh_keys_cleanup(struct subprocess_info *info) | |||
93 | static int call_usermodehelper_keys(char *path, char **argv, char **envp, | 93 | static int call_usermodehelper_keys(char *path, char **argv, char **envp, |
94 | struct key *session_keyring, int wait) | 94 | struct key *session_keyring, int wait) |
95 | { | 95 | { |
96 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; | 96 | return call_usermodehelper_fns(path, argv, envp, wait, |
97 | struct subprocess_info *info = | 97 | umh_keys_init, umh_keys_cleanup, |
98 | call_usermodehelper_setup(path, argv, envp, gfp_mask); | 98 | key_get(session_keyring)); |
99 | |||
100 | if (!info) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | call_usermodehelper_setfns(info, umh_keys_init, umh_keys_cleanup, | ||
104 | key_get(session_keyring)); | ||
105 | return call_usermodehelper_exec(info, wait); | ||
106 | } | 99 | } |
107 | 100 | ||
108 | /* | 101 | /* |
diff --git a/security/security.c b/security/security.c index 5497a57fba01..3efc9b12aef4 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <linux/ima.h> | 20 | #include <linux/ima.h> |
21 | #include <linux/evm.h> | 21 | #include <linux/evm.h> |
22 | #include <linux/fsnotify.h> | 22 | #include <linux/fsnotify.h> |
23 | #include <linux/mman.h> | ||
24 | #include <linux/mount.h> | ||
25 | #include <linux/personality.h> | ||
23 | #include <net/flow.h> | 26 | #include <net/flow.h> |
24 | 27 | ||
25 | #define MAX_LSM_EVM_XATTR 2 | 28 | #define MAX_LSM_EVM_XATTR 2 |
@@ -657,18 +660,56 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
657 | return security_ops->file_ioctl(file, cmd, arg); | 660 | return security_ops->file_ioctl(file, cmd, arg); |
658 | } | 661 | } |
659 | 662 | ||
660 | int security_file_mmap(struct file *file, unsigned long reqprot, | 663 | static inline unsigned long mmap_prot(struct file *file, unsigned long prot) |
661 | unsigned long prot, unsigned long flags, | ||
662 | unsigned long addr, unsigned long addr_only) | ||
663 | { | 664 | { |
664 | int ret; | 665 | /* |
666 | * Does we have PROT_READ and does the application expect | ||
667 | * it to imply PROT_EXEC? If not, nothing to talk about... | ||
668 | */ | ||
669 | if ((prot & (PROT_READ | PROT_EXEC)) != PROT_READ) | ||
670 | return prot; | ||
671 | if (!(current->personality & READ_IMPLIES_EXEC)) | ||
672 | return prot; | ||
673 | /* | ||
674 | * if that's an anonymous mapping, let it. | ||
675 | */ | ||
676 | if (!file) | ||
677 | return prot | PROT_EXEC; | ||
678 | /* | ||
679 | * ditto if it's not on noexec mount, except that on !MMU we need | ||
680 | * BDI_CAP_EXEC_MMAP (== VM_MAYEXEC) in this case | ||
681 | */ | ||
682 | if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { | ||
683 | #ifndef CONFIG_MMU | ||
684 | unsigned long caps = 0; | ||
685 | struct address_space *mapping = file->f_mapping; | ||
686 | if (mapping && mapping->backing_dev_info) | ||
687 | caps = mapping->backing_dev_info->capabilities; | ||
688 | if (!(caps & BDI_CAP_EXEC_MAP)) | ||
689 | return prot; | ||
690 | #endif | ||
691 | return prot | PROT_EXEC; | ||
692 | } | ||
693 | /* anything on noexec mount won't get PROT_EXEC */ | ||
694 | return prot; | ||
695 | } | ||
665 | 696 | ||
666 | ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); | 697 | int security_mmap_file(struct file *file, unsigned long prot, |
698 | unsigned long flags) | ||
699 | { | ||
700 | int ret; | ||
701 | ret = security_ops->mmap_file(file, prot, | ||
702 | mmap_prot(file, prot), flags); | ||
667 | if (ret) | 703 | if (ret) |
668 | return ret; | 704 | return ret; |
669 | return ima_file_mmap(file, prot); | 705 | return ima_file_mmap(file, prot); |
670 | } | 706 | } |
671 | 707 | ||
708 | int security_mmap_addr(unsigned long addr) | ||
709 | { | ||
710 | return security_ops->mmap_addr(addr); | ||
711 | } | ||
712 | |||
672 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 713 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
673 | unsigned long prot) | 714 | unsigned long prot) |
674 | { | 715 | { |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fa2341b68331..372ec6502aa8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -3083,9 +3083,7 @@ error: | |||
3083 | return rc; | 3083 | return rc; |
3084 | } | 3084 | } |
3085 | 3085 | ||
3086 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, | 3086 | static int selinux_mmap_addr(unsigned long addr) |
3087 | unsigned long prot, unsigned long flags, | ||
3088 | unsigned long addr, unsigned long addr_only) | ||
3089 | { | 3087 | { |
3090 | int rc = 0; | 3088 | int rc = 0; |
3091 | u32 sid = current_sid(); | 3089 | u32 sid = current_sid(); |
@@ -3104,10 +3102,12 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot, | |||
3104 | } | 3102 | } |
3105 | 3103 | ||
3106 | /* do DAC check on address space usage */ | 3104 | /* do DAC check on address space usage */ |
3107 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | 3105 | return cap_mmap_addr(addr); |
3108 | if (rc || addr_only) | 3106 | } |
3109 | return rc; | ||
3110 | 3107 | ||
3108 | static int selinux_mmap_file(struct file *file, unsigned long reqprot, | ||
3109 | unsigned long prot, unsigned long flags) | ||
3110 | { | ||
3111 | if (selinux_checkreqprot) | 3111 | if (selinux_checkreqprot) |
3112 | prot = reqprot; | 3112 | prot = reqprot; |
3113 | 3113 | ||
@@ -5570,7 +5570,8 @@ static struct security_operations selinux_ops = { | |||
5570 | .file_alloc_security = selinux_file_alloc_security, | 5570 | .file_alloc_security = selinux_file_alloc_security, |
5571 | .file_free_security = selinux_file_free_security, | 5571 | .file_free_security = selinux_file_free_security, |
5572 | .file_ioctl = selinux_file_ioctl, | 5572 | .file_ioctl = selinux_file_ioctl, |
5573 | .file_mmap = selinux_file_mmap, | 5573 | .mmap_file = selinux_mmap_file, |
5574 | .mmap_addr = selinux_mmap_addr, | ||
5574 | .file_mprotect = selinux_file_mprotect, | 5575 | .file_mprotect = selinux_file_mprotect, |
5575 | .file_lock = selinux_file_lock, | 5576 | .file_lock = selinux_file_lock, |
5576 | .file_fcntl = selinux_file_fcntl, | 5577 | .file_fcntl = selinux_file_fcntl, |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 0920ea3bf599..d309e7f472d8 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/netlink.h> | 14 | #include <linux/netlink.h> |
15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
16 | #include <linux/if.h> | 16 | #include <linux/if.h> |
17 | #include <linux/netfilter_ipv4/ip_queue.h> | ||
18 | #include <linux/inet_diag.h> | 17 | #include <linux/inet_diag.h> |
19 | #include <linux/xfrm.h> | 18 | #include <linux/xfrm.h> |
20 | #include <linux/audit.h> | 19 | #include <linux/audit.h> |
@@ -70,12 +69,6 @@ static struct nlmsg_perm nlmsg_route_perms[] = | |||
70 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 69 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
71 | }; | 70 | }; |
72 | 71 | ||
73 | static struct nlmsg_perm nlmsg_firewall_perms[] = | ||
74 | { | ||
75 | { IPQM_MODE, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE }, | ||
76 | { IPQM_VERDICT, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE }, | ||
77 | }; | ||
78 | |||
79 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | 72 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = |
80 | { | 73 | { |
81 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 74 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
@@ -145,12 +138,6 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) | |||
145 | sizeof(nlmsg_route_perms)); | 138 | sizeof(nlmsg_route_perms)); |
146 | break; | 139 | break; |
147 | 140 | ||
148 | case SECCLASS_NETLINK_FIREWALL_SOCKET: | ||
149 | case SECCLASS_NETLINK_IP6FW_SOCKET: | ||
150 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms, | ||
151 | sizeof(nlmsg_firewall_perms)); | ||
152 | break; | ||
153 | |||
154 | case SECCLASS_NETLINK_TCPDIAG_SOCKET: | 141 | case SECCLASS_NETLINK_TCPDIAG_SOCKET: |
155 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms, | 142 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms, |
156 | sizeof(nlmsg_tcpdiag_perms)); | 143 | sizeof(nlmsg_tcpdiag_perms)); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 4e93f9ef970b..3ad290251288 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -1259,12 +1259,8 @@ static int sel_make_bools(void) | |||
1259 | if (!inode) | 1259 | if (!inode) |
1260 | goto out; | 1260 | goto out; |
1261 | 1261 | ||
1262 | ret = -EINVAL; | ||
1263 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | ||
1264 | if (len < 0) | ||
1265 | goto out; | ||
1266 | |||
1267 | ret = -ENAMETOOLONG; | 1262 | ret = -ENAMETOOLONG; |
1263 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | ||
1268 | if (len >= PAGE_SIZE) | 1264 | if (len >= PAGE_SIZE) |
1269 | goto out; | 1265 | goto out; |
1270 | 1266 | ||
@@ -1557,19 +1553,10 @@ static inline u32 sel_ino_to_perm(unsigned long ino) | |||
1557 | static ssize_t sel_read_class(struct file *file, char __user *buf, | 1553 | static ssize_t sel_read_class(struct file *file, char __user *buf, |
1558 | size_t count, loff_t *ppos) | 1554 | size_t count, loff_t *ppos) |
1559 | { | 1555 | { |
1560 | ssize_t rc, len; | ||
1561 | char *page; | ||
1562 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1556 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1563 | 1557 | char res[TMPBUFLEN]; | |
1564 | page = (char *)__get_free_page(GFP_KERNEL); | 1558 | ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_class(ino)); |
1565 | if (!page) | 1559 | return simple_read_from_buffer(buf, count, ppos, res, len); |
1566 | return -ENOMEM; | ||
1567 | |||
1568 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); | ||
1569 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | ||
1570 | free_page((unsigned long)page); | ||
1571 | |||
1572 | return rc; | ||
1573 | } | 1560 | } |
1574 | 1561 | ||
1575 | static const struct file_operations sel_class_ops = { | 1562 | static const struct file_operations sel_class_ops = { |
@@ -1580,19 +1567,10 @@ static const struct file_operations sel_class_ops = { | |||
1580 | static ssize_t sel_read_perm(struct file *file, char __user *buf, | 1567 | static ssize_t sel_read_perm(struct file *file, char __user *buf, |
1581 | size_t count, loff_t *ppos) | 1568 | size_t count, loff_t *ppos) |
1582 | { | 1569 | { |
1583 | ssize_t rc, len; | ||
1584 | char *page; | ||
1585 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1570 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1586 | 1571 | char res[TMPBUFLEN]; | |
1587 | page = (char *)__get_free_page(GFP_KERNEL); | 1572 | ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_perm(ino)); |
1588 | if (!page) | 1573 | return simple_read_from_buffer(buf, count, ppos, res, len); |
1589 | return -ENOMEM; | ||
1590 | |||
1591 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); | ||
1592 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | ||
1593 | free_page((unsigned long)page); | ||
1594 | |||
1595 | return rc; | ||
1596 | } | 1574 | } |
1597 | 1575 | ||
1598 | static const struct file_operations sel_perm_ops = { | 1576 | static const struct file_operations sel_perm_ops = { |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d583c0545808..ee0bb5735f35 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -1171,7 +1171,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | /** | 1173 | /** |
1174 | * smack_file_mmap : | 1174 | * smack_mmap_file : |
1175 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | 1175 | * Check permissions for a mmap operation. The @file may be NULL, e.g. |
1176 | * if mapping anonymous memory. | 1176 | * if mapping anonymous memory. |
1177 | * @file contains the file structure for file to map (may be NULL). | 1177 | * @file contains the file structure for file to map (may be NULL). |
@@ -1180,10 +1180,9 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1180 | * @flags contains the operational flags. | 1180 | * @flags contains the operational flags. |
1181 | * Return 0 if permission is granted. | 1181 | * Return 0 if permission is granted. |
1182 | */ | 1182 | */ |
1183 | static int smack_file_mmap(struct file *file, | 1183 | static int smack_mmap_file(struct file *file, |
1184 | unsigned long reqprot, unsigned long prot, | 1184 | unsigned long reqprot, unsigned long prot, |
1185 | unsigned long flags, unsigned long addr, | 1185 | unsigned long flags) |
1186 | unsigned long addr_only) | ||
1187 | { | 1186 | { |
1188 | struct smack_known *skp; | 1187 | struct smack_known *skp; |
1189 | struct smack_rule *srp; | 1188 | struct smack_rule *srp; |
@@ -1198,11 +1197,6 @@ static int smack_file_mmap(struct file *file, | |||
1198 | int tmay; | 1197 | int tmay; |
1199 | int rc; | 1198 | int rc; |
1200 | 1199 | ||
1201 | /* do DAC check on address space usage */ | ||
1202 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
1203 | if (rc || addr_only) | ||
1204 | return rc; | ||
1205 | |||
1206 | if (file == NULL || file->f_dentry == NULL) | 1200 | if (file == NULL || file->f_dentry == NULL) |
1207 | return 0; | 1201 | return 0; |
1208 | 1202 | ||
@@ -3482,7 +3476,8 @@ struct security_operations smack_ops = { | |||
3482 | .file_ioctl = smack_file_ioctl, | 3476 | .file_ioctl = smack_file_ioctl, |
3483 | .file_lock = smack_file_lock, | 3477 | .file_lock = smack_file_lock, |
3484 | .file_fcntl = smack_file_fcntl, | 3478 | .file_fcntl = smack_file_fcntl, |
3485 | .file_mmap = smack_file_mmap, | 3479 | .mmap_file = smack_mmap_file, |
3480 | .mmap_addr = cap_mmap_addr, | ||
3486 | .file_set_fowner = smack_file_set_fowner, | 3481 | .file_set_fowner = smack_file_set_fowner, |
3487 | .file_send_sigiotask = smack_file_send_sigiotask, | 3482 | .file_send_sigiotask = smack_file_send_sigiotask, |
3488 | .file_receive = smack_file_receive, | 3483 | .file_receive = smack_file_receive, |