From 553f770ef71b27ee053bd241bef0998a15f43467 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sat, 8 Jul 2017 22:52:47 -0400
Subject: ipc: move compat shmctl to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 ipc/compat.c | 233 +----------------------------------------------------------
 1 file changed, 3 insertions(+), 230 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/ipc/compat.c b/ipc/compat.c
index 9b3c85f8a538..fbfd6fb0a68d 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -39,16 +39,6 @@ struct compat_msgbuf {
 	char mtext[1];
 };
 
-struct compat_ipc_perm {
-	key_t key;
-	__compat_uid_t uid;
-	__compat_gid_t gid;
-	__compat_uid_t cuid;
-	__compat_gid_t cgid;
-	compat_mode_t mode;
-	unsigned short seq;
-};
-
 struct compat_semid_ds {
 	struct compat_ipc_perm sem_perm;
 	compat_time_t sem_otime;
@@ -76,44 +66,12 @@ struct compat_msqid_ds {
 	compat_ipc_pid_t msg_lrpid;
 };
 
-struct compat_shmid_ds {
-	struct compat_ipc_perm shm_perm;
-	int shm_segsz;
-	compat_time_t shm_atime;
-	compat_time_t shm_dtime;
-	compat_time_t shm_ctime;
-	compat_ipc_pid_t shm_cpid;
-	compat_ipc_pid_t shm_lpid;
-	unsigned short shm_nattch;
-	unsigned short shm_unused;
-	compat_uptr_t shm_unused2;
-	compat_uptr_t shm_unused3;
-};
-
 struct compat_ipc_kludge {
 	compat_uptr_t msgp;
 	compat_long_t msgtyp;
 };
 
-struct compat_shminfo64 {
-	compat_ulong_t shmmax;
-	compat_ulong_t shmmin;
-	compat_ulong_t shmmni;
-	compat_ulong_t shmseg;
-	compat_ulong_t shmall;
-	compat_ulong_t __unused1;
-	compat_ulong_t __unused2;
-	compat_ulong_t __unused3;
-	compat_ulong_t __unused4;
-};
-
-struct compat_shm_info {
-	compat_int_t used_ids;
-	compat_ulong_t shm_tot, shm_rss, shm_swp;
-	compat_ulong_t swap_attempts, swap_successes;
-};
-
-static inline int compat_ipc_parse_version(int *cmd)
+static inline int __compat_ipc_parse_version(int *cmd)
 {
 #ifdef	CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	int version = *cmd & IPC_64;
@@ -241,7 +199,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
 	int err, err2;
 	struct semid64_ds sem64;
 	struct semid64_ds __user *up64;
-	int version = compat_ipc_parse_version(&third);
+	int version = __compat_ipc_parse_version(&third);
 
 	memset(&sem64, 0, sizeof(sem64));
 
@@ -499,7 +457,7 @@ COMPAT_SYSCALL_DEFINE3(msgctl, int, first, int, second, void __user *, uptr)
 {
 	int err, err2;
 	struct msqid64_ds m64;
-	int version = compat_ipc_parse_version(&second);
+	int version = __compat_ipc_parse_version(&second);
 	void __user *p;
 
 	memset(&m64, 0, sizeof(m64));
@@ -561,191 +519,6 @@ COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
 	return (long)ret;
 }
 
-static inline int get_compat_shmid64_ds(struct shmid64_ds *sem64,
-					struct compat_shmid64_ds __user *up64)
-{
-	if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
-		return -EFAULT;
-	return __get_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm);
-}
-
-static inline int get_compat_shmid_ds(struct shmid64_ds *s,
-				      struct compat_shmid_ds __user *up)
-{
-	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
-		return -EFAULT;
-	return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
-}
-
-static inline int put_compat_shmid64_ds(struct shmid64_ds *sem64,
-					struct compat_shmid64_ds __user *up64)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
-		return -EFAULT;
-	err  = __put_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm);
-	err |= __put_user(sem64->shm_atime, &up64->shm_atime);
-	err |= __put_user(sem64->shm_dtime, &up64->shm_dtime);
-	err |= __put_user(sem64->shm_ctime, &up64->shm_ctime);
-	err |= __put_user(sem64->shm_segsz, &up64->shm_segsz);
-	err |= __put_user(sem64->shm_nattch, &up64->shm_nattch);
-	err |= __put_user(sem64->shm_cpid, &up64->shm_cpid);
-	err |= __put_user(sem64->shm_lpid, &up64->shm_lpid);
-	return err;
-}
-
-static inline int put_compat_shmid_ds(struct shmid64_ds *s,
-				      struct compat_shmid_ds __user *up)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
-		return -EFAULT;
-	err  = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
-	err |= __put_user(s->shm_atime, &up->shm_atime);
-	err |= __put_user(s->shm_dtime, &up->shm_dtime);
-	err |= __put_user(s->shm_ctime, &up->shm_ctime);
-	err |= __put_user(s->shm_segsz, &up->shm_segsz);
-	err |= __put_user(s->shm_nattch, &up->shm_nattch);
-	err |= __put_user(s->shm_cpid, &up->shm_cpid);
-	err |= __put_user(s->shm_lpid, &up->shm_lpid);
-	return err;
-}
-
-static inline int put_compat_shminfo64(struct shminfo64 *smi,
-				       struct compat_shminfo64 __user *up64)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
-		return -EFAULT;
-	if (smi->shmmax > INT_MAX)
-		smi->shmmax = INT_MAX;
-	err  = __put_user(smi->shmmax, &up64->shmmax);
-	err |= __put_user(smi->shmmin, &up64->shmmin);
-	err |= __put_user(smi->shmmni, &up64->shmmni);
-	err |= __put_user(smi->shmseg, &up64->shmseg);
-	err |= __put_user(smi->shmall, &up64->shmall);
-	return err;
-}
-
-static inline int put_compat_shminfo(struct shminfo64 *smi,
-				     struct shminfo __user *up)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
-		return -EFAULT;
-	if (smi->shmmax > INT_MAX)
-		smi->shmmax = INT_MAX;
-	err  = __put_user(smi->shmmax, &up->shmmax);
-	err |= __put_user(smi->shmmin, &up->shmmin);
-	err |= __put_user(smi->shmmni, &up->shmmni);
-	err |= __put_user(smi->shmseg, &up->shmseg);
-	err |= __put_user(smi->shmall, &up->shmall);
-	return err;
-}
-
-static inline int put_compat_shm_info(struct shm_info __user *ip,
-				      struct compat_shm_info __user *uip)
-{
-	int err;
-	struct shm_info si;
-
-	if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)) ||
-	    copy_from_user(&si, ip, sizeof(si)))
-		return -EFAULT;
-	err  = __put_user(si.used_ids, &uip->used_ids);
-	err |= __put_user(si.shm_tot, &uip->shm_tot);
-	err |= __put_user(si.shm_rss, &uip->shm_rss);
-	err |= __put_user(si.shm_swp, &uip->shm_swp);
-	err |= __put_user(si.swap_attempts, &uip->swap_attempts);
-	err |= __put_user(si.swap_successes, &uip->swap_successes);
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
-{
-	void __user *p;
-	struct shmid64_ds sem64;
-	struct shminfo64 smi;
-	int err, err2;
-	int version = compat_ipc_parse_version(&second);
-
-	memset(&sem64, 0, sizeof(sem64));
-
-	switch (second & (~IPC_64)) {
-	case IPC_RMID:
-	case SHM_LOCK:
-	case SHM_UNLOCK:
-		err = sys_shmctl(first, second, uptr);
-		break;
-
-	case IPC_INFO:
-		p = compat_alloc_user_space(sizeof(smi));
-		err = sys_shmctl(first, second, p);
-		if (err < 0)
-			break;
-		if (copy_from_user(&smi, p, sizeof(smi)))
-			err2 = -EFAULT;
-		else if (version == IPC_64)
-			err2 = put_compat_shminfo64(&smi, uptr);
-		else
-			err2 = put_compat_shminfo(&smi, uptr);
-		if (err2)
-			err = -EFAULT;
-		break;
-
-
-	case IPC_SET:
-		if (version == IPC_64)
-			err = get_compat_shmid64_ds(&sem64, uptr);
-		else
-			err = get_compat_shmid_ds(&sem64, uptr);
-
-		if (err)
-			break;
-		p = compat_alloc_user_space(sizeof(sem64));
-		if (copy_to_user(p, &sem64, sizeof(sem64)))
-			err = -EFAULT;
-		else
-			err = sys_shmctl(first, second, p);
-		break;
-
-	case IPC_STAT:
-	case SHM_STAT:
-		p = compat_alloc_user_space(sizeof(sem64));
-		err = sys_shmctl(first, second, p);
-		if (err < 0)
-			break;
-		if (copy_from_user(&sem64, p, sizeof(sem64)))
-			err2 = -EFAULT;
-		else if (version == IPC_64)
-			err2 = put_compat_shmid64_ds(&sem64, uptr);
-		else
-			err2 = put_compat_shmid_ds(&sem64, uptr);
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	case SHM_INFO:
-		p = compat_alloc_user_space(sizeof(struct shm_info));
-		err = sys_shmctl(first, second, p);
-		if (err < 0)
-			break;
-		err2 = put_compat_shm_info(p, uptr);
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
-}
-
 COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
 		       unsigned, nsops,
 		       const struct compat_timespec __user *, timeout)
