Commit 1efdb69b authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

userns: Convert ipc to use kuid and kgid where appropriate



- Store the ipc owner and creator with a kuid
- Store the ipc group and the crators group with a kgid.
- Add error handling to ipc_update_perms, allowing it to
  fail if the uids and gids can not be converted to kuids
  or kgids.
- Modify the proc files to display the ipc creator and
  owner in the user namespace of the opener of the proc file.

Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
parent 9582d901
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ struct ipc_kludge {

#ifdef __KERNEL__
#include <linux/spinlock.h>
#include <linux/uidgid.h>

#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */

@@ -89,10 +90,10 @@ struct kern_ipc_perm
	int		deleted;
	int		id;
	key_t		key;
	uid_t		uid;
	gid_t		gid;
	uid_t		cuid;
	gid_t		cgid;
	kuid_t		uid;
	kgid_t		gid;
	kuid_t		cuid;
	kgid_t		cgid;
	umode_t		mode; 
	unsigned long	seq;
	void		*security;
+0 −1
Original line number Diff line number Diff line
@@ -925,7 +925,6 @@ config UIDGID_CONVERTED

	# List of kernel pieces that need user namespace work
	# Features
	depends on SYSVIPC = n
	depends on IMA = n
	depends on EVM = n
	depends on KEYS = n
+9 −5
Original line number Diff line number Diff line
@@ -443,9 +443,12 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
			goto out_unlock;
		}

		err = ipc_update_perm(&msqid64.msg_perm, ipcp);
		if (err)
			goto out_unlock;

		msq->q_qbytes = msqid64.msg_qbytes;

		ipc_update_perm(&msqid64.msg_perm, ipcp);
		msq->q_ctime = get_seconds();
		/* sleeping receivers might be excluded by
		 * stricter permissions.
@@ -922,6 +925,7 @@ out:
#ifdef CONFIG_PROC_FS
static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
{
	struct user_namespace *user_ns = seq_user_ns(s);
	struct msg_queue *msq = it;

	return seq_printf(s,
@@ -933,10 +937,10 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
			msq->q_qnum,
			msq->q_lspid,
			msq->q_lrpid,
			msq->q_perm.uid,
			msq->q_perm.gid,
			msq->q_perm.cuid,
			msq->q_perm.cgid,
			from_kuid_munged(user_ns, msq->q_perm.uid),
			from_kgid_munged(user_ns, msq->q_perm.gid),
			from_kuid_munged(user_ns, msq->q_perm.cuid),
			from_kgid_munged(user_ns, msq->q_perm.cgid),
			msq->q_stime,
			msq->q_rtime,
			msq->q_ctime);
+8 −5
Original line number Diff line number Diff line
@@ -1104,7 +1104,9 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
		freeary(ns, ipcp);
		goto out_up;
	case IPC_SET:
		ipc_update_perm(&semid64.sem_perm, ipcp);
		err = ipc_update_perm(&semid64.sem_perm, ipcp);
		if (err)
			goto out_unlock;
		sma->sem_ctime = get_seconds();
		break;
	default:
@@ -1677,6 +1679,7 @@ void exit_sem(struct task_struct *tsk)
#ifdef CONFIG_PROC_FS
static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
{
	struct user_namespace *user_ns = seq_user_ns(s);
	struct sem_array *sma = it;

	return seq_printf(s,
@@ -1685,10 +1688,10 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
			  sma->sem_perm.id,
			  sma->sem_perm.mode,
			  sma->sem_nsems,
			  sma->sem_perm.uid,
			  sma->sem_perm.gid,
			  sma->sem_perm.cuid,
			  sma->sem_perm.cgid,
			  from_kuid_munged(user_ns, sma->sem_perm.uid),
			  from_kgid_munged(user_ns, sma->sem_perm.gid),
			  from_kuid_munged(user_ns, sma->sem_perm.cuid),
			  from_kgid_munged(user_ns, sma->sem_perm.cgid),
			  sma->sem_otime,
			  sma->sem_ctime);
}
+11 −8
Original line number Diff line number Diff line
@@ -758,7 +758,9 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
		do_shm_rmid(ns, ipcp);
		goto out_up;
	case IPC_SET:
		ipc_update_perm(&shmid64.shm_perm, ipcp);
		err = ipc_update_perm(&shmid64.shm_perm, ipcp);
		if (err)
			goto out_unlock;
		shp->shm_ctim = get_seconds();
		break;
	default:
@@ -893,10 +895,10 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
		audit_ipc_obj(&(shp->shm_perm));

		if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
			uid_t euid = current_euid();
			kuid_t euid = current_euid();
			err = -EPERM;
			if (euid != shp->shm_perm.uid &&
			    euid != shp->shm_perm.cuid)
			if (!uid_eq(euid, shp->shm_perm.uid) &&
			    !uid_eq(euid, shp->shm_perm.cuid))
				goto out_unlock;
			if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
				goto out_unlock;
@@ -1220,6 +1222,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
#ifdef CONFIG_PROC_FS
static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
{
	struct user_namespace *user_ns = seq_user_ns(s);
	struct shmid_kernel *shp = it;
	unsigned long rss = 0, swp = 0;

@@ -1242,10 +1245,10 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
			  shp->shm_cprid,
			  shp->shm_lprid,
			  shp->shm_nattch,
			  shp->shm_perm.uid,
			  shp->shm_perm.gid,
			  shp->shm_perm.cuid,
			  shp->shm_perm.cgid,
			  from_kuid_munged(user_ns, shp->shm_perm.uid),
			  from_kgid_munged(user_ns, shp->shm_perm.gid),
			  from_kuid_munged(user_ns, shp->shm_perm.cuid),
			  from_kgid_munged(user_ns, shp->shm_perm.cgid),
			  shp->shm_atim,
			  shp->shm_dtim,
			  shp->shm_ctim,
Loading