diff options
-rw-r--r-- | include/linux/msg.h | 6 | ||||
-rw-r--r-- | ipc/compat.c | 23 | ||||
-rw-r--r-- | ipc/msg.c | 44 |
3 files changed, 46 insertions, 27 deletions
diff --git a/include/linux/msg.h b/include/linux/msg.h index acc7c174ff00..f1b60740d641 100644 --- a/include/linux/msg.h +++ b/include/linux/msg.h | |||
@@ -92,6 +92,12 @@ struct msg_queue { | |||
92 | struct list_head q_senders; | 92 | struct list_head q_senders; |
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* Helper routines for sys_msgsnd and sys_msgrcv */ | ||
96 | extern long do_msgsnd(int msqid, long mtype, void __user *mtext, | ||
97 | size_t msgsz, int msgflg); | ||
98 | extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | ||
99 | size_t msgsz, long msgtyp, int msgflg); | ||
100 | |||
95 | #endif /* __KERNEL__ */ | 101 | #endif /* __KERNEL__ */ |
96 | 102 | ||
97 | #endif /* _LINUX_MSG_H */ | 103 | #endif /* _LINUX_MSG_H */ |
diff --git a/ipc/compat.c b/ipc/compat.c index 4d20cfd38f0a..fa18141539fb 100644 --- a/ipc/compat.c +++ b/ipc/compat.c | |||
@@ -115,7 +115,6 @@ struct compat_shm_info { | |||
115 | 115 | ||
116 | extern int sem_ctls[]; | 116 | extern int sem_ctls[]; |
117 | #define sc_semopm (sem_ctls[2]) | 117 | #define sc_semopm (sem_ctls[2]) |
118 | #define MAXBUF (64*1024) | ||
119 | 118 | ||
120 | static inline int compat_ipc_parse_version(int *cmd) | 119 | static inline int compat_ipc_parse_version(int *cmd) |
121 | { | 120 | { |
@@ -307,35 +306,30 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr) | |||
307 | 306 | ||
308 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) | 307 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) |
309 | { | 308 | { |
310 | struct msgbuf __user *p; | ||
311 | struct compat_msgbuf __user *up = uptr; | 309 | struct compat_msgbuf __user *up = uptr; |
312 | long type; | 310 | long type; |
313 | 311 | ||
314 | if (first < 0) | 312 | if (first < 0) |
315 | return -EINVAL; | 313 | return -EINVAL; |
316 | if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf))) | 314 | if (second < 0) |
317 | return -EINVAL; | 315 | return -EINVAL; |
318 | 316 | ||
319 | p = compat_alloc_user_space(second + sizeof(struct msgbuf)); | 317 | if (get_user(type, &up->mtype)) |
320 | if (get_user(type, &up->mtype) || | ||
321 | put_user(type, &p->mtype) || | ||
322 | copy_in_user(p->mtext, up->mtext, second)) | ||
323 | return -EFAULT; | 318 | return -EFAULT; |
324 | 319 | ||
325 | return sys_msgsnd(first, p, second, third); | 320 | return do_msgsnd(first, type, up->mtext, second, third); |
326 | } | 321 | } |
327 | 322 | ||
328 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | 323 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, |
329 | int version, void __user *uptr) | 324 | int version, void __user *uptr) |
330 | { | 325 | { |
331 | struct msgbuf __user *p; | ||
332 | struct compat_msgbuf __user *up; | 326 | struct compat_msgbuf __user *up; |
333 | long type; | 327 | long type; |
334 | int err; | 328 | int err; |
335 | 329 | ||
336 | if (first < 0) | 330 | if (first < 0) |
337 | return -EINVAL; | 331 | return -EINVAL; |
338 | if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf))) | 332 | if (second < 0) |
339 | return -EINVAL; | 333 | return -EINVAL; |
340 | 334 | ||
341 | if (!version) { | 335 | if (!version) { |
@@ -349,14 +343,11 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | |||
349 | uptr = compat_ptr(ipck.msgp); | 343 | uptr = compat_ptr(ipck.msgp); |
350 | msgtyp = ipck.msgtyp; | 344 | msgtyp = ipck.msgtyp; |
351 | } | 345 | } |
352 | p = compat_alloc_user_space(second + sizeof(struct msgbuf)); | 346 | up = uptr; |
353 | err = sys_msgrcv(first, p, second, msgtyp, third); | 347 | err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third); |
354 | if (err < 0) | 348 | if (err < 0) |
355 | goto out; | 349 | goto out; |
356 | up = uptr; | 350 | if (put_user(type, &up->mtype)) |
357 | if (get_user(type, &p->mtype) || | ||
358 | put_user(type, &up->mtype) || | ||
359 | copy_in_user(up->mtext, p->mtext, err)) | ||
360 | err = -EFAULT; | 351 | err = -EFAULT; |
361 | out: | 352 | out: |
362 | return err; | 353 | return err; |
@@ -626,12 +626,11 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg) | |||
626 | return 0; | 626 | return 0; |
627 | } | 627 | } |
628 | 628 | ||
629 | asmlinkage long | 629 | long do_msgsnd(int msqid, long mtype, void __user *mtext, |
630 | sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) | 630 | size_t msgsz, int msgflg) |
631 | { | 631 | { |
632 | struct msg_queue *msq; | 632 | struct msg_queue *msq; |
633 | struct msg_msg *msg; | 633 | struct msg_msg *msg; |
634 | long mtype; | ||
635 | int err; | 634 | int err; |
636 | struct ipc_namespace *ns; | 635 | struct ipc_namespace *ns; |
637 | 636 | ||
@@ -639,12 +638,10 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) | |||
639 | 638 | ||
640 | if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0) | 639 | if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0) |
641 | return -EINVAL; | 640 | return -EINVAL; |
642 | if (get_user(mtype, &msgp->mtype)) | ||
643 | return -EFAULT; | ||
644 | if (mtype < 1) | 641 | if (mtype < 1) |
645 | return -EINVAL; | 642 | return -EINVAL; |
646 | 643 | ||
647 | msg = load_msg(msgp->mtext, msgsz); | 644 | msg = load_msg(mtext, msgsz); |
648 | if (IS_ERR(msg)) | 645 | if (IS_ERR(msg)) |
649 | return PTR_ERR(msg); | 646 | return PTR_ERR(msg); |
650 | 647 | ||
@@ -723,6 +720,16 @@ out_free: | |||
723 | return err; | 720 | return err; |
724 | } | 721 | } |
725 | 722 | ||
723 | asmlinkage long | ||
724 | sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) | ||
725 | { | ||
726 | long mtype; | ||
727 | |||
728 | if (get_user(mtype, &msgp->mtype)) | ||
729 | return -EFAULT; | ||
730 | return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); | ||
731 | } | ||
732 | |||
726 | static inline int convert_mode(long *msgtyp, int msgflg) | 733 | static inline int convert_mode(long *msgtyp, int msgflg) |
727 | { | 734 | { |
728 | /* | 735 | /* |
@@ -742,8 +749,8 @@ static inline int convert_mode(long *msgtyp, int msgflg) | |||
742 | return SEARCH_EQUAL; | 749 | return SEARCH_EQUAL; |
743 | } | 750 | } |
744 | 751 | ||
745 | asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, | 752 | long do_msgrcv(int msqid, long *pmtype, void __user *mtext, |
746 | long msgtyp, int msgflg) | 753 | size_t msgsz, long msgtyp, int msgflg) |
747 | { | 754 | { |
748 | struct msg_queue *msq; | 755 | struct msg_queue *msq; |
749 | struct msg_msg *msg; | 756 | struct msg_msg *msg; |
@@ -889,15 +896,30 @@ out_unlock: | |||
889 | return PTR_ERR(msg); | 896 | return PTR_ERR(msg); |
890 | 897 | ||
891 | msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; | 898 | msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; |
892 | if (put_user (msg->m_type, &msgp->mtype) || | 899 | *pmtype = msg->m_type; |
893 | store_msg(msgp->mtext, msg, msgsz)) { | 900 | if (store_msg(mtext, msg, msgsz)) |
894 | msgsz = -EFAULT; | 901 | msgsz = -EFAULT; |
895 | } | 902 | |
896 | free_msg(msg); | 903 | free_msg(msg); |
897 | 904 | ||
898 | return msgsz; | 905 | return msgsz; |
899 | } | 906 | } |
900 | 907 | ||
908 | asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, | ||
909 | long msgtyp, int msgflg) | ||
910 | { | ||
911 | long err, mtype; | ||
912 | |||
913 | err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); | ||
914 | if (err < 0) | ||
915 | goto out; | ||
916 | |||
917 | if (put_user(mtype, &msgp->mtype)) | ||
918 | err = -EFAULT; | ||
919 | out: | ||
920 | return err; | ||
921 | } | ||
922 | |||
901 | #ifdef CONFIG_PROC_FS | 923 | #ifdef CONFIG_PROC_FS |
902 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it) | 924 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it) |
903 | { | 925 | { |