-- 
cgit v1.2.3-58-ga151


From 4693916846269d633a3664586650dbfac2c5562f Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 9 Jul 2017 08:31:16 -0400
Subject: msgctl(): move compat to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 ipc/compat.c | 132 ----------------------------------------------------------
 ipc/msg.c    | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 132 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/ipc/compat.c b/ipc/compat.c
index fbfd6fb0a68d..c83099a3b265 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -50,22 +50,6 @@ struct compat_semid_ds {
 	unsigned short sem_nsems;
 };
 
-struct compat_msqid_ds {
-	struct compat_ipc_perm msg_perm;
-	compat_uptr_t msg_first;
-	compat_uptr_t msg_last;
-	compat_time_t msg_stime;
-	compat_time_t msg_rtime;
-	compat_time_t msg_ctime;
-	compat_ulong_t msg_lcbytes;
-	compat_ulong_t msg_lqbytes;
-	unsigned short msg_cbytes;
-	unsigned short msg_qnum;
-	unsigned short msg_qbytes;
-	compat_ipc_pid_t msg_lspid;
-	compat_ipc_pid_t msg_lrpid;
-};
-
 struct compat_ipc_kludge {
 	compat_uptr_t msgp;
 	compat_long_t msgtyp;
@@ -391,122 +375,6 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
 			 msgflg, compat_do_msg_fill);
 }
 
