diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2013-01-04 18:34:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-04 19:11:45 -0500 |
commit | f9dd87f4738c7555aca2cdf8cb2b2326cafb0cad (patch) | |
tree | 4fb581910eaee4309ae6befeef8c4f921b274c5d | |
parent | 03f595668017f1a1fb971c02fc37140bc6e7bb1c (diff) |
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: Stanislav 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: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/msg.h | 5 | ||||
-rw-r--r-- | ipc/compat.c | 45 | ||||
-rw-r--r-- | ipc/msg.c | 44 |
3 files changed, 45 insertions, 49 deletions
diff --git a/include/linux/msg.h b/include/linux/msg.h index 7a4b9e97d29a..fc5743a554e6 100644 --- a/include/linux/msg.h +++ b/include/linux/msg.h | |||
@@ -34,7 +34,8 @@ struct msg_queue { | |||
34 | /* Helper routines for sys_msgsnd and sys_msgrcv */ | 34 | /* Helper routines for sys_msgsnd and sys_msgrcv */ |
35 | extern long do_msgsnd(int msqid, long mtype, void __user *mtext, | 35 | extern long do_msgsnd(int msqid, long mtype, void __user *mtext, |
36 | size_t msgsz, int msgflg); | 36 | size_t msgsz, int msgflg); |
37 | extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | 37 | extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, |
38 | size_t msgsz, long msgtyp, int msgflg); | 38 | int msgflg, |
39 | long (*msg_fill)(void __user *, struct msg_msg *, size_t)); | ||
39 | 40 | ||
40 | #endif /* _LINUX_MSG_H */ | 41 | #endif /* _LINUX_MSG_H */ |
diff --git a/ipc/compat.c b/ipc/compat.c index ad9518eb26e0..eb3ea16d2d1d 100644 --- a/ipc/compat.c +++ b/ipc/compat.c | |||
@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) | |||
306 | return err; | 306 | return err; |
307 | } | 307 | } |
308 | 308 | ||
309 | long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) | ||
310 | { | ||
311 | struct compat_msgbuf __user *msgp = dest; | ||
312 | size_t msgsz; | ||
313 | |||
314 | if (put_user(msg->m_type, &msgp->mtype)) | ||
315 | return -EFAULT; | ||
316 | |||
317 | msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; | ||
318 | if (store_msg(msgp->mtext, msg, msgsz)) | ||
319 | return -EFAULT; | ||
320 | return msgsz; | ||
321 | } | ||
322 | |||
309 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC | 323 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC |
310 | long compat_sys_semctl(int first, int second, int third, void __user *uptr) | 324 | long compat_sys_semctl(int first, int second, int third, void __user *uptr) |
311 | { | 325 | { |
@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) | |||
337 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | 351 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, |
338 | int version, void __user *uptr) | 352 | int version, void __user *uptr) |
339 | { | 353 | { |
340 | struct compat_msgbuf __user *up; | ||
341 | long type; | ||
342 | int err; | ||
343 | |||
344 | if (first < 0) | 354 | if (first < 0) |
345 | return -EINVAL; | 355 | return -EINVAL; |
346 | if (second < 0) | 356 | if (second < 0) |
@@ -348,23 +358,14 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | |||
348 | 358 | ||
349 | if (!version) { | 359 | if (!version) { |
350 | struct compat_ipc_kludge ipck; | 360 | struct compat_ipc_kludge ipck; |
351 | err = -EINVAL; | ||
352 | if (!uptr) | 361 | if (!uptr) |
353 | goto out; | 362 | return -EINVAL; |
354 | err = -EFAULT; | ||
355 | if (copy_from_user (&ipck, uptr, sizeof(ipck))) | 363 | if (copy_from_user (&ipck, uptr, sizeof(ipck))) |
356 | goto out; | 364 | return -EFAULT; |
357 | uptr = compat_ptr(ipck.msgp); | 365 | uptr = compat_ptr(ipck.msgp); |
358 | msgtyp = ipck.msgtyp; | 366 | msgtyp = ipck.msgtyp; |
359 | } | 367 | } |
360 | up = uptr; | 368 | return do_msgrcv(first, uptr, second, msgtyp, third, compat_do_msg_fill); |
361 | err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third); | ||
362 | if (err < 0) | ||
363 | goto out; | ||
364 | if (put_user(type, &up->mtype)) | ||
365 | err = -EFAULT; | ||
366 | out: | ||
367 | return err; | ||
368 | } | 369 | } |
369 | #else | 370 | #else |
370 | long compat_sys_semctl(int semid, int semnum, int cmd, int arg) | 371 | 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 | long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, | 386 | long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, |
386 | compat_ssize_t msgsz, long msgtyp, int msgflg) | 387 | compat_ssize_t msgsz, long msgtyp, int msgflg) |
387 | { | 388 | { |
388 | long err, mtype; | 389 | return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg, |
389 | 390 | compat_do_msg_fill); | |
390 | err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg); | ||
391 | if (err < 0) | ||
392 | goto out; | ||
393 | |||
394 | if (put_user(mtype, &msgp->mtype)) | ||
395 | err = -EFAULT; | ||
396 | out: | ||
397 | return err; | ||
398 | } | 391 | } |
399 | #endif | 392 | #endif |
400 | 393 | ||
@@ -755,15 +755,30 @@ static inline int convert_mode(long *msgtyp, int msgflg) | |||
755 | return SEARCH_EQUAL; | 755 | return SEARCH_EQUAL; |
756 | } | 756 | } |
757 | 757 | ||
758 | long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | 758 | static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) |
759 | size_t msgsz, long msgtyp, int msgflg) | 759 | { |
760 | struct msgbuf __user *msgp = dest; | ||
761 | size_t msgsz; | ||
762 | |||
763 | if (put_user(msg->m_type, &msgp->mtype)) | ||
764 | return -EFAULT; | ||
765 | |||
766 | msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; | ||
767 | if (store_msg(msgp->mtext, msg, msgsz)) | ||
768 | return -EFAULT; | ||
769 | return msgsz; | ||
770 | } | ||
771 | |||
772 | long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, | ||
773 | int msgflg, | ||
774 | long (*msg_handler)(void __user *, struct msg_msg *, size_t)) | ||
760 | { | 775 | { |
761 | struct msg_queue *msq; | 776 | struct msg_queue *msq; |
762 | struct msg_msg *msg; | 777 | struct msg_msg *msg; |
763 | int mode; | 778 | int mode; |
764 | struct ipc_namespace *ns; | 779 | struct ipc_namespace *ns; |
765 | 780 | ||
766 | if (msqid < 0 || (long) msgsz < 0) | 781 | if (msqid < 0 || (long) bufsz < 0) |
767 | return -EINVAL; | 782 | return -EINVAL; |
768 | mode = convert_mode(&msgtyp, msgflg); | 783 | mode = convert_mode(&msgtyp, msgflg); |
769 | ns = current->nsproxy->ipc_ns; | 784 | ns = current->nsproxy->ipc_ns; |
@@ -804,7 +819,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
804 | * Found a suitable message. | 819 | * Found a suitable message. |
805 | * Unlink it from the queue. | 820 | * Unlink it from the queue. |
806 | */ | 821 | */ |
807 | if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { | 822 | if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { |
808 | msg = ERR_PTR(-E2BIG); | 823 | msg = ERR_PTR(-E2BIG); |
809 | goto out_unlock; | 824 | goto out_unlock; |
810 | } | 825 | } |
@@ -831,7 +846,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
831 | if (msgflg & MSG_NOERROR) | 846 | if (msgflg & MSG_NOERROR) |
832 | msr_d.r_maxsize = INT_MAX; | 847 | msr_d.r_maxsize = INT_MAX; |
833 | else | 848 | else |
834 | msr_d.r_maxsize = msgsz; | 849 | msr_d.r_maxsize = bufsz; |
835 | msr_d.r_msg = ERR_PTR(-EAGAIN); | 850 | msr_d.r_msg = ERR_PTR(-EAGAIN); |
836 | current->state = TASK_INTERRUPTIBLE; | 851 | current->state = TASK_INTERRUPTIBLE; |
837 | msg_unlock(msq); | 852 | msg_unlock(msq); |
@@ -894,29 +909,16 @@ out_unlock: | |||
894 | if (IS_ERR(msg)) | 909 | if (IS_ERR(msg)) |
895 | return PTR_ERR(msg); | 910 | return PTR_ERR(msg); |
896 | 911 | ||
897 | msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; | 912 | bufsz = msg_handler(buf, msg, bufsz); |
898 | *pmtype = msg->m_type; | ||
899 | if (store_msg(mtext, msg, msgsz)) | ||
900 | msgsz = -EFAULT; | ||
901 | |||
902 | free_msg(msg); | 913 | free_msg(msg); |
903 | 914 | ||
904 | return msgsz; | 915 | return bufsz; |
905 | } | 916 | } |
906 | 917 | ||
907 | SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, | 918 | SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, |
908 | long, msgtyp, int, msgflg) | 919 | long, msgtyp, int, msgflg) |
909 | { | 920 | { |
910 | long err, mtype; | 921 | return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); |
911 | |||
912 | err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); | ||
913 | if (err < 0) | ||
914 | goto out; | ||
915 | |||
916 | if (put_user(mtype, &msgp->mtype)) | ||
917 | err = -EFAULT; | ||
918 | out: | ||
919 | return err; | ||
920 | } | 922 | } |
921 | 923 | ||
922 | #ifdef CONFIG_PROC_FS | 924 | #ifdef CONFIG_PROC_FS |