aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge E. Hallyn <serge@hallyn.com>2011-03-23 19:43:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-23 22:47:08 -0400
commitb0e77598f87107001a00b8a4ece9c95e4254ccc4 (patch)
tree2738276570e4faa7c92a64521c192f04dca93801
parentb515498f5bb5f38fc0e390b4ff7d00b6077de127 (diff)
userns: user namespaces: convert several capable() calls
CAP_IPC_OWNER and CAP_IPC_LOCK can be checked against current_user_ns(), because the resource comes from current's own ipc namespace. setuid/setgid are to uids in own namespace, so again checks can be against current_user_ns(). Changelog: Jan 11: Use task_ns_capable() in place of sched_capable(). Jan 11: Use nsown_capable() as suggested by Bastian Blank. Jan 11: Clarify (hopefully) some logic in futex and sched.c Feb 15: use ns_capable for ipc, not nsown_capable Feb 23: let copy_ipcs handle setting ipc_ns->user_ns Feb 23: pass ns down rather than taking it from current [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: Daniel Lezcano <daniel.lezcano@free.fr> Acked-by: David Howells <dhowells@redhat.com> Cc: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/ipc_namespace.h7
-rw-r--r--ipc/msg.c8
-rw-r--r--ipc/namespace.c13
-rw-r--r--ipc/sem.c10
-rw-r--r--ipc/shm.c9
-rw-r--r--ipc/util.c26
-rw-r--r--ipc/util.h5
-rw-r--r--kernel/futex.c11
-rw-r--r--kernel/futex_compat.c11
-rw-r--r--kernel/groups.c2
-rw-r--r--kernel/nsproxy.c7
-rw-r--r--kernel/sched.c9
-rw-r--r--kernel/uid16.c2
13 files changed, 75 insertions, 45 deletions
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index d3c32dcec623..a6d1655f9607 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -5,6 +5,7 @@
5#include <linux/idr.h> 5#include <linux/idr.h>
6#include <linux/rwsem.h> 6#include <linux/rwsem.h>
7#include <linux/notifier.h> 7#include <linux/notifier.h>
8#include <linux/nsproxy.h>
8 9
9/* 10/*
10 * ipc namespace events 11 * ipc namespace events
@@ -93,7 +94,7 @@ static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; }
93 94
94#if defined(CONFIG_IPC_NS) 95#if defined(CONFIG_IPC_NS)
95extern struct ipc_namespace *copy_ipcs(unsigned long flags, 96extern struct ipc_namespace *copy_ipcs(unsigned long flags,
96 struct ipc_namespace *ns); 97 struct task_struct *tsk);
97static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) 98static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
98{ 99{
99 if (ns) 100 if (ns)
@@ -104,12 +105,12 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
104extern void put_ipc_ns(struct ipc_namespace *ns); 105extern void put_ipc_ns(struct ipc_namespace *ns);
105#else 106#else
106static inline struct ipc_namespace *copy_ipcs(unsigned long flags, 107static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
107 struct ipc_namespace *ns) 108 struct task_struct *tsk)
108{ 109{
109 if (flags & CLONE_NEWIPC) 110 if (flags & CLONE_NEWIPC)
110 return ERR_PTR(-EINVAL); 111 return ERR_PTR(-EINVAL);
111 112
112 return ns; 113 return tsk->nsproxy->ipc_ns;
113} 114}
114 115
115static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) 116static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
diff --git a/ipc/msg.c b/ipc/msg.c
index 747b65507a91..0e732e92e22f 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -421,7 +421,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
421 return -EFAULT; 421 return -EFAULT;
422 } 422 }
423 423
424 ipcp = ipcctl_pre_down(&msg_ids(ns), msqid, cmd, 424 ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid, cmd,
425 &msqid64.msg_perm, msqid64.msg_qbytes); 425 &msqid64.msg_perm, msqid64.msg_qbytes);
426 if (IS_ERR(ipcp)) 426 if (IS_ERR(ipcp))
427 return PTR_ERR(ipcp); 427 return PTR_ERR(ipcp);
@@ -539,7 +539,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
539 success_return = 0; 539 success_return = 0;
540 } 540 }
541 err = -EACCES; 541 err = -EACCES;
542 if (ipcperms(&msq->q_perm, S_IRUGO)) 542 if (ipcperms(ns, &msq->q_perm, S_IRUGO))
543 goto out_unlock; 543 goto out_unlock;
544 544
545 err = security_msg_queue_msgctl(msq, cmd); 545 err = security_msg_queue_msgctl(msq, cmd);
@@ -664,7 +664,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
664 struct msg_sender s; 664 struct msg_sender s;
665 665
666 err = -EACCES; 666 err = -EACCES;
667 if (ipcperms(&msq->q_perm, S_IWUGO)) 667 if (ipcperms(ns, &msq->q_perm, S_IWUGO))
668 goto out_unlock_free; 668 goto out_unlock_free;
669 669
670 err = security_msg_queue_msgsnd(msq, msg, msgflg); 670 err = security_msg_queue_msgsnd(msq, msg, msgflg);
@@ -774,7 +774,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
774 struct list_head *tmp; 774 struct list_head *tmp;
775 775
776 msg = ERR_PTR(-EACCES); 776 msg = ERR_PTR(-EACCES);
777 if (ipcperms(&msq->q_perm, S_IRUGO)) 777 if (ipcperms(ns, &msq->q_perm, S_IRUGO))
778 goto out_unlock; 778 goto out_unlock;
779 779
780 msg = ERR_PTR(-EAGAIN); 780 msg = ERR_PTR(-EAGAIN);
diff --git a/ipc/namespace.c b/ipc/namespace.c
index aa1889962693..3c3e5223e7e5 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -15,7 +15,8 @@
15 15
16#include "util.h" 16#include "util.h"
17 17
18static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns) 18static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
19 struct ipc_namespace *old_ns)
19{ 20{
20 struct ipc_namespace *ns; 21 struct ipc_namespace *ns;
21 int err; 22 int err;
@@ -44,17 +45,19 @@ static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns)
44 ipcns_notify(IPCNS_CREATED); 45 ipcns_notify(IPCNS_CREATED);
45 register_ipcns_notifier(ns); 46 register_ipcns_notifier(ns);
46 47
47 ns->user_ns = old_ns->user_ns; 48 ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns);
48 get_user_ns(ns->user_ns);
49 49
50 return ns; 50 return ns;
51} 51}
52 52
53struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) 53struct ipc_namespace *copy_ipcs(unsigned long flags,
54 struct task_struct *tsk)
54{ 55{
56 struct ipc_namespace *ns = tsk->nsproxy->ipc_ns;
57
55 if (!(flags & CLONE_NEWIPC)) 58 if (!(flags & CLONE_NEWIPC))
56 return get_ipc_ns(ns); 59 return get_ipc_ns(ns);
57 return create_ipc_ns(ns); 60 return create_ipc_ns(tsk, ns);
58} 61}
59 62
60/* 63/*
diff --git a/ipc/sem.c b/ipc/sem.c
index 0e0d49bbb867..ae040a0727c2 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -817,7 +817,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
817 } 817 }
818 818
819 err = -EACCES; 819 err = -EACCES;
820 if (ipcperms (&sma->sem_perm, S_IRUGO)) 820 if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
821 goto out_unlock; 821 goto out_unlock;
822 822
823 err = security_sem_semctl(sma, cmd); 823 err = security_sem_semctl(sma, cmd);
@@ -862,7 +862,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
862 nsems = sma->sem_nsems; 862 nsems = sma->sem_nsems;
863 863
864 err = -EACCES; 864 err = -EACCES;
865 if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO)) 865 if (ipcperms(ns, &sma->sem_perm,
866 (cmd == SETVAL || cmd == SETALL) ? S_IWUGO : S_IRUGO))
866 goto out_unlock; 867 goto out_unlock;
867 868
868 err = security_sem_semctl(sma, cmd); 869 err = security_sem_semctl(sma, cmd);
@@ -1047,7 +1048,8 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
1047 return -EFAULT; 1048 return -EFAULT;
1048 } 1049 }
1049 1050
1050 ipcp = ipcctl_pre_down(&sem_ids(ns), semid, cmd, &semid64.sem_perm, 0); 1051 ipcp = ipcctl_pre_down(ns, &sem_ids(ns), semid, cmd,
1052 &semid64.sem_perm, 0);
1051 if (IS_ERR(ipcp)) 1053 if (IS_ERR(ipcp))
1052 return PTR_ERR(ipcp); 1054 return PTR_ERR(ipcp);
1053 1055
@@ -1386,7 +1388,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1386 goto out_unlock_free; 1388 goto out_unlock_free;
1387 1389
1388 error = -EACCES; 1390 error = -EACCES;
1389 if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) 1391 if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
1390 goto out_unlock_free; 1392 goto out_unlock_free;
1391 1393
1392 error = security_sem_semop(sma, sops, nsops, alter); 1394 error = security_sem_semop(sma, sops, nsops, alter);
diff --git a/ipc/shm.c b/ipc/shm.c
index 7d3bb22a9302..8644452f5c4c 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -623,7 +623,8 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
623 return -EFAULT; 623 return -EFAULT;
624 } 624 }
625 625
626 ipcp = ipcctl_pre_down(&shm_ids(ns), shmid, cmd, &shmid64.shm_perm, 0); 626 ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd,
627 &shmid64.shm_perm, 0);
627 if (IS_ERR(ipcp)) 628 if (IS_ERR(ipcp))
628 return PTR_ERR(ipcp); 629 return PTR_ERR(ipcp);
629 630
@@ -737,7 +738,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
737 result = 0; 738 result = 0;
738 } 739 }
739 err = -EACCES; 740 err = -EACCES;
740 if (ipcperms (&shp->shm_perm, S_IRUGO)) 741 if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
741 goto out_unlock; 742 goto out_unlock;
742 err = security_shm_shmctl(shp, cmd); 743 err = security_shm_shmctl(shp, cmd);
743 if (err) 744 if (err)
@@ -773,7 +774,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
773 774
774 audit_ipc_obj(&(shp->shm_perm)); 775 audit_ipc_obj(&(shp->shm_perm));
775 776
776 if (!capable(CAP_IPC_LOCK)) { 777 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
777 uid_t euid = current_euid(); 778 uid_t euid = current_euid();
778 err = -EPERM; 779 err = -EPERM;
779 if (euid != shp->shm_perm.uid && 780 if (euid != shp->shm_perm.uid &&
@@ -888,7 +889,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
888 } 889 }
889 890
890 err = -EACCES; 891 err = -EACCES;
891 if (ipcperms(&shp->shm_perm, acc_mode)) 892 if (ipcperms(ns, &shp->shm_perm, acc_mode))
892 goto out_unlock; 893 goto out_unlock;
893 894
894 err = security_shm_shmat(shp, shmaddr, shmflg); 895 err = security_shm_shmat(shp, shmaddr, shmflg);
diff --git a/ipc/util.c b/ipc/util.c
index 69a0cc13d966..8fd1b891ec0c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -329,12 +329,14 @@ retry:
329 * 329 *
330 * It is called with ipc_ids.rw_mutex and ipcp->lock held. 330 * It is called with ipc_ids.rw_mutex and ipcp->lock held.
331 */ 331 */
332static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, 332static int ipc_check_perms(struct ipc_namespace *ns,
333 struct ipc_params *params) 333 struct kern_ipc_perm *ipcp,
334 struct ipc_ops *ops,
335 struct ipc_params *params)
334{ 336{
335 int err; 337 int err;
336 338
337 if (ipcperms(ipcp, params->flg)) 339 if (ipcperms(ns, ipcp, params->flg))
338 err = -EACCES; 340 err = -EACCES;
339 else { 341 else {
340 err = ops->associate(ipcp, params->flg); 342 err = ops->associate(ipcp, params->flg);
@@ -396,7 +398,7 @@ retry:
396 * ipc_check_perms returns the IPC id on 398 * ipc_check_perms returns the IPC id on
397 * success 399 * success
398 */ 400 */
399 err = ipc_check_perms(ipcp, ops, params); 401 err = ipc_check_perms(ns, ipcp, ops, params);
400 } 402 }
401 ipc_unlock(ipcp); 403 ipc_unlock(ipcp);
402 } 404 }
@@ -610,10 +612,12 @@ void ipc_rcu_putref(void *ptr)
610 * 612 *
611 * Check user, group, other permissions for access 613 * Check user, group, other permissions for access
612 * to ipc resources. return 0 if allowed 614 * to ipc resources. return 0 if allowed
615 *
616 * @flag will most probably be 0 or S_...UGO from <linux/stat.h>
613 */ 617 */
614 618
615int ipcperms (struct kern_ipc_perm *ipcp, short flag) 619int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
616{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ 620{
617 uid_t euid = current_euid(); 621 uid_t euid = current_euid();
618 int requested_mode, granted_mode; 622 int requested_mode, granted_mode;
619 623
@@ -627,7 +631,7 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag)
627 granted_mode >>= 3; 631 granted_mode >>= 3;
628 /* is there some bit set in requested_mode but not in granted_mode? */ 632 /* is there some bit set in requested_mode but not in granted_mode? */
629 if ((requested_mode & ~granted_mode & 0007) && 633 if ((requested_mode & ~granted_mode & 0007) &&
630 !capable(CAP_IPC_OWNER)) 634 !ns_capable(ns->user_ns, CAP_IPC_OWNER))
631 return -1; 635 return -1;
632 636
633 return security_ipc_permission(ipcp, flag); 637 return security_ipc_permission(ipcp, flag);
@@ -765,6 +769,7 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
765 769
766/** 770/**
767 * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd 771 * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
772 * @ids: the ipc namespace
768 * @ids: the table of ids where to look for the ipc 773 * @ids: the table of ids where to look for the ipc
769 * @id: the id of the ipc to retrieve 774 * @id: the id of the ipc to retrieve
770 * @cmd: the cmd to check 775 * @cmd: the cmd to check
@@ -779,7 +784,8 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
779 * - returns the ipc with both ipc and rw_mutex locks held in case of success 784 * - returns the ipc with both ipc and rw_mutex locks held in case of success
780 * or an err-code without any lock held otherwise. 785 * or an err-code without any lock held otherwise.
781 */ 786 */
782struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, 787struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
788 struct ipc_ids *ids, int id, int cmd,
783 struct ipc64_perm *perm, int extra_perm) 789 struct ipc64_perm *perm, int extra_perm)
784{ 790{
785 struct kern_ipc_perm *ipcp; 791 struct kern_ipc_perm *ipcp;
@@ -799,8 +805,8 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
799 perm->gid, perm->mode); 805 perm->gid, perm->mode);
800 806
801 euid = current_euid(); 807 euid = current_euid();
802 if (euid == ipcp->cuid || 808 if (euid == ipcp->cuid || euid == ipcp->uid ||
803 euid == ipcp->uid || capable(CAP_SYS_ADMIN)) 809 ns_capable(ns->user_ns, CAP_SYS_ADMIN))
804 return ipcp; 810 return ipcp;
805 811
806 err = -EPERM; 812 err = -EPERM;
diff --git a/ipc/util.h b/ipc/util.h
index 764b51a37a6a..6f5c20bedaab 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -103,7 +103,7 @@ int ipc_get_maxid(struct ipc_ids *);
103void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *); 103void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
104 104
105/* must be called with ipcp locked */ 105/* must be called with ipcp locked */
106int ipcperms(struct kern_ipc_perm *ipcp, short flg); 106int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flg);
107 107
108/* for rare, potentially huge allocations. 108/* for rare, potentially huge allocations.
109 * both function can sleep 109 * both function can sleep
@@ -126,7 +126,8 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
126void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out); 126void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
127void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out); 127void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
128void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out); 128void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
129struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, 129struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
130 struct ipc_ids *ids, int id, int cmd,
130 struct ipc64_perm *perm, int extra_perm); 131 struct ipc64_perm *perm, int extra_perm);
131 132
132#ifndef __ARCH_WANT_IPC_PARSE_VERSION 133#ifndef __ARCH_WANT_IPC_PARSE_VERSION
diff --git a/kernel/futex.c b/kernel/futex.c
index bda415715382..6570c459f31c 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2418,10 +2418,19 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
2418 goto err_unlock; 2418 goto err_unlock;
2419 ret = -EPERM; 2419 ret = -EPERM;
2420 pcred = __task_cred(p); 2420 pcred = __task_cred(p);
2421 /* If victim is in different user_ns, then uids are not
2422 comparable, so we must have CAP_SYS_PTRACE */
2423 if (cred->user->user_ns != pcred->user->user_ns) {
2424 if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
2425 goto err_unlock;
2426 goto ok;
2427 }
2428 /* If victim is in same user_ns, then uids are comparable */
2421 if (cred->euid != pcred->euid && 2429 if (cred->euid != pcred->euid &&
2422 cred->euid != pcred->uid && 2430 cred->euid != pcred->uid &&
2423 !capable(CAP_SYS_PTRACE)) 2431 !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
2424 goto err_unlock; 2432 goto err_unlock;
2433ok:
2425 head = p->robust_list; 2434 head = p->robust_list;
2426 rcu_read_unlock(); 2435 rcu_read_unlock();
2427 } 2436 }
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index a7934ac75e5b..5f9e689dc8f0 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -153,10 +153,19 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
153 goto err_unlock; 153 goto err_unlock;
154 ret = -EPERM; 154 ret = -EPERM;
155 pcred = __task_cred(p); 155 pcred = __task_cred(p);
156 /* If victim is in different user_ns, then uids are not
157 comparable, so we must have CAP_SYS_PTRACE */
158 if (cred->user->user_ns != pcred->user->user_ns) {
159 if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
160 goto err_unlock;
161 goto ok;
162 }
163 /* If victim is in same user_ns, then uids are comparable */
156 if (cred->euid != pcred->euid && 164 if (cred->euid != pcred->euid &&
157 cred->euid != pcred->uid && 165 cred->euid != pcred->uid &&
158 !capable(CAP_SYS_PTRACE)) 166 !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
159 goto err_unlock; 167 goto err_unlock;
168ok:
160 head = p->compat_robust_list; 169 head = p->compat_robust_list;
161 rcu_read_unlock(); 170 rcu_read_unlock();
162 } 171 }
diff --git a/kernel/groups.c b/kernel/groups.c
index 253dc0f35cf4..1cc476d52dd3 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 (!capable(CAP_SETGID)) 236 if (!nsown_capable(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 ac8a56e90bf8..a05d191ffdd9 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -75,16 +75,11 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
75 goto out_uts; 75 goto out_uts;
76 } 76 }
77 77
78 new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns); 78 new_nsp->ipc_ns = copy_ipcs(flags, tsk);
79 if (IS_ERR(new_nsp->ipc_ns)) { 79 if (IS_ERR(new_nsp->ipc_ns)) {
80 err = PTR_ERR(new_nsp->ipc_ns); 80 err = PTR_ERR(new_nsp->ipc_ns);
81 goto out_ipc; 81 goto out_ipc;
82 } 82 }
83 if (new_nsp->ipc_ns != tsk->nsproxy->ipc_ns) {
84 put_user_ns(new_nsp->ipc_ns->user_ns);
85 new_nsp->ipc_ns->user_ns = task_cred_xxx(tsk, user)->user_ns;
86 get_user_ns(new_nsp->ipc_ns->user_ns);
87 }
88 83
89 new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk)); 84 new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
90 if (IS_ERR(new_nsp->pid_ns)) { 85 if (IS_ERR(new_nsp->pid_ns)) {
diff --git a/kernel/sched.c b/kernel/sched.c
index a172494a9a63..480adeb63f8f 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4892,8 +4892,11 @@ static bool check_same_owner(struct task_struct *p)
4892 4892
4893 rcu_read_lock(); 4893 rcu_read_lock();
4894 pcred = __task_cred(p); 4894 pcred = __task_cred(p);
4895 match = (cred->euid == pcred->euid || 4895 if (cred->user->user_ns == pcred->user->user_ns)
4896 cred->euid == pcred->uid); 4896 match = (cred->euid == pcred->euid ||
4897 cred->euid == pcred->uid);
4898 else
4899 match = false;
4897 rcu_read_unlock(); 4900 rcu_read_unlock();
4898 return match; 4901 return match;
4899} 4902}
@@ -5221,7 +5224,7 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
5221 goto out_free_cpus_allowed; 5224 goto out_free_cpus_allowed;
5222 } 5225 }
5223 retval = -EPERM; 5226 retval = -EPERM;
5224 if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) 5227 if (!check_same_owner(p) && !task_ns_capable(p, CAP_SYS_NICE))
5225 goto out_unlock; 5228 goto out_unlock;
5226 5229
5227 retval = security_task_setscheduler(p); 5230 retval = security_task_setscheduler(p);
diff --git a/kernel/uid16.c b/kernel/uid16.c
index 419209893d87..51c6e89e8619 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -189,7 +189,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
189 struct group_info *group_info; 189 struct group_info *group_info;
190 int retval; 190 int retval;
191 191
192 if (!capable(CAP_SETGID)) 192 if (!nsown_capable(CAP_SETGID))
193 return -EPERM; 193 return -EPERM;
194 if ((unsigned)gidsetsize > NGROUPS_MAX) 194 if ((unsigned)gidsetsize > NGROUPS_MAX)
195 return -EINVAL; 195 return -EINVAL;