-static inline int get_compat_msqid64(struct msqid64_ds *m64,
-				     struct compat_msqid64_ds __user *up64)
-{
-	int err;
-
-	if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
-		return -EFAULT;
-	err  = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
-	err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes);
-	return err;
-}
-
-static inline int get_compat_msqid(struct msqid64_ds *m,
-				   struct compat_msqid_ds __user *up)
-{
-	int err;
-
-	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
-		return -EFAULT;
-	err  = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
-	err |= __get_user(m->msg_qbytes, &up->msg_qbytes);
-	return err;
-}
-
-static inline int put_compat_msqid64_ds(struct msqid64_ds *m64,
-				 struct compat_msqid64_ds __user *up64)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
-		return -EFAULT;
-	err  = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
-	err |= __put_user(m64->msg_stime, &up64->msg_stime);
-	err |= __put_user(m64->msg_rtime, &up64->msg_rtime);
-	err |= __put_user(m64->msg_ctime, &up64->msg_ctime);
-	err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes);
-	err |= __put_user(m64->msg_qnum, &up64->msg_qnum);
-	err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes);
-	err |= __put_user(m64->msg_lspid, &up64->msg_lspid);
-	err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid);
-	return err;
-}
-
-static inline int put_compat_msqid_ds(struct msqid64_ds *m,
-				      struct compat_msqid_ds __user *up)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
-		return -EFAULT;
-	err  = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
-	err |= __put_user(m->msg_stime, &up->msg_stime);
-	err |= __put_user(m->msg_rtime, &up->msg_rtime);
-	err |= __put_user(m->msg_ctime, &up->msg_ctime);
-	err |= __put_user(m->msg_cbytes, &up->msg_cbytes);
-	err |= __put_user(m->msg_qnum, &up->msg_qnum);
-	err |= __put_user(m->msg_qbytes, &up->msg_qbytes);
-	err |= __put_user(m->msg_lspid, &up->msg_lspid);
-	err |= __put_user(m->msg_lrpid, &up->msg_lrpid);
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE3(msgctl, int, first, int, second, void __user *, uptr)
-{
-	int err, err2;
-	struct msqid64_ds m64;
-	int version = __compat_ipc_parse_version(&second);
-	void __user *p;
-
-	memset(&m64, 0, sizeof(m64));
-
-	switch (second & (~IPC_64)) {
-	case IPC_INFO:
-	case IPC_RMID:
-	case MSG_INFO:
-		err = sys_msgctl(first, second, uptr);
-		break;
-
-	case IPC_SET:
-		if (version == IPC_64)
-			err = get_compat_msqid64(&m64, uptr);
-		else
-			err = get_compat_msqid(&m64, uptr);
-
-		if (err)
-			break;
-		p = compat_alloc_user_space(sizeof(m64));
-		if (copy_to_user(p, &m64, sizeof(m64)))
-			err = -EFAULT;
-		else
-			err = sys_msgctl(first, second, p);
-		break;
-
-	case IPC_STAT:
-	case MSG_STAT:
-		p = compat_alloc_user_space(sizeof(m64));
-		err = sys_msgctl(first, second, p);
-		if (err < 0)
-			break;
-		if (copy_from_user(&m64, p, sizeof(m64)))
-			err2 = -EFAULT;
-		else if (version == IPC_64)
-			err2 = put_compat_msqid64_ds(&m64, uptr);
-		else
-			err2 = put_compat_msqid_ds(&m64, uptr);
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
-}
-
 COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
 {
 	unsigned long ret;
diff --git a/ipc/msg.c b/ipc/msg.c
index 322e7bf8b8d1..3400012e1ce8 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -567,6 +567,139 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
 	}
 }
 
