Commit f9dd87f4 authored by Stanislav Kinsbursky's avatar Stanislav Kinsbursky Committed by Linus Torvalds

ipc: message queue receive cleanup

Move all message related manipulation into one function msg_fill().
Actually, two functions because of the compat one.

[akpm@linux-foundation.org: checkpatch fixes]
Signed-off-by: default avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 03f59566
...@@ -34,7 +34,8 @@ struct msg_queue { ...@@ -34,7 +34,8 @@ struct msg_queue {
/* Helper routines for sys_msgsnd and sys_msgrcv */ /* Helper routines for sys_msgsnd and sys_msgrcv */
extern long do_msgsnd(int msqid, long mtype, void __user *mtext, extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
size_t msgsz, int msgflg); size_t msgsz, int msgflg);
extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext, extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
size_t msgsz, long msgtyp, int msgflg); int msgflg,
long (*msg_fill)(void __user *, struct msg_msg *, size_t));
#endif /* _LINUX_MSG_H */ #endif /* _LINUX_MSG_H */
...@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) ...@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
return err; return err;
} }
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;
}
#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
long compat_sys_semctl(int first, int second, int third, void __user *uptr) long compat_sys_semctl(int first, int second, int third, void __user *uptr)
{ {
...@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) ...@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
long compat_sys_msgrcv(int first, int second, int msgtyp, int third, long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
int version, void __user *uptr) int version, void __user *uptr)
{ {
struct compat_msgbuf __user *up;
long type;
int err;
if (first < 0) if (first < 0)
return -EINVAL; return -EINVAL;
if (second < 0) if (second < 0)
...@@ -348,23 +358,14 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third, ...@@ -348,23 +358,14 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
if (!version) { if (!version) {
struct compat_ipc_kludge ipck; struct compat_ipc_kludge ipck;
err = -EINVAL;
if (!uptr) if (!uptr)
goto out; return -EINVAL;
err = -EFAULT;
if (copy_from_user (&ipck, uptr, sizeof(ipck))) if (copy_from_user (&ipck, uptr, sizeof(ipck)))
goto out; return -EFAULT;
uptr = compat_ptr(ipck.msgp); uptr = compat_ptr(ipck.msgp);
msgtyp = ipck.msgtyp; msgtyp = ipck.msgtyp;
} }
up = uptr; return do_msgrcv(first, uptr, second, msgtyp, third, compat_do_msg_fill);
err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
if (err < 0)
goto out;
if (put_user(type, &up->mtype))
err = -EFAULT;
out:
return err;
} }
#else #else
long compat_sys_semctl(int semid, int semnum, int cmd, int arg) long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
...@@ -385,16 +386,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, ...@@ -385,16 +386,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
compat_ssize_t msgsz, long msgtyp, int msgflg) compat_ssize_t msgsz, long msgtyp, int msgflg)
{ {
long err, mtype; return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg,
compat_do_msg_fill);
err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg);
if (err < 0)
goto out;
if (put_user(mtype, &msgp->mtype))
err = -EFAULT;
out:
return err;
} }
#endif #endif
......
...@@ -755,15 +755,30 @@ static inline int convert_mode(long *msgtyp, int msgflg) ...@@ -755,15 +755,30 @@ static inline int convert_mode(long *msgtyp, int msgflg)
return SEARCH_EQUAL; return SEARCH_EQUAL;
} }
long do_msgrcv(int msqid, long *pmtype, void __user *mtext, static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
size_t msgsz, long msgtyp, int msgflg) {
struct 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;
}
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))
{ {
struct msg_queue *msq; struct msg_queue *msq;
struct msg_msg *msg; struct msg_msg *msg;
int mode; int mode;
struct ipc_namespace *ns; struct ipc_namespace *ns;
if (msqid < 0 || (long) msgsz < 0) if (msqid < 0 || (long) bufsz < 0)
return -EINVAL; return -EINVAL;
mode = convert_mode(&msgtyp, msgflg); mode = convert_mode(&msgtyp, msgflg);
ns = current->nsproxy->ipc_ns; ns = current->nsproxy->ipc_ns;
...@@ -804,7 +819,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -804,7 +819,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
* Found a suitable message. * Found a suitable message.
* Unlink it from the queue. * Unlink it from the queue.
*/ */
if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
msg = ERR_PTR(-E2BIG); msg = ERR_PTR(-E2BIG);
goto out_unlock; goto out_unlock;
} }
...@@ -831,7 +846,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -831,7 +846,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
if (msgflg & MSG_NOERROR) if (msgflg & MSG_NOERROR)
msr_d.r_maxsize = INT_MAX; msr_d.r_maxsize = INT_MAX;
else else
msr_d.r_maxsize = msgsz; msr_d.r_maxsize = bufsz;
msr_d.r_msg = ERR_PTR(-EAGAIN); msr_d.r_msg = ERR_PTR(-EAGAIN);
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
msg_unlock(msq); msg_unlock(msq);
...@@ -894,29 +909,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -894,29 +909,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
if (IS_ERR(msg)) if (IS_ERR(msg))
return PTR_ERR(msg); return PTR_ERR(msg);
msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; bufsz = msg_handler(buf, msg, bufsz);
*pmtype = msg->m_type;
if (store_msg(mtext, msg, msgsz))
msgsz = -EFAULT;
free_msg(msg); free_msg(msg);
return msgsz; return bufsz;
} }
SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
long, msgtyp, int, msgflg) long, msgtyp, int, msgflg)
{ {
long err, mtype; return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
if (err < 0)
goto out;
if (put_user(mtype, &msgp->mtype))
err = -EFAULT;
out:
return err;
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment