backported vs2.1.x fix to irq handling, which caused incorrect scheduler behavior
[linux-2.6.git] / ipc / msg.c
1 /*
2  * linux/ipc/msg.c
3  * Copyright (C) 1992 Krishna Balasubramanian
4  *
5  * Removed all the remaining kerneld mess
6  * Catch the -EFAULT stuff properly
7  * Use GFP_KERNEL for messages as in 1.2
8  * Fixed up the unchecked user space derefs
9  * Copyright (C) 1998 Alan Cox & Andi Kleen
10  *
11  * /proc/sysvipc/msg support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
12  *
13  * mostly rewritten, threaded and wake-one semantics added
14  * MSGMAX limit removed, sysctl's added
15  * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
16  *
17  * support for audit of ipc object properties and permission changes
18  * Dustin Kirkland <dustin.kirkland@us.ibm.com>
19  */
20
21 #include <linux/capability.h>
22 #include <linux/slab.h>
23 #include <linux/msg.h>
24 #include <linux/spinlock.h>
25 #include <linux/init.h>
26 #include <linux/proc_fs.h>
27 #include <linux/list.h>
28 #include <linux/security.h>
29 #include <linux/sched.h>
30 #include <linux/syscalls.h>
31 #include <linux/audit.h>
32 #include <linux/seq_file.h>
33 #include <linux/mutex.h>
34 #include <linux/vs_base.h>
35
36 #include <asm/current.h>
37 #include <asm/uaccess.h>
38 #include "util.h"
39
40 /* sysctl: */
41 int msg_ctlmax = MSGMAX;
42 int msg_ctlmnb = MSGMNB;
43 int msg_ctlmni = MSGMNI;
44
45 /*
46  * one msg_receiver structure for each sleeping receiver:
47  */
48 struct msg_receiver {
49         struct list_head        r_list;
50         struct task_struct      *r_tsk;
51
52         int                     r_mode;
53         long                    r_msgtype;
54         long                    r_maxsize;
55
56         volatile struct msg_msg *r_msg;
57 };
58
59 /* one msg_sender for each sleeping sender */
60 struct msg_sender {
61         struct list_head        list;
62         struct task_struct      *tsk;
63 };
64
65 #define SEARCH_ANY              1
66 #define SEARCH_EQUAL            2
67 #define SEARCH_NOTEQUAL         3
68 #define SEARCH_LESSEQUAL        4
69
70 static atomic_t msg_bytes =     ATOMIC_INIT(0);
71 static atomic_t msg_hdrs =      ATOMIC_INIT(0);
72
73 static struct ipc_ids msg_ids;
74
75 #define msg_lock(id)            ((struct msg_queue *)ipc_lock(&msg_ids, id))
76 #define msg_unlock(msq)         ipc_unlock(&(msq)->q_perm)
77 #define msg_rmid(id)            ((struct msg_queue *)ipc_rmid(&msg_ids, id))
78 #define msg_checkid(msq, msgid) ipc_checkid(&msg_ids, &msq->q_perm, msgid)
79 #define msg_buildid(id, seq)    ipc_buildid(&msg_ids, id, seq)
80
81 static void freeque(struct msg_queue *msq, int id);
82 static int newque(key_t key, int msgflg);
83 #ifdef CONFIG_PROC_FS
84 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
85 #endif
86
87 void __init msg_init(void)
88 {
89         ipc_init_ids(&msg_ids, msg_ctlmni);
90         ipc_init_proc_interface("sysvipc/msg",
91                                 "       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",
92                                 &msg_ids,
93                                 sysvipc_msg_proc_show);
94 }
95
96 static int newque(key_t key, int msgflg)
97 {
98         struct msg_queue *msq;
99         int id, retval;
100
101         msq = ipc_rcu_alloc(sizeof(*msq));
102         if (!msq)
103                 return -ENOMEM;
104
105         msq->q_perm.mode = msgflg & S_IRWXUGO;
106         msq->q_perm.key = key;
107         msq->q_perm.xid = vx_current_xid();
108
109         msq->q_perm.security = NULL;
110         retval = security_msg_queue_alloc(msq);
111         if (retval) {
112                 ipc_rcu_putref(msq);
113                 return retval;
114         }
115
116         id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
117         if (id == -1) {
118                 security_msg_queue_free(msq);
119                 ipc_rcu_putref(msq);
120                 return -ENOSPC;
121         }
122
123         msq->q_id = msg_buildid(id, msq->q_perm.seq);
124         msq->q_stime = msq->q_rtime = 0;
125         msq->q_ctime = get_seconds();
126         msq->q_cbytes = msq->q_qnum = 0;
127         msq->q_qbytes = msg_ctlmnb;
128         msq->q_lspid = msq->q_lrpid = 0;
129         INIT_LIST_HEAD(&msq->q_messages);
130         INIT_LIST_HEAD(&msq->q_receivers);
131         INIT_LIST_HEAD(&msq->q_senders);
132         msg_unlock(msq);
133
134         return msq->q_id;
135 }
136
137 static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
138 {
139         mss->tsk = current;
140         current->state = TASK_INTERRUPTIBLE;
141         list_add_tail(&mss->list, &msq->q_senders);
142 }
143
144 static inline void ss_del(struct msg_sender *mss)
145 {
146         if (mss->list.next != NULL)
147                 list_del(&mss->list);
148 }
149
150 static void ss_wakeup(struct list_head *h, int kill)
151 {
152         struct list_head *tmp;
153
154         tmp = h->next;
155         while (tmp != h) {
156                 struct msg_sender *mss;
157
158                 mss = list_entry(tmp, struct msg_sender, list);
159                 tmp = tmp->next;
160                 if (kill)
161                         mss->list.next = NULL;
162                 wake_up_process(mss->tsk);
163         }
164 }
165
166 static void expunge_all(struct msg_queue *msq, int res)
167 {
168         struct list_head *tmp;
169
170         tmp = msq->q_receivers.next;
171         while (tmp != &msq->q_receivers) {
172                 struct msg_receiver *msr;
173
174                 msr = list_entry(tmp, struct msg_receiver, r_list);
175                 tmp = tmp->next;
176                 msr->r_msg = NULL;
177                 wake_up_process(msr->r_tsk);
178                 smp_mb();
179                 msr->r_msg = ERR_PTR(res);
180         }
181 }
182
183 /*
184  * freeque() wakes up waiters on the sender and receiver waiting queue,
185  * removes the message queue from message queue ID
186  * array, and cleans up all the messages associated with this queue.
187  *
188  * msg_ids.mutex and the spinlock for this message queue is hold
189  * before freeque() is called. msg_ids.mutex remains locked on exit.
190  */
191 static void freeque(struct msg_queue *msq, int id)
192 {
193         struct list_head *tmp;
194
195         expunge_all(msq, -EIDRM);
196         ss_wakeup(&msq->q_senders, 1);
197         msq = msg_rmid(id);
198         msg_unlock(msq);
199
200         tmp = msq->q_messages.next;
201         while (tmp != &msq->q_messages) {
202                 struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list);
203
204                 tmp = tmp->next;
205                 atomic_dec(&msg_hdrs);
206                 free_msg(msg);
207         }
208         atomic_sub(msq->q_cbytes, &msg_bytes);
209         security_msg_queue_free(msq);
210         ipc_rcu_putref(msq);
211 }
212
213 asmlinkage long sys_msgget(key_t key, int msgflg)
214 {
215         struct msg_queue *msq;
216         int id, ret = -EPERM;
217         
218         mutex_lock(&msg_ids.mutex);
219         if (key == IPC_PRIVATE) 
220                 ret = newque(key, msgflg);
221         else if ((id = ipc_findkey(&msg_ids, key)) == -1) { /* key not used */
222                 if (!(msgflg & IPC_CREAT))
223                         ret = -ENOENT;
224                 else
225                         ret = newque(key, msgflg);
226         } else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) {
227                 ret = -EEXIST;
228         } else {
229                 msq = msg_lock(id);
230                 BUG_ON(msq == NULL);
231                 if (ipcperms(&msq->q_perm, msgflg))
232                         ret = -EACCES;
233                 else {
234                         int qid = msg_buildid(id, msq->q_perm.seq);
235
236                         ret = security_msg_queue_associate(msq, msgflg);
237                         if (!ret)
238                                 ret = qid;
239                 }
240                 msg_unlock(msq);
241         }
242         mutex_unlock(&msg_ids.mutex);
243
244         return ret;
245 }
246
247 static inline unsigned long
248 copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
249 {
250         switch(version) {
251         case IPC_64:
252                 return copy_to_user(buf, in, sizeof(*in));
253         case IPC_OLD:
254         {
255                 struct msqid_ds out;
256
257                 memset(&out, 0, sizeof(out));
258
259                 ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm);
260
261                 out.msg_stime           = in->msg_stime;
262                 out.msg_rtime           = in->msg_rtime;
263                 out.msg_ctime           = in->msg_ctime;
264
265                 if (in->msg_cbytes > USHRT_MAX)
266                         out.msg_cbytes  = USHRT_MAX;
267                 else
268                         out.msg_cbytes  = in->msg_cbytes;
269                 out.msg_lcbytes         = in->msg_cbytes;
270
271                 if (in->msg_qnum > USHRT_MAX)
272                         out.msg_qnum    = USHRT_MAX;
273                 else
274                         out.msg_qnum    = in->msg_qnum;
275
276                 if (in->msg_qbytes > USHRT_MAX)
277                         out.msg_qbytes  = USHRT_MAX;
278                 else
279                         out.msg_qbytes  = in->msg_qbytes;
280                 out.msg_lqbytes         = in->msg_qbytes;
281
282                 out.msg_lspid           = in->msg_lspid;
283                 out.msg_lrpid           = in->msg_lrpid;
284
285                 return copy_to_user(buf, &out, sizeof(out));
286         }
287         default:
288                 return -EINVAL;
289         }
290 }
291
292 struct msq_setbuf {
293         unsigned long   qbytes;
294         uid_t           uid;
295         gid_t           gid;
296         mode_t          mode;
297 };
298
299 static inline unsigned long
300 copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
301 {
302         switch(version) {
303         case IPC_64:
304         {
305                 struct msqid64_ds tbuf;
306
307                 if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
308                         return -EFAULT;
309
310                 out->qbytes             = tbuf.msg_qbytes;
311                 out->uid                = tbuf.msg_perm.uid;
312                 out->gid                = tbuf.msg_perm.gid;
313                 out->mode               = tbuf.msg_perm.mode;
314
315                 return 0;
316         }
317         case IPC_OLD:
318         {
319                 struct msqid_ds tbuf_old;
320
321                 if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
322                         return -EFAULT;
323
324                 out->uid                = tbuf_old.msg_perm.uid;
325                 out->gid                = tbuf_old.msg_perm.gid;
326                 out->mode               = tbuf_old.msg_perm.mode;
327
328                 if (tbuf_old.msg_qbytes == 0)
329                         out->qbytes     = tbuf_old.msg_lqbytes;
330                 else
331                         out->qbytes     = tbuf_old.msg_qbytes;
332
333                 return 0;
334         }
335         default:
336                 return -EINVAL;
337         }
338 }
339
340 asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
341 {
342         struct kern_ipc_perm *ipcp;
343         struct msq_setbuf setbuf;
344         struct msg_queue *msq;
345         int err, version;
346
347         if (msqid < 0 || cmd < 0)
348                 return -EINVAL;
349
350         version = ipc_parse_version(&cmd);
351
352         switch (cmd) {
353         case IPC_INFO:
354         case MSG_INFO:
355         {
356                 struct msginfo msginfo;
357                 int max_id;
358
359                 if (!buf)
360                         return -EFAULT;
361                 /*
362                  * We must not return kernel stack data.
363                  * due to padding, it's not enough
364                  * to set all member fields.
365                  */
366                 err = security_msg_queue_msgctl(NULL, cmd);
367                 if (err)
368                         return err;
369
370                 memset(&msginfo, 0, sizeof(msginfo));
371                 msginfo.msgmni = msg_ctlmni;
372                 msginfo.msgmax = msg_ctlmax;
373                 msginfo.msgmnb = msg_ctlmnb;
374                 msginfo.msgssz = MSGSSZ;
375                 msginfo.msgseg = MSGSEG;
376                 mutex_lock(&msg_ids.mutex);
377                 if (cmd == MSG_INFO) {
378                         msginfo.msgpool = msg_ids.in_use;
379                         msginfo.msgmap = atomic_read(&msg_hdrs);
380                         msginfo.msgtql = atomic_read(&msg_bytes);
381                 } else {
382                         msginfo.msgmap = MSGMAP;
383                         msginfo.msgpool = MSGPOOL;
384                         msginfo.msgtql = MSGTQL;
385                 }
386                 max_id = msg_ids.max_id;
387                 mutex_unlock(&msg_ids.mutex);
388                 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
389                         return -EFAULT;
390                 return (max_id < 0) ? 0 : max_id;
391         }
392         case MSG_STAT:
393         case IPC_STAT:
394         {
395                 struct msqid64_ds tbuf;
396                 int success_return;
397
398                 if (!buf)
399                         return -EFAULT;
400                 if (cmd == MSG_STAT && msqid >= msg_ids.entries->size)
401                         return -EINVAL;
402
403                 memset(&tbuf, 0, sizeof(tbuf));
404
405                 msq = msg_lock(msqid);
406                 if (msq == NULL)
407                         return -EINVAL;
408
409                 if (cmd == MSG_STAT) {
410                         success_return = msg_buildid(msqid, msq->q_perm.seq);
411                 } else {
412                         err = -EIDRM;
413                         if (msg_checkid(msq, msqid))
414                                 goto out_unlock;
415                         success_return = 0;
416                 }
417                 err = -EACCES;
418                 if (ipcperms(&msq->q_perm, S_IRUGO))
419                         goto out_unlock;
420
421                 err = security_msg_queue_msgctl(msq, cmd);
422                 if (err)
423                         goto out_unlock;
424
425                 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
426                 tbuf.msg_stime  = msq->q_stime;
427                 tbuf.msg_rtime  = msq->q_rtime;
428                 tbuf.msg_ctime  = msq->q_ctime;
429                 tbuf.msg_cbytes = msq->q_cbytes;
430                 tbuf.msg_qnum   = msq->q_qnum;
431                 tbuf.msg_qbytes = msq->q_qbytes;
432                 tbuf.msg_lspid  = msq->q_lspid;
433                 tbuf.msg_lrpid  = msq->q_lrpid;
434                 msg_unlock(msq);
435                 if (copy_msqid_to_user(buf, &tbuf, version))
436                         return -EFAULT;
437                 return success_return;
438         }
439         case IPC_SET:
440                 if (!buf)
441                         return -EFAULT;
442                 if (copy_msqid_from_user(&setbuf, buf, version))
443                         return -EFAULT;
444                 break;
445         case IPC_RMID:
446                 break;
447         default:
448                 return  -EINVAL;
449         }
450
451         mutex_lock(&msg_ids.mutex);
452         msq = msg_lock(msqid);
453         err = -EINVAL;
454         if (msq == NULL)
455                 goto out_up;
456
457         err = -EIDRM;
458         if (msg_checkid(msq, msqid))
459                 goto out_unlock_up;
460         ipcp = &msq->q_perm;
461
462         err = audit_ipc_obj(ipcp);
463         if (err)
464                 goto out_unlock_up;
465         if (cmd==IPC_SET) {
466                 err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
467                                          setbuf.mode);
468                 if (err)
469                         goto out_unlock_up;
470         }
471
472         err = -EPERM;
473         if (current->euid != ipcp->cuid &&
474             current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
475                 /* We _could_ check for CAP_CHOWN above, but we don't */
476                 goto out_unlock_up;
477
478         err = security_msg_queue_msgctl(msq, cmd);
479         if (err)
480                 goto out_unlock_up;
481
482         switch (cmd) {
483         case IPC_SET:
484         {
485                 err = -EPERM;
486                 if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
487                         goto out_unlock_up;
488
489                 msq->q_qbytes = setbuf.qbytes;
490
491                 ipcp->uid = setbuf.uid;
492                 ipcp->gid = setbuf.gid;
493                 ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
494                              (S_IRWXUGO & setbuf.mode);
495                 msq->q_ctime = get_seconds();
496                 /* sleeping receivers might be excluded by
497                  * stricter permissions.
498                  */
499                 expunge_all(msq, -EAGAIN);
500                 /* sleeping senders might be able to send
501                  * due to a larger queue size.
502                  */
503                 ss_wakeup(&msq->q_senders, 0);
504                 msg_unlock(msq);
505                 break;
506         }
507         case IPC_RMID:
508                 freeque(msq, msqid);
509                 break;
510         }
511         err = 0;
512 out_up:
513         mutex_unlock(&msg_ids.mutex);
514         return err;
515 out_unlock_up:
516         msg_unlock(msq);
517         goto out_up;
518 out_unlock:
519         msg_unlock(msq);
520         return err;
521 }
522
523 static int testmsg(struct msg_msg *msg, long type, int mode)
524 {
525         switch(mode)
526         {
527                 case SEARCH_ANY:
528                         return 1;
529                 case SEARCH_LESSEQUAL:
530                         if (msg->m_type <=type)
531                                 return 1;
532                         break;
533                 case SEARCH_EQUAL:
534                         if (msg->m_type == type)
535                                 return 1;
536                         break;
537                 case SEARCH_NOTEQUAL:
538                         if (msg->m_type != type)
539                                 return 1;
540                         break;
541         }
542         return 0;
543 }
544
545 static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
546 {
547         struct list_head *tmp;
548
549         tmp = msq->q_receivers.next;
550         while (tmp != &msq->q_receivers) {
551                 struct msg_receiver *msr;
552
553                 msr = list_entry(tmp, struct msg_receiver, r_list);
554                 tmp = tmp->next;
555                 if (testmsg(msg, msr->r_msgtype, msr->r_mode) &&
556                     !security_msg_queue_msgrcv(msq, msg, msr->r_tsk,
557                                                msr->r_msgtype, msr->r_mode)) {
558
559                         list_del(&msr->r_list);
560                         if (msr->r_maxsize < msg->m_ts) {
561                                 msr->r_msg = NULL;
562                                 wake_up_process(msr->r_tsk);
563                                 smp_mb();
564                                 msr->r_msg = ERR_PTR(-E2BIG);
565                         } else {
566                                 msr->r_msg = NULL;
567                                 msq->q_lrpid = msr->r_tsk->pid;
568                                 msq->q_rtime = get_seconds();
569                                 wake_up_process(msr->r_tsk);
570                                 smp_mb();
571                                 msr->r_msg = msg;
572
573                                 return 1;
574                         }
575                 }
576         }
577         return 0;
578 }
579
580 asmlinkage long
581 sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
582 {
583         struct msg_queue *msq;
584         struct msg_msg *msg;
585         long mtype;
586         int err;
587
588         if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0)
589                 return -EINVAL;
590         if (get_user(mtype, &msgp->mtype))
591                 return -EFAULT;
592         if (mtype < 1)
593                 return -EINVAL;
594
595         msg = load_msg(msgp->mtext, msgsz);
596         if (IS_ERR(msg))
597                 return PTR_ERR(msg);
598
599         msg->m_type = mtype;
600         msg->m_ts = msgsz;
601
602         msq = msg_lock(msqid);
603         err = -EINVAL;
604         if (msq == NULL)
605                 goto out_free;
606
607         err= -EIDRM;
608         if (msg_checkid(msq, msqid))
609                 goto out_unlock_free;
610
611         for (;;) {
612                 struct msg_sender s;
613
614                 err = -EACCES;
615                 if (ipcperms(&msq->q_perm, S_IWUGO))
616                         goto out_unlock_free;
617
618                 err = security_msg_queue_msgsnd(msq, msg, msgflg);
619                 if (err)
620                         goto out_unlock_free;
621
622                 if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
623                                 1 + msq->q_qnum <= msq->q_qbytes) {
624                         break;
625                 }
626
627                 /* queue full, wait: */
628                 if (msgflg & IPC_NOWAIT) {
629                         err = -EAGAIN;
630                         goto out_unlock_free;
631                 }
632                 ss_add(msq, &s);
633                 ipc_rcu_getref(msq);
634                 msg_unlock(msq);
635                 schedule();
636
637                 ipc_lock_by_ptr(&msq->q_perm);
638                 ipc_rcu_putref(msq);
639                 if (msq->q_perm.deleted) {
640                         err = -EIDRM;
641                         goto out_unlock_free;
642                 }
643                 ss_del(&s);
644
645                 if (signal_pending(current)) {
646                         err = -ERESTARTNOHAND;
647                         goto out_unlock_free;
648                 }
649         }
650
651         msq->q_lspid = current->tgid;
652         msq->q_stime = get_seconds();
653
654         if (!pipelined_send(msq, msg)) {
655                 /* noone is waiting for this message, enqueue it */
656                 list_add_tail(&msg->m_list, &msq->q_messages);
657                 msq->q_cbytes += msgsz;
658                 msq->q_qnum++;
659                 atomic_add(msgsz, &msg_bytes);
660                 atomic_inc(&msg_hdrs);
661         }
662
663         err = 0;
664         msg = NULL;
665
666 out_unlock_free:
667         msg_unlock(msq);
668 out_free:
669         if (msg != NULL)
670                 free_msg(msg);
671         return err;
672 }
673
674 static inline int convert_mode(long *msgtyp, int msgflg)
675 {
676         /*
677          *  find message of correct type.
678          *  msgtyp = 0 => get first.
679          *  msgtyp > 0 => get first message of matching type.
680          *  msgtyp < 0 => get message with least type must be < abs(msgtype).
681          */
682         if (*msgtyp == 0)
683                 return SEARCH_ANY;
684         if (*msgtyp < 0) {
685                 *msgtyp = -*msgtyp;
686                 return SEARCH_LESSEQUAL;
687         }
688         if (msgflg & MSG_EXCEPT)
689                 return SEARCH_NOTEQUAL;
690         return SEARCH_EQUAL;
691 }
692
693 asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
694                            long msgtyp, int msgflg)
695 {
696         struct msg_queue *msq;
697         struct msg_msg *msg;
698         int mode;
699
700         if (msqid < 0 || (long) msgsz < 0)
701                 return -EINVAL;
702         mode = convert_mode(&msgtyp, msgflg);
703
704         msq = msg_lock(msqid);
705         if (msq == NULL)
706                 return -EINVAL;
707
708         msg = ERR_PTR(-EIDRM);
709         if (msg_checkid(msq, msqid))
710                 goto out_unlock;
711
712         for (;;) {
713                 struct msg_receiver msr_d;
714                 struct list_head *tmp;
715
716                 msg = ERR_PTR(-EACCES);
717                 if (ipcperms(&msq->q_perm, S_IRUGO))
718                         goto out_unlock;
719
720                 msg = ERR_PTR(-EAGAIN);
721                 tmp = msq->q_messages.next;
722                 while (tmp != &msq->q_messages) {
723                         struct msg_msg *walk_msg;
724
725                         walk_msg = list_entry(tmp, struct msg_msg, m_list);
726                         if (testmsg(walk_msg, msgtyp, mode) &&
727                             !security_msg_queue_msgrcv(msq, walk_msg, current,
728                                                        msgtyp, mode)) {
729
730                                 msg = walk_msg;
731                                 if (mode == SEARCH_LESSEQUAL &&
732                                                 walk_msg->m_type != 1) {
733                                         msg = walk_msg;
734                                         msgtyp = walk_msg->m_type - 1;
735                                 } else {
736                                         msg = walk_msg;
737                                         break;
738                                 }
739                         }
740                         tmp = tmp->next;
741                 }
742                 if (!IS_ERR(msg)) {
743                         /*
744                          * Found a suitable message.
745                          * Unlink it from the queue.
746                          */
747                         if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
748                                 msg = ERR_PTR(-E2BIG);
749                                 goto out_unlock;
750                         }
751                         list_del(&msg->m_list);
752                         msq->q_qnum--;
753                         msq->q_rtime = get_seconds();
754                         msq->q_lrpid = current->tgid;
755                         msq->q_cbytes -= msg->m_ts;
756                         atomic_sub(msg->m_ts, &msg_bytes);
757                         atomic_dec(&msg_hdrs);
758                         ss_wakeup(&msq->q_senders, 0);
759                         msg_unlock(msq);
760                         break;
761                 }
762                 /* No message waiting. Wait for a message */
763                 if (msgflg & IPC_NOWAIT) {
764                         msg = ERR_PTR(-ENOMSG);
765                         goto out_unlock;
766                 }
767                 list_add_tail(&msr_d.r_list, &msq->q_receivers);
768                 msr_d.r_tsk = current;
769                 msr_d.r_msgtype = msgtyp;
770                 msr_d.r_mode = mode;
771                 if (msgflg & MSG_NOERROR)
772                         msr_d.r_maxsize = INT_MAX;
773                 else
774                         msr_d.r_maxsize = msgsz;
775                 msr_d.r_msg = ERR_PTR(-EAGAIN);
776                 current->state = TASK_INTERRUPTIBLE;
777                 msg_unlock(msq);
778
779                 schedule();
780
781                 /* Lockless receive, part 1:
782                  * Disable preemption.  We don't hold a reference to the queue
783                  * and getting a reference would defeat the idea of a lockless
784                  * operation, thus the code relies on rcu to guarantee the
785                  * existance of msq:
786                  * Prior to destruction, expunge_all(-EIRDM) changes r_msg.
787                  * Thus if r_msg is -EAGAIN, then the queue not yet destroyed.
788                  * rcu_read_lock() prevents preemption between reading r_msg
789                  * and the spin_lock() inside ipc_lock_by_ptr().
790                  */
791                 rcu_read_lock();
792
793                 /* Lockless receive, part 2:
794                  * Wait until pipelined_send or expunge_all are outside of
795                  * wake_up_process(). There is a race with exit(), see
796                  * ipc/mqueue.c for the details.
797                  */
798                 msg = (struct msg_msg*)msr_d.r_msg;
799                 while (msg == NULL) {
800                         cpu_relax();
801                         msg = (struct msg_msg *)msr_d.r_msg;
802                 }
803
804                 /* Lockless receive, part 3:
805                  * If there is a message or an error then accept it without
806                  * locking.
807                  */
808                 if (msg != ERR_PTR(-EAGAIN)) {
809                         rcu_read_unlock();
810                         break;
811                 }
812
813                 /* Lockless receive, part 3:
814                  * Acquire the queue spinlock.
815                  */
816                 ipc_lock_by_ptr(&msq->q_perm);
817                 rcu_read_unlock();
818
819                 /* Lockless receive, part 4:
820                  * Repeat test after acquiring the spinlock.
821                  */
822                 msg = (struct msg_msg*)msr_d.r_msg;
823                 if (msg != ERR_PTR(-EAGAIN))
824                         goto out_unlock;
825
826                 list_del(&msr_d.r_list);
827                 if (signal_pending(current)) {
828                         msg = ERR_PTR(-ERESTARTNOHAND);
829 out_unlock:
830                         msg_unlock(msq);
831                         break;
832                 }
833         }
834         if (IS_ERR(msg))
835                 return PTR_ERR(msg);
836
837         msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
838         if (put_user (msg->m_type, &msgp->mtype) ||
839             store_msg(msgp->mtext, msg, msgsz)) {
840                 msgsz = -EFAULT;
841         }
842         free_msg(msg);
843
844         return msgsz;
845 }
846
847 #ifdef CONFIG_PROC_FS
848 static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
849 {
850         struct msg_queue *msq = it;
851
852         if (!vx_check(msq->q_perm.xid, VX_IDENT))
853                 return 0;
854
855         return seq_printf(s,
856                         "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
857                         msq->q_perm.key,
858                         msq->q_id,
859                         msq->q_perm.mode,
860                         msq->q_cbytes,
861                         msq->q_qnum,
862                         msq->q_lspid,
863                         msq->q_lrpid,
864                         msq->q_perm.uid,
865                         msq->q_perm.gid,
866                         msq->q_perm.cuid,
867                         msq->q_perm.cgid,
868                         msq->q_stime,
869                         msq->q_rtime,
870                         msq->q_ctime);
871 }
872 #endif