+#ifdef CONFIG_COMPAT
+
+struct compat_msqid_ds {
+	struct compat_ipc_perm msg_perm;
+	compat_uptr_t msg_first;
+	compat_uptr_t msg_last;
+	compat_time_t msg_stime;
+	compat_time_t msg_rtime;
+	compat_time_t msg_ctime;
+	compat_ulong_t msg_lcbytes;
+	compat_ulong_t msg_lqbytes;
+	unsigned short msg_cbytes;
+	unsigned short msg_qnum;
+	unsigned short msg_qbytes;
+	compat_ipc_pid_t msg_lspid;
+	compat_ipc_pid_t msg_lrpid;
+};
+
+static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf,
+					int version)
+{
+	memset(out, 0, sizeof(*out));
+	if (version == IPC_64) {
+		struct compat_msqid64_ds *p = buf;
+		struct compat_ipc64_perm v;
+		if (copy_from_user(&v, &p->msg_perm, sizeof(v)))
+			return -EFAULT;
+		out->msg_perm.uid = v.uid;
+		out->msg_perm.gid = v.gid;
+		out->msg_perm.mode = v.mode;
+		if (get_user(out->msg_qbytes, &p->msg_qbytes))
+			return -EFAULT;
+	} else {
+		struct compat_msqid_ds *p = buf;
+		struct compat_ipc_perm v;
+		if (copy_from_user(&v, &p->msg_perm, sizeof(v)))
+			return -EFAULT;
+		out->msg_perm.uid = v.uid;
+		out->msg_perm.gid = v.gid;
+		out->msg_perm.mode = v.mode;
+		if (get_user(out->msg_qbytes, &p->msg_qbytes))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int copy_compat_msqid_to_user(void __user *buf, struct msqid64_ds *in,
+					int version)
+{
+	if (version == IPC_64) {
+		struct compat_msqid64_ds v;
+		memset(&v, 0, sizeof(v));
+		v.msg_perm.key = in->msg_perm.key;
+		v.msg_perm.uid = in->msg_perm.uid;
+		v.msg_perm.gid = in->msg_perm.gid;
+		v.msg_perm.cuid = in->msg_perm.cuid;
+		v.msg_perm.cgid = in->msg_perm.cgid;
+		v.msg_perm.mode = in->msg_perm.mode;
+		v.msg_perm.seq = in->msg_perm.seq;
+		v.msg_stime = in->msg_stime;
+		v.msg_rtime = in->msg_rtime;
+		v.msg_ctime = in->msg_ctime;
+		v.msg_cbytes = in->msg_cbytes;
+		v.msg_qnum = in->msg_qnum;
+		v.msg_qbytes = in->msg_qbytes;
+		v.msg_lspid = in->msg_lspid;
+		v.msg_lrpid = in->msg_lrpid;
+		return copy_to_user(buf, &v, sizeof(v));
+	} else {
+		struct compat_msqid_ds v;
+		memset(&v, 0, sizeof(v));
+		v.msg_perm.key = in->msg_perm.key;
+		SET_UID(v.msg_perm.uid, in->msg_perm.uid);
+		SET_GID(v.msg_perm.gid, in->msg_perm.gid);
+		SET_UID(v.msg_perm.cuid, in->msg_perm.cuid);
+		SET_GID(v.msg_perm.cgid, in->msg_perm.cgid);
+		v.msg_perm.mode = in->msg_perm.mode;
+		v.msg_perm.seq = in->msg_perm.seq;
+		v.msg_stime = in->msg_stime;
+		v.msg_rtime = in->msg_rtime;
+		v.msg_ctime = in->msg_ctime;
+		v.msg_cbytes = in->msg_cbytes;
+		v.msg_qnum = in->msg_qnum;
+		v.msg_qbytes = in->msg_qbytes;
+		v.msg_lspid = in->msg_lspid;
+		v.msg_lrpid = in->msg_lrpid;
+		return copy_to_user(buf, &v, sizeof(v));
+	}
+}
+
+COMPAT_SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, void __user *, uptr)
+{
+	struct ipc_namespace *ns;
+	int err;
+	struct msqid64_ds msqid64;
+	int version = compat_ipc_parse_version(&cmd);
+
+	ns = current->nsproxy->ipc_ns;
+
+	if (msqid < 0 || cmd < 0)
+		return -EINVAL;
+
+	switch (cmd & (~IPC_64)) {
+	case IPC_INFO:
+	case MSG_INFO: {
+		struct msginfo msginfo;
+		err = msgctl_info(ns, msqid, cmd, &msginfo);
+		if (err < 0)
+			return err;
+		if (copy_to_user(uptr, &msginfo, sizeof(struct msginfo)))
+			err = -EFAULT;
+		return err;
+	}
+	case IPC_STAT:
+	case MSG_STAT:
+		err = msgctl_stat(ns, msqid, cmd, &msqid64);
+		if (err < 0)
+			return err;
+		if (copy_compat_msqid_to_user(uptr, &msqid64, version))
+			err = -EFAULT;
+		return err;
+	case IPC_SET:
+		if (copy_compat_msqid_from_user(&msqid64, uptr, version))
+			return -EFAULT;
+		/* fallthru */
+	case IPC_RMID:
+		return msgctl_down(ns, msqid, cmd, &msqid64);
+	default:
+		return -EINVAL;
+	}
+}
+#endif
+
 static int testmsg(struct msg_msg *msg, long type, int mode)
 {
 	switch (mode) {
-- 
cgit v1.2.3-58-ga151


From c0ebccb6fa1e2c9c3377fa8136e6d8bc006fca64 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 9 Jul 2017 10:03:23 -0400
Subject: semctl(): move compat to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 ipc/compat.c | 230 +++++++++--------------------------------------------------
 ipc/sem.c    |  94 ++++++++++++++++++++++++
 ipc/util.h   |   6 ++
 3 files changed, 133 insertions(+), 197 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/ipc/compat.c b/ipc/compat.c
index c83099a3b265..3c25ca1e46c7 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -39,214 +39,55 @@ struct compat_msgbuf {
 	char mtext[1];
 };
 
-struct compat_semid_ds {
-	struct compat_ipc_perm sem_perm;
-	compat_time_t sem_otime;
-	compat_time_t sem_ctime;
-	compat_uptr_t sem_base;
-	compat_uptr_t sem_pending;
-	compat_uptr_t sem_pending_last;
-	compat_uptr_t undo;
-	unsigned short sem_nsems;
-};
-
 struct compat_ipc_kludge {
 	compat_uptr_t msgp;
 	compat_long_t msgtyp;
 };
 
-static inline int __compat_ipc_parse_version(int *cmd)
-{
-#ifdef	CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
-	int version = *cmd & IPC_64;
-
-	/* this is tricky: architectures that have support for the old
-	 * ipc structures in 64 bit binaries need to have IPC_64 set
-	 * in cmd, the others need to have it cleared */
-#ifndef ipc_parse_version
-	*cmd |= IPC_64;
-#else
-	*cmd &= ~IPC_64;
-#endif
-	return version;
-#else
-	/* With the asm-generic APIs, we always use the 64-bit versions. */
-	return IPC_64;
-#endif
-}
-
-static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
-					  struct compat_ipc64_perm __user *up64)
-{
-	int err;
-
-	err  = __get_user(p64->uid, &up64->uid);
-	err |= __get_user(p64->gid, &up64->gid);
-	err |= __get_user(p64->mode, &up64->mode);
-	return err;
-}
-
-static inline int __get_compat_ipc_perm(struct ipc64_perm *p,
-					struct compat_ipc_perm __user *up)
-{
-	int err;
-
-	err  = __get_user(p->uid, &up->uid);
-	err |= __get_user(p->gid, &up->gid);
-	err |= __get_user(p->mode, &up->mode);
-	return err;
-}
-
-static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
-					  struct compat_ipc64_perm __user *up64)
-{
-	int err;
-
-	err  = __put_user(p64->key, &up64->key);
-	err |= __put_user(p64->uid, &up64->uid);
-	err |= __put_user(p64->gid, &up64->gid);
-	err |= __put_user(p64->cuid, &up64->cuid);
-	err |= __put_user(p64->cgid, &up64->cgid);
-	err |= __put_user(p64->mode, &up64->mode);
-	err |= __put_user(p64->seq, &up64->seq);
-	return err;
-}
-
-static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
-					struct compat_ipc_perm __user *uip)
-{
-	int err;
-	__compat_uid_t u;
-	__compat_gid_t g;
-
-	err  = __put_user(p->key, &uip->key);
-	SET_UID(u, p->uid);
-	err |= __put_user(u, &uip->uid);
-	SET_GID(g, p->gid);
-	err |= __put_user(g, &uip->gid);
-	SET_UID(u, p->cuid);
-	err |= __put_user(u, &uip->cuid);
-	SET_GID(g, p->cgid);
-	err |= __put_user(g, &uip->cgid);
-	err |= __put_user(p->mode, &uip->mode);
-	err |= __put_user(p->seq, &uip->seq);
-	return err;
-}
-
-static inline int get_compat_semid64_ds(struct semid64_ds *sem64,
-					struct compat_semid64_ds __user *up64)
+int get_compat_ipc64_perm(struct ipc64_perm *to,
+			  struct compat_ipc64_perm __user *from)
 {
-	if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
+	struct compat_ipc64_perm v;
+	if (copy_from_user(&v, from, sizeof(v)))
 		return -EFAULT;
-	return __get_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
+	to->uid = v.uid;
+	to->gid = v.gid;
+	to->mode = v.mode;
+	return 0;
 }
 
-static inline int get_compat_semid_ds(struct semid64_ds *s,
-				      struct compat_semid_ds __user *up)
+int get_compat_ipc_perm(struct ipc64_perm *to,
+			struct compat_ipc_perm __user *from)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+	struct compat_ipc_perm v;
+	if (copy_from_user(&v, from, sizeof(v)))
 		return -EFAULT;
-	return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
+	to->uid = v.uid;
+	to->gid = v.gid;
+	to->mode = v.mode;
+	return 0;
 }
 
