aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/msg.h6
-rw-r--r--ipc/compat.c23
-rw-r--r--ipc/msg.c44
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 */
96extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
97 size_t msgsz, int msgflg);
98extern 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
116extern int sem_ctls[]; 116extern int sem_ctls[];
117#define sc_semopm (sem_ctls[2]) 117#define sc_semopm (sem_ctls[2])
118#define MAXBUF (64*1024)
119 118
120static inline int compat_ipc_parse_version(int *cmd) 119static 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
308long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) 307long 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
328long compat_sys_msgrcv(int first, int second, int msgtyp, int third, 323long 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;
361out: 352out:
362 return err; 353 return err;
diff --git a/ipc/msg.c b/ipc/msg.c
index 1266b1d0c8e3..a388824740e7 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -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
629asmlinkage long 629long do_msgsnd(int msqid, long mtype, void __user *mtext,
630sys_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
723asmlinkage long
724sys_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
726static inline int convert_mode(long *msgtyp, int msgflg) 733static 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
745asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, 752long 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
908asmlinkage 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;
919out:
920 return err;
921}
922
901#ifdef CONFIG_PROC_FS 923#ifdef CONFIG_PROC_FS
902static int sysvipc_msg_proc_show(struct seq_file *s, void *it) 924static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
903{ 925{