diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/capability.c | 12 | ||||
| -rw-r--r-- | kernel/fork.c | 5 | ||||
| -rw-r--r-- | kernel/groups.c | 2 | ||||
| -rw-r--r-- | kernel/nsproxy.c | 36 | ||||
| -rw-r--r-- | kernel/pid.c | 1 | ||||
| -rw-r--r-- | kernel/pid_namespace.c | 2 | ||||
| -rw-r--r-- | kernel/sys.c | 20 | ||||
| -rw-r--r-- | kernel/uid16.c | 2 | ||||
| -rw-r--r-- | kernel/user.c | 2 | ||||
| -rw-r--r-- | kernel/user_namespace.c | 2 | ||||
| -rw-r--r-- | kernel/utsname.c | 2 |
11 files changed, 27 insertions, 59 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index f6c2ce5701e1..6fc1c8af44df 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
| @@ -433,18 +433,6 @@ bool capable(int cap) | |||
| 433 | EXPORT_SYMBOL(capable); | 433 | EXPORT_SYMBOL(capable); |
| 434 | 434 | ||
| 435 | /** | 435 | /** |
| 436 | * nsown_capable - Check superior capability to one's own user_ns | ||
| 437 | * @cap: The capability in question | ||
| 438 | * | ||
| 439 | * Return true if the current task has the given superior capability | ||
| 440 | * targeted at its own user namespace. | ||
| 441 | */ | ||
| 442 | bool nsown_capable(int cap) | ||
| 443 | { | ||
| 444 | return ns_capable(current_user_ns(), cap); | ||
| 445 | } | ||
| 446 | |||
| 447 | /** | ||
| 448 | * inode_capable - Check superior capability over inode | 436 | * inode_capable - Check superior capability over inode |
| 449 | * @inode: The inode in question | 437 | * @inode: The inode in question |
| 450 | * @cap: The capability in question | 438 | * @cap: The capability in question |
diff --git a/kernel/fork.c b/kernel/fork.c index bf46287c91a4..c9eaf2013002 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1825,11 +1825,6 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
| 1825 | if (unshare_flags & CLONE_NEWUSER) | 1825 | if (unshare_flags & CLONE_NEWUSER) |
| 1826 | unshare_flags |= CLONE_THREAD | CLONE_FS; | 1826 | unshare_flags |= CLONE_THREAD | CLONE_FS; |
| 1827 | /* | 1827 | /* |
| 1828 | * If unsharing a pid namespace must also unshare the thread. | ||
| 1829 | */ | ||
| 1830 | if (unshare_flags & CLONE_NEWPID) | ||
| 1831 | unshare_flags |= CLONE_THREAD; | ||
| 1832 | /* | ||
| 1833 | * If unsharing a thread from a thread group, must also unshare vm. | 1828 | * If unsharing a thread from a thread group, must also unshare vm. |
| 1834 | */ | 1829 | */ |
| 1835 | if (unshare_flags & CLONE_THREAD) | 1830 | if (unshare_flags & CLONE_THREAD) |
diff --git a/kernel/groups.c b/kernel/groups.c index 6b2588dd04ff..90cf1c38c8ea 100644 --- a/kernel/groups.c +++ b/kernel/groups.c | |||
| @@ -233,7 +233,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) | |||
| 233 | struct group_info *group_info; | 233 | struct group_info *group_info; |
| 234 | int retval; | 234 | int retval; |
| 235 | 235 | ||
| 236 | if (!nsown_capable(CAP_SETGID)) | 236 | if (!ns_capable(current_user_ns(), CAP_SETGID)) |
| 237 | return -EPERM; | 237 | return -EPERM; |
| 238 | if ((unsigned)gidsetsize > NGROUPS_MAX) | 238 | if ((unsigned)gidsetsize > NGROUPS_MAX) |
| 239 | return -EINVAL; | 239 | return -EINVAL; |
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 997cbb951a3b..8e7811086b82 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
| @@ -126,22 +126,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) | |||
| 126 | struct nsproxy *old_ns = tsk->nsproxy; | 126 | struct nsproxy *old_ns = tsk->nsproxy; |
| 127 | struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); | 127 | struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); |
| 128 | struct nsproxy *new_ns; | 128 | struct nsproxy *new_ns; |
| 129 | int err = 0; | ||
| 130 | 129 | ||
| 131 | if (!old_ns) | 130 | if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | |
| 131 | CLONE_NEWPID | CLONE_NEWNET)))) { | ||
| 132 | get_nsproxy(old_ns); | ||
| 132 | return 0; | 133 | return 0; |
| 133 | |||
| 134 | get_nsproxy(old_ns); | ||
| 135 | |||
| 136 | if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | | ||
| 137 | CLONE_NEWPID | CLONE_NEWNET))) | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) { | ||
| 141 | err = -EPERM; | ||
| 142 | goto out; | ||
| 143 | } | 134 | } |
| 144 | 135 | ||
| 136 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) | ||
| 137 | return -EPERM; | ||
| 138 | |||
| 145 | /* | 139 | /* |
| 146 | * CLONE_NEWIPC must detach from the undolist: after switching | 140 | * CLONE_NEWIPC must detach from the undolist: after switching |
| 147 | * to a new ipc namespace, the semaphore arrays from the old | 141 | * to a new ipc namespace, the semaphore arrays from the old |
| @@ -149,22 +143,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) | |||
| 149 | * means share undolist with parent, so we must forbid using | 143 | * means share undolist with parent, so we must forbid using |
| 150 | * it along with CLONE_NEWIPC. | 144 | * it along with CLONE_NEWIPC. |
| 151 | */ | 145 | */ |
| 152 | if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) { | 146 | if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) == |
| 153 | err = -EINVAL; | 147 | (CLONE_NEWIPC | CLONE_SYSVSEM)) |
| 154 | goto out; | 148 | return -EINVAL; |
| 155 | } | ||
| 156 | 149 | ||
| 157 | new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs); | 150 | new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs); |
| 158 | if (IS_ERR(new_ns)) { | 151 | if (IS_ERR(new_ns)) |
| 159 | err = PTR_ERR(new_ns); | 152 | return PTR_ERR(new_ns); |
| 160 | goto out; | ||
| 161 | } | ||
| 162 | 153 | ||
| 163 | tsk->nsproxy = new_ns; | 154 | tsk->nsproxy = new_ns; |
| 164 | 155 | return 0; | |
| 165 | out: | ||
| 166 | put_nsproxy(old_ns); | ||
| 167 | return err; | ||
| 168 | } | 156 | } |
| 169 | 157 | ||
| 170 | void free_nsproxy(struct nsproxy *ns) | 158 | void free_nsproxy(struct nsproxy *ns) |
diff --git a/kernel/pid.c b/kernel/pid.c index 66505c1dfc51..ebe5e80b10f8 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
| @@ -265,6 +265,7 @@ void free_pid(struct pid *pid) | |||
| 265 | struct pid_namespace *ns = upid->ns; | 265 | struct pid_namespace *ns = upid->ns; |
| 266 | hlist_del_rcu(&upid->pid_chain); | 266 | hlist_del_rcu(&upid->pid_chain); |
| 267 | switch(--ns->nr_hashed) { | 267 | switch(--ns->nr_hashed) { |
| 268 | case 2: | ||
| 268 | case 1: | 269 | case 1: |
| 269 | /* When all that is left in the pid namespace | 270 | /* When all that is left in the pid namespace |
| 270 | * is the reaper wake up the reaper. The reaper | 271 | * is the reaper wake up the reaper. The reaper |
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 601bb361c235..42086551a24a 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
| @@ -329,7 +329,7 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns) | |||
| 329 | struct pid_namespace *ancestor, *new = ns; | 329 | struct pid_namespace *ancestor, *new = ns; |
| 330 | 330 | ||
| 331 | if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) || | 331 | if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) || |
| 332 | !nsown_capable(CAP_SYS_ADMIN)) | 332 | !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) |
| 333 | return -EPERM; | 333 | return -EPERM; |
| 334 | 334 | ||
| 335 | /* | 335 | /* |
diff --git a/kernel/sys.c b/kernel/sys.c index 771129b299f8..c18ecca575b4 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -337,7 +337,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | |||
| 337 | if (rgid != (gid_t) -1) { | 337 | if (rgid != (gid_t) -1) { |
| 338 | if (gid_eq(old->gid, krgid) || | 338 | if (gid_eq(old->gid, krgid) || |
| 339 | gid_eq(old->egid, krgid) || | 339 | gid_eq(old->egid, krgid) || |
| 340 | nsown_capable(CAP_SETGID)) | 340 | ns_capable(old->user_ns, CAP_SETGID)) |
| 341 | new->gid = krgid; | 341 | new->gid = krgid; |
| 342 | else | 342 | else |
| 343 | goto error; | 343 | goto error; |
| @@ -346,7 +346,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | |||
| 346 | if (gid_eq(old->gid, kegid) || | 346 | if (gid_eq(old->gid, kegid) || |
| 347 | gid_eq(old->egid, kegid) || | 347 | gid_eq(old->egid, kegid) || |
| 348 | gid_eq(old->sgid, kegid) || | 348 | gid_eq(old->sgid, kegid) || |
| 349 | nsown_capable(CAP_SETGID)) | 349 | ns_capable(old->user_ns, CAP_SETGID)) |
| 350 | new->egid = kegid; | 350 | new->egid = kegid; |
| 351 | else | 351 | else |
| 352 | goto error; | 352 | goto error; |
| @@ -387,7 +387,7 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) | |||
| 387 | old = current_cred(); | 387 | old = current_cred(); |
| 388 | 388 | ||
| 389 | retval = -EPERM; | 389 | retval = -EPERM; |
| 390 | if (nsown_capable(CAP_SETGID)) | 390 | if (ns_capable(old->user_ns, CAP_SETGID)) |
| 391 | new->gid = new->egid = new->sgid = new->fsgid = kgid; | 391 | new->gid = new->egid = new->sgid = new->fsgid = kgid; |
| 392 | else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) | 392 | else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) |
| 393 | new->egid = new->fsgid = kgid; | 393 | new->egid = new->fsgid = kgid; |
| @@ -471,7 +471,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
| 471 | new->uid = kruid; | 471 | new->uid = kruid; |
| 472 | if (!uid_eq(old->uid, kruid) && | 472 | if (!uid_eq(old->uid, kruid) && |
| 473 | !uid_eq(old->euid, kruid) && | 473 | !uid_eq(old->euid, kruid) && |
| 474 | !nsown_capable(CAP_SETUID)) | 474 | !ns_capable(old->user_ns, CAP_SETUID)) |
| 475 | goto error; | 475 | goto error; |
| 476 | } | 476 | } |
| 477 | 477 | ||
| @@ -480,7 +480,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
| 480 | if (!uid_eq(old->uid, keuid) && | 480 | if (!uid_eq(old->uid, keuid) && |
| 481 | !uid_eq(old->euid, keuid) && | 481 | !uid_eq(old->euid, keuid) && |
| 482 | !uid_eq(old->suid, keuid) && | 482 | !uid_eq(old->suid, keuid) && |
| 483 | !nsown_capable(CAP_SETUID)) | 483 | !ns_capable(old->user_ns, CAP_SETUID)) |
| 484 | goto error; | 484 | goto error; |
| 485 | } | 485 | } |
| 486 | 486 | ||
| @@ -534,7 +534,7 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) | |||
| 534 | old = current_cred(); | 534 | old = current_cred(); |
| 535 | 535 | ||
| 536 | retval = -EPERM; | 536 | retval = -EPERM; |
| 537 | if (nsown_capable(CAP_SETUID)) { | 537 | if (ns_capable(old->user_ns, CAP_SETUID)) { |
| 538 | new->suid = new->uid = kuid; | 538 | new->suid = new->uid = kuid; |
| 539 | if (!uid_eq(kuid, old->uid)) { | 539 | if (!uid_eq(kuid, old->uid)) { |
| 540 | retval = set_user(new); | 540 | retval = set_user(new); |
| @@ -591,7 +591,7 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | |||
| 591 | old = current_cred(); | 591 | old = current_cred(); |
| 592 | 592 | ||
| 593 | retval = -EPERM; | 593 | retval = -EPERM; |
| 594 | if (!nsown_capable(CAP_SETUID)) { | 594 | if (!ns_capable(old->user_ns, CAP_SETUID)) { |
| 595 | if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && | 595 | if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
| 596 | !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) | 596 | !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) |
| 597 | goto error; | 597 | goto error; |
| @@ -673,7 +673,7 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) | |||
| 673 | old = current_cred(); | 673 | old = current_cred(); |
| 674 | 674 | ||
| 675 | retval = -EPERM; | 675 | retval = -EPERM; |
| 676 | if (!nsown_capable(CAP_SETGID)) { | 676 | if (!ns_capable(old->user_ns, CAP_SETGID)) { |
| 677 | if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && | 677 | if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
| 678 | !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) | 678 | !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) |
| 679 | goto error; | 679 | goto error; |
| @@ -744,7 +744,7 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) | |||
| 744 | 744 | ||
| 745 | if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) || | 745 | if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) || |
| 746 | uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || | 746 | uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || |
| 747 | nsown_capable(CAP_SETUID)) { | 747 | ns_capable(old->user_ns, CAP_SETUID)) { |
| 748 | if (!uid_eq(kuid, old->fsuid)) { | 748 | if (!uid_eq(kuid, old->fsuid)) { |
| 749 | new->fsuid = kuid; | 749 | new->fsuid = kuid; |
| 750 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) | 750 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) |
| @@ -783,7 +783,7 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) | |||
| 783 | 783 | ||
| 784 | if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) || | 784 | if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) || |
| 785 | gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || | 785 | gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || |
| 786 | nsown_capable(CAP_SETGID)) { | 786 | ns_capable(old->user_ns, CAP_SETGID)) { |
| 787 | if (!gid_eq(kgid, old->fsgid)) { | 787 | if (!gid_eq(kgid, old->fsgid)) { |
| 788 | new->fsgid = kgid; | 788 | new->fsgid = kgid; |
| 789 | goto change_okay; | 789 | goto change_okay; |
diff --git a/kernel/uid16.c b/kernel/uid16.c index f6c83d7ef000..602e5bbbceff 100644 --- a/kernel/uid16.c +++ b/kernel/uid16.c | |||
| @@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) | |||
| 176 | struct group_info *group_info; | 176 | struct group_info *group_info; |
| 177 | int retval; | 177 | int retval; |
| 178 | 178 | ||
| 179 | if (!nsown_capable(CAP_SETGID)) | 179 | if (!ns_capable(current_user_ns(), CAP_SETGID)) |
| 180 | return -EPERM; | 180 | return -EPERM; |
| 181 | if ((unsigned)gidsetsize > NGROUPS_MAX) | 181 | if ((unsigned)gidsetsize > NGROUPS_MAX) |
| 182 | return -EINVAL; | 182 | return -EINVAL; |
diff --git a/kernel/user.c b/kernel/user.c index 69b4c3d48cde..5bbb91988e69 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
| @@ -51,8 +51,6 @@ struct user_namespace init_user_ns = { | |||
| 51 | .owner = GLOBAL_ROOT_UID, | 51 | .owner = GLOBAL_ROOT_UID, |
| 52 | .group = GLOBAL_ROOT_GID, | 52 | .group = GLOBAL_ROOT_GID, |
| 53 | .proc_inum = PROC_USER_INIT_INO, | 53 | .proc_inum = PROC_USER_INIT_INO, |
| 54 | .may_mount_sysfs = true, | ||
| 55 | .may_mount_proc = true, | ||
| 56 | }; | 54 | }; |
| 57 | EXPORT_SYMBOL_GPL(init_user_ns); | 55 | EXPORT_SYMBOL_GPL(init_user_ns); |
| 58 | 56 | ||
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 9064b919a406..13fb1134ba58 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
| @@ -101,8 +101,6 @@ int create_user_ns(struct cred *new) | |||
| 101 | 101 | ||
| 102 | set_cred_user_ns(new, ns); | 102 | set_cred_user_ns(new, ns); |
| 103 | 103 | ||
| 104 | update_mnt_policy(ns); | ||
| 105 | |||
| 106 | return 0; | 104 | return 0; |
| 107 | } | 105 | } |
| 108 | 106 | ||
diff --git a/kernel/utsname.c b/kernel/utsname.c index 2fc8576efaa8..fd393124e507 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c | |||
| @@ -114,7 +114,7 @@ static int utsns_install(struct nsproxy *nsproxy, void *new) | |||
| 114 | struct uts_namespace *ns = new; | 114 | struct uts_namespace *ns = new; |
| 115 | 115 | ||
| 116 | if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || | 116 | if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || |
| 117 | !nsown_capable(CAP_SYS_ADMIN)) | 117 | !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) |
| 118 | return -EPERM; | 118 | return -EPERM; |
| 119 | 119 | ||
| 120 | get_uts_ns(ns); | 120 | get_uts_ns(ns); |