-static inline int put_compat_semid64_ds(struct semid64_ds *sem64,
-					struct compat_semid64_ds __user *up64)
+void to_compat_ipc64_perm(struct compat_ipc64_perm *to, struct ipc64_perm *from)
 {
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
-		return -EFAULT;
-	err  = __put_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
-	err |= __put_user(sem64->sem_otime, &up64->sem_otime);
-	err |= __put_user(sem64->sem_ctime, &up64->sem_ctime);
-	err |= __put_user(sem64->sem_nsems, &up64->sem_nsems);
-	return err;
+	to->key = from->key;
+	to->uid = from->uid;
+	to->gid = from->gid;
+	to->cuid = from->cuid;
+	to->cgid = from->cgid;
+	to->mode = from->mode;
+	to->seq = from->seq;
 }
 
-static inline int put_compat_semid_ds(struct semid64_ds *s,
-				      struct compat_semid_ds __user *up)
+void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
 {
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
-		return -EFAULT;
-	err  = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
-	err |= __put_user(s->sem_otime, &up->sem_otime);
-	err |= __put_user(s->sem_ctime, &up->sem_ctime);
-	err |= __put_user(s->sem_nsems, &up->sem_nsems);
-	return err;
-}
-
-static long do_compat_semctl(int first, int second, int third, u32 pad)
-{
-	unsigned long fourth;
-	int err, err2;
-	struct semid64_ds sem64;
-	struct semid64_ds __user *up64;
-	int version = __compat_ipc_parse_version(&third);
-
-	memset(&sem64, 0, sizeof(sem64));
-
-	if ((third & (~IPC_64)) == SETVAL)
-#ifdef __BIG_ENDIAN
-		fourth = (unsigned long)pad << 32;
-#else
-		fourth = pad;
-#endif
-	else
-		fourth = (unsigned long)compat_ptr(pad);
-	switch (third & (~IPC_64)) {
-	case IPC_INFO:
-	case IPC_RMID:
-	case SEM_INFO:
-	case GETVAL:
-	case GETPID:
-	case GETNCNT:
-	case GETZCNT:
-	case GETALL:
-	case SETVAL:
-	case SETALL:
-		err = sys_semctl(first, second, third, fourth);
-		break;
-
-	case IPC_STAT:
-	case SEM_STAT:
-		up64 = compat_alloc_user_space(sizeof(sem64));
-		fourth = (unsigned long)up64;
-		err = sys_semctl(first, second, third, fourth);
-		if (err < 0)
-			break;
-		if (copy_from_user(&sem64, up64, sizeof(sem64)))
-			err2 = -EFAULT;
-		else if (version == IPC_64)
-			err2 = put_compat_semid64_ds(&sem64, compat_ptr(pad));
-		else
-			err2 = put_compat_semid_ds(&sem64, compat_ptr(pad));
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	case IPC_SET:
-		if (version == IPC_64)
-			err = get_compat_semid64_ds(&sem64, compat_ptr(pad));
-		else
-			err = get_compat_semid_ds(&sem64, compat_ptr(pad));
-
-		up64 = compat_alloc_user_space(sizeof(sem64));
-		if (copy_to_user(up64, &sem64, sizeof(sem64)))
-			err = -EFAULT;
-		if (err)
-			break;
-
-		fourth = (unsigned long)up64;
-		err = sys_semctl(first, second, third, fourth);
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
+	to->key = from->key;
+	SET_UID(to->uid, from->uid);
+	SET_GID(to->gid, from->gid);
+	SET_UID(to->cuid, from->cuid);
+	SET_GID(to->cgid, from->cgid);
+	to->mode = from->mode;
+	to->seq = from->seq;
 }
 
 static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
@@ -291,7 +132,7 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
 			return -EINVAL;
 		if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
 			return -EFAULT;
-		return do_compat_semctl(first, second, third, pad);
+		return compat_sys_semctl(first, second, third, pad);
 
 	case MSGSND: {
 		struct compat_msgbuf __user *up = compat_ptr(ptr);
@@ -352,11 +193,6 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
 }
 #endif
 
-COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
-{
-	return do_compat_semctl(semid, semnum, cmd, arg);
-}
-
 COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
 		       compat_ssize_t, msgsz, int, msgflg)
 {
diff --git a/ipc/sem.c b/ipc/sem.c
index c8029c6bef72..fcf064d6046a 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1617,6 +1617,100 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
 	}
 }
 
