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 |
