Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0e77598 authored by Serge E. Hallyn's avatar Serge E. Hallyn Committed by Linus Torvalds
Browse files

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: default avatarSerge E. Hallyn <serge.hallyn@canonical.com>
Acked-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: default avatarDaniel Lezcano <daniel.lezcano@free.fr>
Acked-by: default avatarDavid Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b515498f
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/idr.h>
#include <linux/rwsem.h>
#include <linux/notifier.h>
#include <linux/nsproxy.h>

/*
 * ipc namespace events
@@ -93,7 +94,7 @@ static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; }

#if defined(CONFIG_IPC_NS)
extern struct ipc_namespace *copy_ipcs(unsigned long flags,
				       struct ipc_namespace *ns);
				       struct task_struct *tsk);
static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
{
	if (ns)
@@ -104,12 +105,12 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
extern void put_ipc_ns(struct ipc_namespace *ns);
#else
static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
		struct ipc_namespace *ns)
					      struct task_struct *tsk)
{
	if (flags & CLONE_NEWIPC)
		return ERR_PTR(-EINVAL);

	return ns;
	return tsk->nsproxy->ipc_ns;
}

static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
+4 −4
Original line number Diff line number Diff line
@@ -421,7 +421,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
			return -EFAULT;
	}

	ipcp = ipcctl_pre_down(&msg_ids(ns), msqid, cmd,
	ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid, cmd,
			       &msqid64.msg_perm, msqid64.msg_qbytes);
	if (IS_ERR(ipcp))
		return PTR_ERR(ipcp);
@@ -539,7 +539,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
			success_return = 0;
		}
		err = -EACCES;
		if (ipcperms(&msq->q_perm, S_IRUGO))
		if (ipcperms(ns, &msq->q_perm, S_IRUGO))
			goto out_unlock;

		err = security_msg_queue_msgctl(msq, cmd);
@@ -664,7 +664,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
		struct msg_sender s;

		err = -EACCES;
		if (ipcperms(&msq->q_perm, S_IWUGO))
		if (ipcperms(ns, &msq->q_perm, S_IWUGO))
			goto out_unlock_free;

		err = security_msg_queue_msgsnd(msq, msg, msgflg);
@@ -774,7 +774,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
		struct list_head *tmp;

		msg = ERR_PTR(-EACCES);
		if (ipcperms(&msq->q_perm, S_IRUGO))
		if (ipcperms(ns, &msq->q_perm, S_IRUGO))
			goto out_unlock;

		msg = ERR_PTR(-EAGAIN);
+8 −5
Original line number Diff line number Diff line
@@ -15,7 +15,8 @@

#include "util.h"

static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns)
static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
					   struct ipc_namespace *old_ns)
{
	struct ipc_namespace *ns;
	int err;
@@ -44,17 +45,19 @@ static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns)
	ipcns_notify(IPCNS_CREATED);
	register_ipcns_notifier(ns);

	ns->user_ns = old_ns->user_ns;
	get_user_ns(ns->user_ns);
	ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns);

	return ns;
}

struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
struct ipc_namespace *copy_ipcs(unsigned long flags,
				struct task_struct *tsk)
{
	struct ipc_namespace *ns = tsk->nsproxy->ipc_ns;

	if (!(flags & CLONE_NEWIPC))
		return get_ipc_ns(ns);
	return create_ipc_ns(ns);
	return create_ipc_ns(tsk, ns);
}

/*
+6 −4
Original line number Diff line number Diff line
@@ -817,7 +817,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
		}

		err = -EACCES;
		if (ipcperms (&sma->sem_perm, S_IRUGO))
		if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
			goto out_unlock;

		err = security_sem_semctl(sma, cmd);
@@ -862,7 +862,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
	nsems = sma->sem_nsems;

	err = -EACCES;
	if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
	if (ipcperms(ns, &sma->sem_perm,
			(cmd == SETVAL || cmd == SETALL) ? S_IWUGO : S_IRUGO))
		goto out_unlock;

	err = security_sem_semctl(sma, cmd);
@@ -1047,7 +1048,8 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
			return -EFAULT;
	}

	ipcp = ipcctl_pre_down(&sem_ids(ns), semid, cmd, &semid64.sem_perm, 0);
	ipcp = ipcctl_pre_down(ns, &sem_ids(ns), semid, cmd,
			       &semid64.sem_perm, 0);
	if (IS_ERR(ipcp))
		return PTR_ERR(ipcp);

@@ -1386,7 +1388,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
		goto out_unlock_free;

	error = -EACCES;
	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
	if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
		goto out_unlock_free;

	error = security_sem_semop(sma, sops, nsops, alter);
+5 −4
Original line number Diff line number Diff line
@@ -623,7 +623,8 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
			return -EFAULT;
	}

	ipcp = ipcctl_pre_down(&shm_ids(ns), shmid, cmd, &shmid64.shm_perm, 0);
	ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd,
			       &shmid64.shm_perm, 0);
	if (IS_ERR(ipcp))
		return PTR_ERR(ipcp);

@@ -737,7 +738,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
			result = 0;
		}
		err = -EACCES;
		if (ipcperms (&shp->shm_perm, S_IRUGO))
		if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
			goto out_unlock;
		err = security_shm_shmctl(shp, cmd);
		if (err)
@@ -773,7 +774,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)

		audit_ipc_obj(&(shp->shm_perm));

		if (!capable(CAP_IPC_LOCK)) {
		if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
			uid_t euid = current_euid();
			err = -EPERM;
			if (euid != shp->shm_perm.uid &&
@@ -888,7 +889,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
	}

	err = -EACCES;
	if (ipcperms(&shp->shm_perm, acc_mode))
	if (ipcperms(ns, &shp->shm_perm, acc_mode))
		goto out_unlock;

	err = security_shm_shmat(shp, shmaddr, shmflg);
Loading