+#ifdef CONFIG_COMPAT
+
+struct compat_semid_ds {
+	struct compat_ipc_perm sem_perm;
+	compat_time_t sem_otime;
+	compat_time_t sem_ctime;
+	compat_uptr_t sem_base;
+	compat_uptr_t sem_pending;
+	compat_uptr_t sem_pending_last;
+	compat_uptr_t undo;
+	unsigned short sem_nsems;
+};
+
+static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf,
+					int version)
+{
+	memset(out, 0, sizeof(*out));
+	if (version == IPC_64) {
+		struct compat_semid64_ds *p = buf;
+		return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm);
+	} else {
+		struct compat_semid_ds *p = buf;
+		return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm);
+	}
+}
+
+static int copy_compat_semid_to_user(void __user *buf, struct semid64_ds *in,
+					int version)
+{
+	if (version == IPC_64) {
+		struct compat_semid64_ds v;
+		memset(&v, 0, sizeof(v));
+		to_compat_ipc64_perm(&v.sem_perm, &in->sem_perm);
+		v.sem_otime = in->sem_otime;
+		v.sem_ctime = in->sem_ctime;
+		v.sem_nsems = in->sem_nsems;
+		return copy_to_user(buf, &v, sizeof(v));
+	} else {
+		struct compat_semid_ds v;
+		memset(&v, 0, sizeof(v));
+		to_compat_ipc_perm(&v.sem_perm, &in->sem_perm);
+		v.sem_otime = in->sem_otime;
+		v.sem_ctime = in->sem_ctime;
+		v.sem_nsems = in->sem_nsems;
+		return copy_to_user(buf, &v, sizeof(v));
+	}
+}
+
+COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
+{
+	void __user *p = compat_ptr(arg);
+	struct ipc_namespace *ns;
+	struct semid64_ds semid64;
+	int version = compat_ipc_parse_version(&cmd);
+	int err;
+
+	ns = current->nsproxy->ipc_ns;
+
+	if (semid < 0)
+		return -EINVAL;
+
+	switch (cmd & (~IPC_64)) {
+	case IPC_INFO:
+	case SEM_INFO:
+		return semctl_info(ns, semid, cmd, p);
+	case IPC_STAT:
+	case SEM_STAT:
+		err = semctl_stat(ns, semid, cmd, &semid64);
+		if (err < 0)
+			return err;
+		if (copy_compat_semid_to_user(p, &semid64, version))
+			err = -EFAULT;
+		return err;
+	case GETVAL:
+	case GETPID:
+	case GETNCNT:
+	case GETZCNT:
+	case GETALL:
+	case SETALL:
+		return semctl_main(ns, semid, semnum, cmd, p);
+	case SETVAL:
+		return semctl_setval(ns, semid, semnum, arg);
+	case IPC_SET:
+		if (copy_compat_semid_from_user(&semid64, p, version))
+			return -EFAULT;
+		/* fallthru */
+	case IPC_RMID:
+		return semctl_down(ns, semid, cmd, &semid64);
+	default:
+		return -EINVAL;
+	}
+}
+#endif
+
 /* If the task doesn't already have a undo_list, then allocate one
  * here.  We guarantee there is only one thread using this undo list,
  * and current is THE ONE
diff --git a/ipc/util.h b/ipc/util.h
index 3a3dfe137bee..c7b7a5ff1f0b 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -204,6 +204,12 @@ struct compat_ipc_perm {
 	unsigned short seq;
 };
 
+void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *);
+void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *);
+int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *);
+int get_compat_ipc64_perm(struct ipc64_perm *,
+			  struct compat_ipc64_perm __user *);
+
 static inline int compat_ipc_parse_version(int *cmd)
 {
 #ifdef	CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
-- 
cgit v1.2.3-58-ga151


From 20bc2a3aff5a88a666e81182fd277ea2a521fd3d Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 9 Jul 2017 10:27:22 -0400
Subject: ipc(2): move compat to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 ipc/compat.c  | 98 +++--------------------------------------------------------
 ipc/syscall.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 93 insertions(+), 95 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/ipc/compat.c b/ipc/compat.c
index 3c25ca1e46c7..00c2e3beccc8 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -39,11 +39,6 @@ struct compat_msgbuf {
 	char mtext[1];
 };
 
-struct compat_ipc_kludge {
-	compat_uptr_t msgp;
-	compat_long_t msgtyp;
-};
-
 int get_compat_ipc64_perm(struct ipc64_perm *to,
 			  struct compat_ipc64_perm __user *from)
 {
@@ -104,95 +99,6 @@ static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bu
 	return msgsz;
 }
 
-#ifndef COMPAT_SHMLBA
-#define COMPAT_SHMLBA	SHMLBA
-#endif
-
-#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
-COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
-	u32, third, compat_uptr_t, ptr, u32, fifth)
-{
-	int version;
-	u32 pad;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
-	case SEMTIMEDOP:
-		return compat_sys_semtimedop(first, compat_ptr(ptr), second,
-						compat_ptr(fifth));
-	case SEMGET:
-		return sys_semget(first, second, third);
-	case SEMCTL:
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
-			return -EFAULT;
-		return compat_sys_semctl(first, second, third, pad);
-
-	case MSGSND: {
-		struct compat_msgbuf __user *up = compat_ptr(ptr);
-		compat_long_t type;
-
-		if (first < 0 || second < 0)
-			return -EINVAL;
-
-		if (get_user(type, &up->mtype))
-			return -EFAULT;
-
-		return do_msgsnd(first, type, up->mtext, second, third);
-	}
-	case MSGRCV: {
-		void __user *uptr = compat_ptr(ptr);
-
-		if (first < 0 || second < 0)
-			return -EINVAL;
-
-		if (!version) {
-			struct compat_ipc_kludge ipck;
-			if (!uptr)
-				return -EINVAL;
-			if (copy_from_user(&ipck, uptr, sizeof(ipck)))
-				return -EFAULT;
-			uptr = compat_ptr(ipck.msgp);
-			fifth = ipck.msgtyp;
-		}
-		return do_msgrcv(first, uptr, second, (s32)fifth, third,
-				 compat_do_msg_fill);
-	}
-	case MSGGET:
-		return sys_msgget(first, second);
-	case MSGCTL:
-		return compat_sys_msgctl(first, second, compat_ptr(ptr));
-
-	case SHMAT: {
-		int err;
-		unsigned long raddr;
-
-		if (version == 1)
-			return -EINVAL;
-		err = do_shmat(first, compat_ptr(ptr), second, &raddr,
-			       COMPAT_SHMLBA);
-		if (err < 0)
-			return err;
-		return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
-	}
-	case SHMDT:
-		return sys_shmdt(compat_ptr(ptr));
-	case SHMGET:
-		return sys_shmget(first, (unsigned)second, third);
-	case SHMCTL:
-		return compat_sys_shmctl(first, second, compat_ptr(ptr));
-	}
-
-	return -ENOSYS;
-}
-#endif
-
 COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
 		       compat_ssize_t, msgsz, int, msgflg)
 {
@@ -211,6 +117,10 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
 			 msgflg, compat_do_msg_fill);
 }
 
+#ifndef COMPAT_SHMLBA
+#define COMPAT_SHMLBA	SHMLBA
+#endif
+
 COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
 {
 	unsigned long ret;
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 52429489cde0..667022746ca5 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -5,12 +5,12 @@
  * the individual syscalls instead.
  */
 #include <linux/unistd.h>
+#include <linux/syscalls.h>
 
 #ifdef __ARCH_WANT_SYS_IPC
 #include <linux/errno.h>
 #include <linux/ipc.h>
 #include <linux/shm.h>
-#include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
 SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
