diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/compat.c | 23 | ||||
-rw-r--r-- | ipc/mqueue.c | 6 | ||||
-rw-r--r-- | ipc/msg.c | 44 | ||||
-rw-r--r-- | ipc/sem.c | 3 | ||||
-rw-r--r-- | ipc/util.c | 7 |
5 files changed, 50 insertions, 33 deletions
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; |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 7c274002c9f5..3acc1661e517 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -90,7 +90,7 @@ static struct super_operations mqueue_super_ops; | |||
90 | static void remove_notification(struct mqueue_inode_info *info); | 90 | static void remove_notification(struct mqueue_inode_info *info); |
91 | 91 | ||
92 | static spinlock_t mq_lock; | 92 | static spinlock_t mq_lock; |
93 | static kmem_cache_t *mqueue_inode_cachep; | 93 | static struct kmem_cache *mqueue_inode_cachep; |
94 | static struct vfsmount *mqueue_mnt; | 94 | static struct vfsmount *mqueue_mnt; |
95 | 95 | ||
96 | static unsigned int queues_count; | 96 | static unsigned int queues_count; |
@@ -211,7 +211,7 @@ static int mqueue_get_sb(struct file_system_type *fs_type, | |||
211 | return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt); | 211 | return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt); |
212 | } | 212 | } |
213 | 213 | ||
214 | static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) | 214 | static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) |
215 | { | 215 | { |
216 | struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo; | 216 | struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo; |
217 | 217 | ||
@@ -224,7 +224,7 @@ static struct inode *mqueue_alloc_inode(struct super_block *sb) | |||
224 | { | 224 | { |
225 | struct mqueue_inode_info *ei; | 225 | struct mqueue_inode_info *ei; |
226 | 226 | ||
227 | ei = kmem_cache_alloc(mqueue_inode_cachep, SLAB_KERNEL); | 227 | ei = kmem_cache_alloc(mqueue_inode_cachep, GFP_KERNEL); |
228 | if (!ei) | 228 | if (!ei) |
229 | return NULL; | 229 | return NULL; |
230 | return &ei->vfs_inode; | 230 | return &ei->vfs_inode; |
@@ -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 | { |
@@ -1070,14 +1070,13 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | |||
1070 | ipc_rcu_getref(sma); | 1070 | ipc_rcu_getref(sma); |
1071 | sem_unlock(sma); | 1071 | sem_unlock(sma); |
1072 | 1072 | ||
1073 | new = (struct sem_undo *) kmalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL); | 1073 | new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL); |
1074 | if (!new) { | 1074 | if (!new) { |
1075 | ipc_lock_by_ptr(&sma->sem_perm); | 1075 | ipc_lock_by_ptr(&sma->sem_perm); |
1076 | ipc_rcu_putref(sma); | 1076 | ipc_rcu_putref(sma); |
1077 | sem_unlock(sma); | 1077 | sem_unlock(sma); |
1078 | return ERR_PTR(-ENOMEM); | 1078 | return ERR_PTR(-ENOMEM); |
1079 | } | 1079 | } |
1080 | memset(new, 0, sizeof(struct sem_undo) + sizeof(short)*nsems); | ||
1081 | new->semadj = (short *) &new[1]; | 1080 | new->semadj = (short *) &new[1]; |
1082 | new->semid = semid; | 1081 | new->semid = semid; |
1083 | 1082 | ||
diff --git a/ipc/util.c b/ipc/util.c index cd8bb14a431f..a9b7a227b8d4 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -514,6 +514,11 @@ void ipc_rcu_getref(void *ptr) | |||
514 | container_of(ptr, struct ipc_rcu_hdr, data)->refcount++; | 514 | container_of(ptr, struct ipc_rcu_hdr, data)->refcount++; |
515 | } | 515 | } |
516 | 516 | ||
517 | static void ipc_do_vfree(struct work_struct *work) | ||
518 | { | ||
519 | vfree(container_of(work, struct ipc_rcu_sched, work)); | ||
520 | } | ||
521 | |||
517 | /** | 522 | /** |
518 | * ipc_schedule_free - free ipc + rcu space | 523 | * ipc_schedule_free - free ipc + rcu space |
519 | * @head: RCU callback structure for queued work | 524 | * @head: RCU callback structure for queued work |
@@ -528,7 +533,7 @@ static void ipc_schedule_free(struct rcu_head *head) | |||
528 | struct ipc_rcu_sched *sched = | 533 | struct ipc_rcu_sched *sched = |
529 | container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]); | 534 | container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]); |
530 | 535 | ||
531 | INIT_WORK(&sched->work, vfree, sched); | 536 | INIT_WORK(&sched->work, ipc_do_vfree); |
532 | schedule_work(&sched->work); | 537 | schedule_work(&sched->work); |
533 | } | 538 | } |
534 | 539 | ||