@@ -97,3 +97,91 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
 	}
 }
 #endif
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+#ifndef COMPAT_SHMLBA
+#define COMPAT_SHMLBA	SHMLBA
+#endif
+
+struct compat_ipc_kludge {
+	compat_uptr_t msgp;
+	compat_long_t msgtyp;
+};
+
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
+COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
+	u32, third, compat_uptr_t, ptr, u32, fifth)
+{
+	int version;
+	u32 pad;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	switch (call) {
+	case SEMOP:
+		/* struct sembuf is the same on 32 and 64bit :)) */
+		return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
+	case SEMTIMEDOP:
+		return compat_sys_semtimedop(first, compat_ptr(ptr), second,
+						compat_ptr(fifth));
+	case SEMGET:
+		return sys_semget(first, second, third);
+	case SEMCTL:
+		if (!ptr)
+			return -EINVAL;
+		if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
+			return -EFAULT;
+		return compat_sys_semctl(first, second, third, pad);
+
+	case MSGSND:
+		return compat_sys_msgsnd(first, ptr, second, third);
+
+	case MSGRCV: {
+		void __user *uptr = compat_ptr(ptr);
+
+		if (first < 0 || second < 0)
+			return -EINVAL;
+
+		if (!version) {
+			struct compat_ipc_kludge ipck;
+			if (!uptr)
+				return -EINVAL;
+			if (copy_from_user(&ipck, uptr, sizeof(ipck)))
+				return -EFAULT;
+			return compat_sys_msgrcv(first, ipck.msgp, second,
+						 ipck.msgtyp, third);
+		}
+		return compat_sys_msgrcv(first, ptr, second, fifth, third);
+	}
+	case MSGGET:
+		return sys_msgget(first, second);
+	case MSGCTL:
+		return compat_sys_msgctl(first, second, compat_ptr(ptr));
+
+	case SHMAT: {
+		int err;
+		unsigned long raddr;
+
+		if (version == 1)
+			return -EINVAL;
+		err = do_shmat(first, compat_ptr(ptr), second, &raddr,
+			       COMPAT_SHMLBA);
+		if (err < 0)
+			return err;
+		return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
+	}
+	case SHMDT:
+		return sys_shmdt(compat_ptr(ptr));
+	case SHMGET:
+		return sys_shmget(first, (unsigned)second, third);
+	case SHMCTL:
+		return compat_sys_shmctl(first, second, compat_ptr(ptr));
+	}
+
+	return -ENOSYS;
+}
+#endif
+#endif
-- 
cgit v1.2.3-58-ga151


From 9b1404c24a357332cb2a6df7c4337e943a4545fd Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 9 Jul 2017 10:34:35 -0400
Subject: msgrcv(2), msgsnd(2): move compat to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/msg.h |  8 --------
 ipc/compat.c        | 37 -------------------------------------
 ipc/msg.c           | 45 +++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 43 insertions(+), 47 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/include/linux/msg.h b/include/linux/msg.h
index f3f302f9c197..4e5ec3cbf464 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -31,12 +31,4 @@ struct msg_queue {
 	struct list_head q_senders;
 };
 
-/* Helper routines for sys_msgsnd and sys_msgrcv */
-extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
-			size_t msgsz, int msgflg);
-extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
-		      int msgflg,
-		      long (*msg_fill)(void __user *, struct msg_msg *,
-				       size_t));
-
 #endif /* _LINUX_MSG_H */
diff --git a/ipc/compat.c b/ipc/compat.c
index 00c2e3beccc8..0586687c3e31 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -34,11 +34,6 @@
 
 #include "util.h"
 
-struct compat_msgbuf {
-	compat_long_t mtype;
-	char mtext[1];
-};
-
 int get_compat_ipc64_perm(struct ipc64_perm *to,
 			  struct compat_ipc64_perm __user *from)
 {
@@ -85,38 +80,6 @@ void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
 	to->seq = from->seq;
 }
 
-static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
-{
-	struct compat_msgbuf __user *msgp = dest;
-	size_t msgsz;
-
-	if (put_user(msg->m_type, &msgp->mtype))
-		return -EFAULT;
-
-	msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
-	if (store_msg(msgp->mtext, msg, msgsz))
-		return -EFAULT;
-	return msgsz;
-}
-
-COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
-		       compat_ssize_t, msgsz, int, msgflg)
-{
-	struct compat_msgbuf __user *up = compat_ptr(msgp);
-	compat_long_t mtype;
-
-	if (get_user(mtype, &up->mtype))
-		return -EFAULT;
-	return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
-}
-
-COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
-		       compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
-{
-	return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
-			 msgflg, compat_do_msg_fill);
-}
-
 #ifndef COMPAT_SHMLBA
 #define COMPAT_SHMLBA	SHMLBA
 #endif
diff --git a/ipc/msg.c b/ipc/msg.c
index 94690fb53f66..855da19c765a 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -730,7 +730,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
 	return 0;
 }
 
-long do_msgsnd(int msqid, long mtype, void __user *mtext,
+static long do_msgsnd(int msqid, long mtype, void __user *mtext,
 		size_t msgsz, int msgflg)
 {
 	struct msg_queue *msq;
@@ -853,6 +853,25 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 	return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
 }
 
+#ifdef CONFIG_COMPAT
+
+struct compat_msgbuf {
+	compat_long_t mtype;
+	char mtext[1];
+};
+
+COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
+		       compat_ssize_t, msgsz, int, msgflg)
+{
+	struct compat_msgbuf __user *up = compat_ptr(msgp);
+	compat_long_t mtype;
+
+	if (get_user(mtype, &up->mtype))
+		return -EFAULT;
+	return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
+}
+#endif
+
 static inline int convert_mode(long *msgtyp, int msgflg)
 {
 	if (msgflg & MSG_COPY)
@@ -949,7 +968,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
 	return found ?: ERR_PTR(-EAGAIN);
 }
 
-long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
+static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
 	       long (*msg_handler)(void __user *, struct msg_msg *, size_t))
 {
 	int mode;
@@ -1113,6 +1132,28 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
 }
 
+#ifdef CONFIG_COMPAT
+static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+	struct compat_msgbuf __user *msgp = dest;
+	size_t msgsz;
+
+	if (put_user(msg->m_type, &msgp->mtype))
+		return -EFAULT;
+
+	msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+	if (store_msg(msgp->mtext, msg, msgsz))
+		return -EFAULT;
+	return msgsz;
+}
+
+COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
+		       compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
+{
+	return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
+			 msgflg, compat_do_msg_fill);
+}
+#endif
 
 void msg_init_ns(struct ipc_namespace *ns)
 {
-- 
cgit v1.2.3-58-ga151


From a78ee9ed2f828e1960f366bf7ab204e7f19924c7 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 9 Jul 2017 10:38:28 -0400
Subject: shmat(2): move compat to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 ipc/compat.c | 16 ----------------
 ipc/shm.c    | 19 +++++++++++++++++++
 2 files changed, 19 insertions(+), 16 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/ipc/compat.c b/ipc/compat.c
index 0586687c3e31..871d07da0a52 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -80,22 +80,6 @@ void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
 	to->seq = from->seq;
 }
 
-#ifndef COMPAT_SHMLBA
-#define COMPAT_SHMLBA	SHMLBA
-#endif
-
-COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
-{
-	unsigned long ret;
-	long err;
-
-	err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);
-	if (err)
-		return err;
-	force_successful_syscall_return();
-	return (long)ret;
-}
-
 COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
 		       unsigned, nsops,
 		       const struct compat_timespec __user *, timeout)
diff --git a/ipc/shm.c b/ipc/shm.c
index 2e31545035a6..342024de3b9d 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1439,6 +1439,25 @@ SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
 	return (long)ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+#ifndef COMPAT_SHMLBA
+#define COMPAT_SHMLBA	SHMLBA
+#endif
+
+COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
+{
+	unsigned long ret;
+	long err;
+
+	err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);
+	if (err)
+		return err;
+	force_successful_syscall_return();
+	return (long)ret;
+}
+#endif
+
 /*
  * detach and kill segment if marked destroyed.
  * The work is done in shm_close.
-- 
cgit v1.2.3-58-ga151


From 44ee454670122a959112caaa7aad86d8cacab1ff Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 9 Jul 2017 10:50:14 -0400
Subject: semtimedop(): move compat to native

... and finally kill the sodding compat_convert_timespec()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/compat.h |  9 ---------
 ipc/compat.c           | 10 ----------
 ipc/sem.c              | 44 +++++++++++++++++++++++++++++++++-----------
 kernel/compat.c        | 23 -----------------------
 4 files changed, 33 insertions(+), 53 deletions(-)

(limited to 'ipc/compat.c')

diff --git a/include/linux/compat.h b/include/linux/compat.h
index 5a6a109b4a50..edae425ca8c0 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -171,15 +171,6 @@ extern int get_compat_itimerspec64(struct itimerspec64 *its,
 extern int put_compat_itimerspec64(const struct itimerspec64 *its,
 			struct compat_itimerspec __user *uits);
 
-/*
- * This function convert a timespec if necessary and returns a *user
- * space* pointer.  If no conversion is necessary, it returns the
- * initial pointer.  NULL is a legitimate argument and will always
- * output NULL.
- */
-extern int compat_convert_timespec(struct timespec __user **,
-				   const void __user *);
-
 struct compat_iovec {
 	compat_uptr_t	iov_base;
 	compat_size_t	iov_len;
diff --git a/ipc/compat.c b/ipc/compat.c
index 871d07da0a52..b17bf93d7b49 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -79,13 +79,3 @@ void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
 	to->mode = from->mode;
 	to->seq = from->seq;
 }
-
-COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
-		       unsigned, nsops,
-		       const struct compat_timespec __user *, timeout)
-{
-	struct timespec __user *ts64;
-	if (compat_convert_timespec(&ts64, timeout))
-		return -EFAULT;
-	return sys_semtimedop(semid, tsems, nsops, ts64);
-}
diff --git a/ipc/sem.c b/ipc/sem.c
index fcf064d6046a..6b832b7fa9fc 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1855,8 +1855,8 @@ out:
 	return un;
 }
 
-SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
-		unsigned, nsops, const struct timespec __user *, timeout)
+static long do_semtimedop(int semid, struct sembuf __user *tsops,
+		unsigned nsops, const struct timespec *timeout)
 {
 	int error = -EINVAL;
 	struct sem_array *sma;
@@ -1887,17 +1887,12 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	}
 
 	if (timeout) {
-		struct timespec _timeout;
-		if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) {
-			error = -EFAULT;
-			goto out_free;
-		}
-		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
-			_timeout.tv_nsec >= 1000000000L) {
+		if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 ||
+			timeout->tv_nsec >= 1000000000L) {
 			error = -EINVAL;
 			goto out_free;
 		}
-		jiffies_left = timespec_to_jiffies(&_timeout);
+		jiffies_left = timespec_to_jiffies(timeout);
 	}
 
 	max = 0;
@@ -2112,10 +2107,37 @@ out_free:
 	return error;
 }
 
+SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
+		unsigned, nsops, const struct timespec __user *, timeout)
+{
+	if (timeout) {
+		struct timespec ts;
+		if (copy_from_user(&ts, timeout, sizeof(*timeout)))
+			return -EFAULT;
+		return do_semtimedop(semid, tsops, nsops, &ts);
+	}
+	return do_semtimedop(semid, tsops, nsops, NULL);
+}
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
+		       unsigned, nsops,
+		       const struct compat_timespec __user *, timeout)
+{
+	if (timeout) {
+		struct timespec ts;
+		if (compat_get_timespec(&ts, timeout))
+			return -EFAULT;
+		return do_semtimedop(semid, tsems, nsops, &ts);
+	}
+	return do_semtimedop(semid, tsems, nsops, NULL);
+}
+#endif
+
 SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
 		unsigned, nsops)
 {
-	return sys_semtimedop(semid, tsops, nsops, NULL);
+	return do_semtimedop(semid, tsops, nsops, NULL);
 }
 
 /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
diff --git a/kernel/compat.c b/kernel/compat.c
index 6f0a0e723a06..772e038d04d9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -200,29 +200,6 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
 }
 EXPORT_SYMBOL_GPL(compat_put_timespec);
 
-int compat_convert_timespec(struct timespec __user **kts,
-			    const void __user *cts)
-{
-	struct timespec ts;
-	struct timespec __user *uts;
-
-	if (!cts || COMPAT_USE_64BIT_TIME) {
-		*kts = (struct timespec __user *)cts;
-		return 0;
-	}
-
-	uts = compat_alloc_user_space(sizeof(ts));
-	if (!uts)
-		return -EFAULT;
-	if (compat_get_timespec(&ts, cts))
-		return -EFAULT;
-	if (copy_to_user(uts, &ts, sizeof(ts)))
-		return -EFAULT;
-
-	*kts = uts;
-	return 0;
-}
-
 int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
 {
 	struct compat_itimerval v32;
-- 
cgit v1.2.3-58-ga151