Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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  * namespaces support
 21  * OpenVZ, SWsoft Inc.
 22  * Pavel Emelianov <xemul@openvz.org>
 23  */
 24 
 25 #include <linux/capability.h>
 26 #include <linux/slab.h>
 27 #include <linux/msg.h>
 28 #include <linux/spinlock.h>
 29 #include <linux/init.h>
 30 #include <linux/proc_fs.h>
 31 #include <linux/list.h>
 32 #include <linux/security.h>
 33 #include <linux/sched.h>
 34 #include <linux/syscalls.h>
 35 #include <linux/audit.h>
 36 #include <linux/seq_file.h>
 37 #include <linux/rwsem.h>
 38 #include <linux/nsproxy.h>
 39 #include <linux/ipc_namespace.h>
 40 
 41 #include <asm/current.h>
 42 #include <asm/uaccess.h>
 43 #include "util.h"
 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         struct msg_msg          *volatile 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 #define msg_ids(ns)     ((ns)->ids[IPC_MSG_IDS])
 71 
 72 #define msg_unlock(msq)         ipc_unlock(&(msq)->q_perm)
 73 #define msg_buildid(id, seq)    ipc_buildid(id, seq)
 74 
 75 static void freeque(struct ipc_namespace *, struct kern_ipc_perm *);
 76 static int newque(struct ipc_namespace *, struct ipc_params *);
 77 #ifdef CONFIG_PROC_FS
 78 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 79 #endif
 80 
 81 void msg_init_ns(struct ipc_namespace *ns)
 82 {
 83         ns->msg_ctlmax = MSGMAX;
 84         ns->msg_ctlmnb = MSGMNB;
 85         ns->msg_ctlmni = MSGMNI;
 86         atomic_set(&ns->msg_bytes, 0);
 87         atomic_set(&ns->msg_hdrs, 0);
 88         ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
 89 }
 90 
 91 #ifdef CONFIG_IPC_NS
 92 void msg_exit_ns(struct ipc_namespace *ns)
 93 {
 94         free_ipcs(ns, &msg_ids(ns), freeque);
 95 }
 96 #endif
 97 
 98 void __init msg_init(void)
 99 {
100         msg_init_ns(&init_ipc_ns);
101         ipc_init_proc_interface("sysvipc/msg",
102                                 "       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",
103                                 IPC_MSG_IDS, sysvipc_msg_proc_show);
104 }
105 
106 /*
107  * This routine is called in the paths where the rw_mutex is held to protect
108  * access to the idr tree.
109  */
110 static inline struct msg_queue *msg_lock_check_down(struct ipc_namespace *ns,
111                                                 int id)
112 {
113         struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
114 
115         if (IS_ERR(ipcp))
116                 return (struct msg_queue *)ipcp;
117 
118         return container_of(ipcp, struct msg_queue, q_perm);
119 }
120 
121 /*
122  * msg_lock_(check_) routines are called in the paths where the rw_mutex
123  * is not held.
124  */
125 static inline struct msg_queue *msg_lock(struct ipc_namespace *ns, int id)
126 {
127         struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id);
128 
129         if (IS_ERR(ipcp))
130                 return (struct msg_queue *)ipcp;
131 
132         return container_of(ipcp, struct msg_queue, q_perm);
133 }
134 
135 static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns,
136                                                 int id)
137 {
138         struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id);
139 
140         if (IS_ERR(ipcp))
141                 return (struct msg_queue *)ipcp;
142 
143         return container_of(ipcp, struct msg_queue, q_perm);
144 }
145 
146 static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
147 {
148         ipc_rmid(&msg_ids(ns), &s->q_perm);
149 }
150 
151 /**
152  * newque - Create a new msg queue
153  * @ns: namespace
154  * @params: ptr to the structure that contains the key and msgflg
155  *
156  * Called with msg_ids.rw_mutex held (writer)
157  */
158 static int newque(struct ipc_namespace *ns, struct ipc_params *params)
159 {
160         struct msg_queue *msq;
161         int id, retval;
162         key_t key = params->key;
163         int msgflg = params->flg;
164 
165         msq = ipc_rcu_alloc(sizeof(*msq));
166         if (!msq)
167                 return -ENOMEM;
168 
169         msq->q_perm.mode = msgflg & S_IRWXUGO;
170         msq->q_perm.key = key;
171 
172         msq->q_perm.security = NULL;
173         retval = security_msg_queue_alloc(msq);
174         if (retval) {
175                 ipc_rcu_putref(msq);
176                 return retval;
177         }
178 
179         /*
180          * ipc_addid() locks msq
181          */
182         id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
183         if (id < 0) {
184                 security_msg_queue_free(msq);
185                 ipc_rcu_putref(msq);
186                 return id;
187         }
188 
189         msq->q_perm.id = msg_buildid(id, msq->q_perm.seq);
190         msq->q_stime = msq->q_rtime = 0;
191         msq->q_ctime = get_seconds();
192         msq->q_cbytes = msq->q_qnum = 0;
193         msq->q_qbytes = ns->msg_ctlmnb;
194         msq->q_lspid = msq->q_lrpid = 0;
195         INIT_LIST_HEAD(&msq->q_messages);
196         INIT_LIST_HEAD(&msq->q_receivers);
197         INIT_LIST_HEAD(&msq->q_senders);
198 
199         msg_unlock(msq);
200 
201         return msq->q_perm.id;
202 }
203 
204 static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
205 {
206         mss->tsk = current;
207         current->state = TASK_INTERRUPTIBLE;
208         list_add_tail(&mss->list, &msq->q_senders);
209 }
210 
211 static inline void ss_del(struct msg_sender *mss)
212 {
213         if (mss->list.next != NULL)
214                 list_del(&mss->list);
215 }
216 
217 static void ss_wakeup(struct list_head *h, int kill)
218 {
219         struct list_head *tmp;
220 
221         tmp = h->next;
222         while (tmp != h) {
223                 struct msg_sender *mss;
224 
225                 mss = list_entry(tmp, struct msg_sender, list);
226                 tmp = tmp->next;
227                 if (kill)
228                         mss->list.next = NULL;
229                 wake_up_process(mss->tsk);
230         }
231 }
232 
233 static void expunge_all(struct msg_queue *msq, int res)
234 {
235         struct list_head *tmp;
236 
237         tmp = msq->q_receivers.next;
238         while (tmp != &msq->q_receivers) {
239                 struct msg_receiver *msr;
240 
241                 /*
242                  * Make sure that the wakeup doesnt preempt
243                  * this CPU prematurely. (on PREEMPT_RT)
244                  */
245                 preempt_disable();
246 
247                 msr = list_entry(tmp, struct msg_receiver, r_list);
248                 tmp = tmp->next;
249                 msr->r_msg = NULL;
250                 wake_up_process(msr->r_tsk); /* serializes */
251                 msr->r_msg = ERR_PTR(res);
252 
253                 preempt_enable();
254         }
255 }
256 
257 /*
258  * freeque() wakes up waiters on the sender and receiver waiting queue,
259  * removes the message queue from message queue ID IDR, and cleans up all the
260  * messages associated with this queue.
261  *
262  * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held
263  * before freeque() is called. msg_ids.rw_mutex remains locked on exit.
264  */
265 static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
266 {
267         struct list_head *tmp;
268         struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
269 
270         expunge_all(msq, -EIDRM);
271         ss_wakeup(&msq->q_senders, 1);
272         msg_rmid(ns, msq);
273         msg_unlock(msq);
274 
275         tmp = msq->q_messages.next;
276         while (tmp != &msq->q_messages) {
277                 struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list);
278 
279                 tmp = tmp->next;
280                 atomic_dec(&ns->msg_hdrs);
281                 free_msg(msg);
282         }
283         atomic_sub(msq->q_cbytes, &ns->msg_bytes);
284         security_msg_queue_free(msq);
285         ipc_rcu_putref(msq);
286 }
287 
288 /*
289  * Called with msg_ids.rw_mutex and ipcp locked.
290  */
291 static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
292 {
293         struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
294 
295         return security_msg_queue_associate(msq, msgflg);
296 }
297 
298 asmlinkage long sys_msgget(key_t key, int msgflg)
299 {
300         struct ipc_namespace *ns;
301         struct ipc_ops msg_ops;
302         struct ipc_params msg_params;
303 
304         ns = current->nsproxy->ipc_ns;
305 
306         msg_ops.getnew = newque;
307         msg_ops.associate = msg_security;
308         msg_ops.more_checks = NULL;
309 
310         msg_params.key = key;
311         msg_params.flg = msgflg;
312 
313         return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
314 }
315 
316 static inline unsigned long
317 copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
318 {
319         switch(version) {
320         case IPC_64:
321                 return copy_to_user(buf, in, sizeof(*in));
322         case IPC_OLD:
323         {
324                 struct msqid_ds out;
325 
326                 memset(&out, 0, sizeof(out));
327 
328                 ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm);
329 
330                 out.msg_stime           = in->msg_stime;
331                 out.msg_rtime           = in->msg_rtime;
332                 out.msg_ctime           = in->msg_ctime;
333 
334                 if (in->msg_cbytes > USHRT_MAX)
335                         out.msg_cbytes  = USHRT_MAX;
336                 else
337                         out.msg_cbytes  = in->msg_cbytes;
338                 out.msg_lcbytes         = in->msg_cbytes;
339 
340                 if (in->msg_qnum > USHRT_MAX)
341                         out.msg_qnum    = USHRT_MAX;
342                 else
343                         out.msg_qnum    = in->msg_qnum;
344 
345                 if (in->msg_qbytes > USHRT_MAX)
346                         out.msg_qbytes  = USHRT_MAX;
347                 else
348                         out.msg_qbytes  = in->msg_qbytes;
349                 out.msg_lqbytes         = in->msg_qbytes;
350 
351                 out.msg_lspid           = in->msg_lspid;
352                 out.msg_lrpid           = in->msg_lrpid;
353 
354                 return copy_to_user(buf, &out, sizeof(out));
355         }
356         default:
357                 return -EINVAL;
358         }
359 }
360 
361 struct msq_setbuf {
362         unsigned long   qbytes;
363         uid_t           uid;
364         gid_t           gid;
365         mode_t          mode;
366 };
367 
368 static inline unsigned long
369 copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
370 {
371         switch(version) {
372         case IPC_64:
373         {
374                 struct msqid64_ds tbuf;
375 
376                 if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
377                         return -EFAULT;
378 
379                 out->qbytes             = tbuf.msg_qbytes;
380                 out->uid                = tbuf.msg_perm.uid;
381                 out->gid                = tbuf.msg_perm.gid;
382                 out->mode               = tbuf.msg_perm.mode;
383 
384                 return 0;
385         }
386         case IPC_OLD:
387         {
388                 struct msqid_ds tbuf_old;
389 
390                 if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
391                         return -EFAULT;
392 
393                 out->uid                = tbuf_old.msg_perm.uid;
394                 out->gid                = tbuf_old.msg_perm.gid;
395                 out->mode               = tbuf_old.msg_perm.mode;
396 
397                 if (tbuf_old.msg_qbytes == 0)
398                         out->qbytes     = tbuf_old.msg_lqbytes;
399                 else
400                         out->qbytes     = tbuf_old.msg_qbytes;
401 
402                 return 0;
403         }
404         default:
405                 return -EINVAL;
406         }
407 }
408 
409 asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
410 {
411         struct kern_ipc_perm *ipcp;
412         struct msq_setbuf uninitialized_var(setbuf);
413         struct msg_queue *msq;
414         int err, version;
415         struct ipc_namespace *ns;
416 
417         if (msqid < 0 || cmd < 0)
418                 return -EINVAL;
419 
420         version = ipc_parse_version(&cmd);
421         ns = current->nsproxy->ipc_ns;
422 
423         switch (cmd) {
424         case IPC_INFO:
425         case MSG_INFO:
426         {
427                 struct msginfo msginfo;
428                 int max_id;
429 
430                 if (!buf)
431                         return -EFAULT;
432                 /*
433                  * We must not return kernel stack data.
434                  * due to padding, it's not enough
435                  * to set all member fields.
436                  */
437                 err = security_msg_queue_msgctl(NULL, cmd);
438                 if (err)
439                         return err;
440 
441                 memset(&msginfo, 0, sizeof(msginfo));
442                 msginfo.msgmni = ns->msg_ctlmni;
443                 msginfo.msgmax = ns->msg_ctlmax;
444                 msginfo.msgmnb = ns->msg_ctlmnb;
445                 msginfo.msgssz = MSGSSZ;
446                 msginfo.msgseg = MSGSEG;
447                 down_read(&msg_ids(ns).rw_mutex);
448                 if (cmd == MSG_INFO) {
449                         msginfo.msgpool = msg_ids(ns).in_use;
450                         msginfo.msgmap = atomic_read(&ns->msg_hdrs);
451                         msginfo.msgtql = atomic_read(&ns->msg_bytes);
452                 } else {
453                         msginfo.msgmap = MSGMAP;
454                         msginfo.msgpool = MSGPOOL;
455                         msginfo.msgtql = MSGTQL;
456                 }
457                 max_id = ipc_get_maxid(&msg_ids(ns));
458                 up_read(&msg_ids(ns).rw_mutex);
459                 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
460                         return -EFAULT;
461                 return (max_id < 0) ? 0 : max_id;
462         }
463         case MSG_STAT:  /* msqid is an index rather than a msg queue id */
464         case IPC_STAT:
465         {
466                 struct msqid64_ds tbuf;
467                 int success_return;
468 
469                 if (!buf)
470                         return -EFAULT;
471 
472                 if (cmd == MSG_STAT) {
473                         msq = msg_lock(ns, msqid);
474                         if (IS_ERR(msq))
475                                 return PTR_ERR(msq);
476                         success_return = msq->q_perm.id;
477                 } else {
478                         msq = msg_lock_check(ns, msqid);
479                         if (IS_ERR(msq))
480                                 return PTR_ERR(msq);
481                         success_return = 0;
482                 }
483                 err = -EACCES;
484                 if (ipcperms(&msq->q_perm, S_IRUGO))
485                         goto out_unlock;
486 
487                 err = security_msg_queue_msgctl(msq, cmd);
488                 if (err)
489                         goto out_unlock;
490 
491                 memset(&tbuf, 0, sizeof(tbuf));
492 
493                 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
494                 tbuf.msg_stime  = msq->q_stime;
495                 tbuf.msg_rtime  = msq->q_rtime;
496                 tbuf.msg_ctime  = msq->q_ctime;
497                 tbuf.msg_cbytes = msq->q_cbytes;
498                 tbuf.msg_qnum   = msq->q_qnum;
499                 tbuf.msg_qbytes = msq->q_qbytes;
500                 tbuf.msg_lspid  = msq->q_lspid;
501                 tbuf.msg_lrpid  = msq->q_lrpid;
502                 msg_unlock(msq);
503                 if (copy_msqid_to_user(buf, &tbuf, version))
504                         return -EFAULT;
505                 return success_return;
506         }
507         case IPC_SET:
508                 if (!buf)
509                         return -EFAULT;
510                 if (copy_msqid_from_user(&setbuf, buf, version))
511                         return -EFAULT;
512                 break;
513         case IPC_RMID:
514                 break;
515         default:
516                 return  -EINVAL;
517         }
518 
519         down_write(&msg_ids(ns).rw_mutex);
520         msq = msg_lock_check_down(ns, msqid);
521         if (IS_ERR(msq)) {
522                 err = PTR_ERR(msq);
523                 goto out_up;
524         }
525 
526         ipcp = &msq->q_perm;
527 
528         err = audit_ipc_obj(ipcp);
529         if (err)
530                 goto out_unlock_up;
531         if (cmd == IPC_SET) {
532                 err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
533                                          setbuf.mode);
534                 if (err)
535                         goto out_unlock_up;
536         }
537 
538         err = -EPERM;
539         if (current->euid != ipcp->cuid &&
540             current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
541                 /* We _could_ check for CAP_CHOWN above, but we don't */
542                 goto out_unlock_up;
543 
544         err = security_msg_queue_msgctl(msq, cmd);
545         if (err)
546                 goto out_unlock_up;
547 
548         switch (cmd) {
549         case IPC_SET:
550         {
551                 err = -EPERM;
552                 if (setbuf.qbytes > ns->msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
553                         goto out_unlock_up;
554 
555                 msq->q_qbytes = setbuf.qbytes;
556 
557                 ipcp->uid = setbuf.uid;
558                 ipcp->gid = setbuf.gid;
559                 ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
560                              (S_IRWXUGO & setbuf.mode);
561                 msq->q_ctime = get_seconds();
562                 /* sleeping receivers might be excluded by
563                  * stricter permissions.
564                  */
565                 expunge_all(msq, -EAGAIN);
566                 /* sleeping senders might be able to send
567                  * due to a larger queue size.
568                  */
569                 ss_wakeup(&msq->q_senders, 0);
570                 msg_unlock(msq);
571                 break;
572         }
573         case IPC_RMID:
574                 freeque(ns, &msq->q_perm);
575                 break;
576         }
577         err = 0;
578 out_up:
579         up_write(&msg_ids(ns).rw_mutex);
580         return err;
581 out_unlock_up:
582         msg_unlock(msq);
583         goto out_up;
584 out_unlock:
585         msg_unlock(msq);
586         return err;
587 }
588 
589 static int testmsg(struct msg_msg *msg, long type, int mode)
590 {
591         switch(mode)
592         {
593                 case SEARCH_ANY:
594                         return 1;
595                 case SEARCH_LESSEQUAL:
596                         if (msg->m_type <=type)
597                                 return 1;
598                         break;
599                 case SEARCH_EQUAL:
600                         if (msg->m_type == type)
601                                 return 1;
602                         break;
603                 case SEARCH_NOTEQUAL:
604                         if (msg->m_type != type)
605                                 return 1;
606                         break;
607         }
608         return 0;
609 }
610 
611 static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
612 {
613         struct list_head *tmp;
614 
615         tmp = msq->q_receivers.next;
616         while (tmp != &msq->q_receivers) {
617                 struct msg_receiver *msr;
618 
619                 msr = list_entry(tmp, struct msg_receiver, r_list);
620                 tmp = tmp->next;
621                 if (testmsg(msg, msr->r_msgtype, msr->r_mode) &&
622                     !security_msg_queue_msgrcv(msq, msg, msr->r_tsk,
623                                                msr->r_msgtype, msr->r_mode)) {
624 
625                         /*
626                          * Make sure that the wakeup doesnt preempt
627                          * this CPU prematurely. (on PREEMPT_RT)
628                          */
629                         preempt_disable();
630 
631                         list_del(&msr->r_list);
632                         if (msr->r_maxsize < msg->m_ts) {
633                                 msr->r_msg = NULL;
634                                 wake_up_process(msr->r_tsk); /* serializes */
635                                 msr->r_msg = ERR_PTR(-E2BIG);
636                         } else {
637                                 msr->r_msg = NULL;
638                                 msq->q_lrpid = task_pid_vnr(msr->r_tsk);
639                                 msq->q_rtime = get_seconds();
640                                 wake_up_process(msr->r_tsk); /* serializes */
641                                 msr->r_msg = msg;
642                                 preempt_enable();
643 
644                                 return 1;
645                         }
646                         preempt_enable();
647                 }
648         }
649         return 0;
650 }
651 
652 long do_msgsnd(int msqid, long mtype, void __user *mtext,
653                 size_t msgsz, int msgflg)
654 {
655         struct msg_queue *msq;
656         struct msg_msg *msg;
657         int err;
658         struct ipc_namespace *ns;
659 
660         ns = current->nsproxy->ipc_ns;
661 
662         if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
663                 return -EINVAL;
664         if (mtype < 1)
665                 return -EINVAL;
666 
667         msg = load_msg(mtext, msgsz);
668         if (IS_ERR(msg))
669                 return PTR_ERR(msg);
670 
671         msg->m_type = mtype;
672         msg->m_ts = msgsz;
673 
674         msq = msg_lock_check(ns, msqid);
675         if (IS_ERR(msq)) {
676                 err = PTR_ERR(msq);
677                 goto out_free;
678         }
679 
680         for (;;) {
681                 struct msg_sender s;
682 
683                 err = -EACCES;
684                 if (ipcperms(&msq->q_perm, S_IWUGO))
685                         goto out_unlock_free;
686 
687                 err = security_msg_queue_msgsnd(msq, msg, msgflg);
688                 if (err)
689                         goto out_unlock_free;
690 
691                 if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
692                                 1 + msq->q_qnum <= msq->q_qbytes) {
693                         break;
694                 }
695 
696                 /* queue full, wait: */
697                 if (msgflg & IPC_NOWAIT) {
698                         err = -EAGAIN;
699                         goto out_unlock_free;
700                 }
701                 ss_add(msq, &s);
702                 ipc_rcu_getref(msq);
703                 msg_unlock(msq);
704                 schedule();
705 
706                 ipc_lock_by_ptr(&msq->q_perm);
707                 ipc_rcu_putref(msq);
708                 if (msq->q_perm.deleted) {
709                         err = -EIDRM;
710                         goto out_unlock_free;
711                 }
712                 ss_del(&s);
713 
714                 if (signal_pending(current)) {
715                         err = -ERESTARTNOHAND;
716                         goto out_unlock_free;
717                 }
718         }
719 
720         msq->q_lspid = task_tgid_vnr(current);
721         msq->q_stime = get_seconds();
722 
723         if (!pipelined_send(msq, msg)) {
724                 /* noone is waiting for this message, enqueue it */
725                 list_add_tail(&msg->m_list, &msq->q_messages);
726                 msq->q_cbytes += msgsz;
727                 msq->q_qnum++;
728                 atomic_add(msgsz, &ns->msg_bytes);
729                 atomic_inc(&ns->msg_hdrs);
730         }
731 
732         err = 0;
733         msg = NULL;
734 
735 out_unlock_free:
736         msg_unlock(msq);
737 out_free:
738         if (msg != NULL)
739                 free_msg(msg);
740         return err;
741 }
742 
743 asmlinkage long
744 sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
745 {
746         long mtype;
747 
748         if (get_user(mtype, &msgp->mtype))
749                 return -EFAULT;
750         return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
751 }
752 
753 static inline int convert_mode(long *msgtyp, int msgflg)
754 {
755         /*
756          *  find message of correct type.
757          *  msgtyp = 0 => get first.
758          *  msgtyp > 0 => get first message of matching type.
759          *  msgtyp < 0 => get message with least type must be < abs(msgtype).
760          */
761         if (*msgtyp == 0)
762                 return SEARCH_ANY;
763         if (*msgtyp < 0) {
764                 *msgtyp = -*msgtyp;
765                 return SEARCH_LESSEQUAL;
766         }
767         if (msgflg & MSG_EXCEPT)
768                 return SEARCH_NOTEQUAL;
769         return SEARCH_EQUAL;
770 }
771 
772 long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
773                 size_t msgsz, long msgtyp, int msgflg)
774 {
775         struct msg_queue *msq;
776         struct msg_msg *msg;
777         int mode;
778         struct ipc_namespace *ns;
779 
780         if (msqid < 0 || (long) msgsz < 0)
781                 return -EINVAL;
782         mode = convert_mode(&msgtyp, msgflg);
783         ns = current->nsproxy->ipc_ns;
784 
785         msq = msg_lock_check(ns, msqid);
786         if (IS_ERR(msq))
787                 return PTR_ERR(msq);
788 
789         for (;;) {
790                 struct msg_receiver msr_d;
791                 struct list_head *tmp;
792 
793                 msg = ERR_PTR(-EACCES);
794                 if (ipcperms(&msq->q_perm, S_IRUGO))
795                         goto out_unlock;
796 
797                 msg = ERR_PTR(-EAGAIN);
798                 tmp = msq->q_messages.next;
799                 while (tmp != &msq->q_messages) {
800                         struct msg_msg *walk_msg;
801 
802                         walk_msg = list_entry(tmp, struct msg_msg, m_list);
803                         if (testmsg(walk_msg, msgtyp, mode) &&
804                             !security_msg_queue_msgrcv(msq, walk_msg, current,
805                                                        msgtyp, mode)) {
806 
807                                 msg = walk_msg;
808                                 if (mode == SEARCH_LESSEQUAL &&
809                                                 walk_msg->m_type != 1) {
810                                         msg = walk_msg;
811                                         msgtyp = walk_msg->m_type - 1;
812                                 } else {
813                                         msg = walk_msg;
814                                         break;
815                                 }
816                         }
817                         tmp = tmp->next;
818                 }
819                 if (!IS_ERR(msg)) {
820                         /*
821                          * Found a suitable message.
822                          * Unlink it from the queue.
823                          */
824                         if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
825                                 msg = ERR_PTR(-E2BIG);
826                                 goto out_unlock;
827                         }
828                         list_del(&msg->m_list);
829                         msq->q_qnum--;
830                         msq->q_rtime = get_seconds();
831                         msq->q_lrpid = task_tgid_vnr(current);
832                         msq->q_cbytes -= msg->m_ts;
833                         atomic_sub(msg->m_ts, &ns->msg_bytes);
834                         atomic_dec(&ns->msg_hdrs);
835                         ss_wakeup(&msq->q_senders, 0);
836                         msg_unlock(msq);
837                         break;
838                 }
839                 /* No message waiting. Wait for a message */
840                 if (msgflg & IPC_NOWAIT) {
841                         msg = ERR_PTR(-ENOMSG);
842                         goto out_unlock;
843                 }
844                 list_add_tail(&msr_d.r_list, &msq->q_receivers);
845                 msr_d.r_tsk = current;
846                 msr_d.r_msgtype = msgtyp;
847                 msr_d.r_mode = mode;
848                 if (msgflg & MSG_NOERROR)
849                         msr_d.r_maxsize = INT_MAX;
850                 else
851                         msr_d.r_maxsize = msgsz;
852                 msr_d.r_msg = ERR_PTR(-EAGAIN);
853                 current->state = TASK_INTERRUPTIBLE;
854                 msg_unlock(msq);
855 
856                 schedule();
857 
858                 /* Lockless receive, part 1:
859                  * Disable preemption.  We don't hold a reference to the queue
860                  * and getting a reference would defeat the idea of a lockless
861                  * operation, thus the code relies on rcu to guarantee the
862                  * existance of msq:
863                  * Prior to destruction, expunge_all(-EIRDM) changes r_msg.
864                  * Thus if r_msg is -EAGAIN, then the queue not yet destroyed.
865                  * rcu_read_lock() prevents preemption between reading r_msg
866                  * and the spin_lock() inside ipc_lock_by_ptr().
867                  */
868                 rcu_read_lock();
869 
870                 /* Lockless receive, part 2:
871                  * Wait until pipelined_send or expunge_all are outside of
872                  * wake_up_process(). There is a race with exit(), see
873                  * ipc/mqueue.c for the details.
874                  */
875                 msg = (struct msg_msg*)msr_d.r_msg;
876                 while (msg == NULL) {
877                         cpu_relax();
878                         msg = (struct msg_msg *)msr_d.r_msg;
879                 }
880 
881                 /* Lockless receive, part 3:
882                  * If there is a message or an error then accept it without
883                  * locking.
884                  */
885                 if (msg != ERR_PTR(-EAGAIN)) {
886                         rcu_read_unlock();
887                         break;
888                 }
889 
890                 /* Lockless receive, part 3:
891                  * Acquire the queue spinlock.
892                  */
893                 ipc_lock_by_ptr(&msq->q_perm);
894                 rcu_read_unlock();
895 
896                 /* Lockless receive, part 4:
897                  * Repeat test after acquiring the spinlock.
898                  */
899                 msg = (struct msg_msg*)msr_d.r_msg;
900                 if (msg != ERR_PTR(-EAGAIN))
901                         goto out_unlock;
902 
903                 list_del(&msr_d.r_list);
904                 if (signal_pending(current)) {
905                         msg = ERR_PTR(-ERESTARTNOHAND);
906 out_unlock:
907                         msg_unlock(msq);
908                         break;
909                 }
910         }
911         if (IS_ERR(msg))
912                 return PTR_ERR(msg);
913 
914         msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
915         *pmtype = msg->m_type;
916         if (store_msg(mtext, msg, msgsz))
917                 msgsz = -EFAULT;
918 
919         free_msg(msg);
920 
921         return msgsz;
922 }
923 
924 asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
925                            long msgtyp, int msgflg)
926 {
927         long err, mtype;
928 
929         err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
930         if (err < 0)
931                 goto out;
932 
933         if (put_user(mtype, &msgp->mtype))
934                 err = -EFAULT;
935 out:
936         return err;
937 }
938 
939 #ifdef CONFIG_PROC_FS
940 static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
941 {
942         struct msg_queue *msq = it;
943 
944         return seq_printf(s,
945                         "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
946                         msq->q_perm.key,
947                         msq->q_perm.id,
948                         msq->q_perm.mode,
949                         msq->q_cbytes,
950                         msq->q_qnum,
951                         msq->q_lspid,
952                         msq->q_lrpid,
953                         msq->q_perm.uid,
954                         msq->q_perm.gid,
955                         msq->q_perm.cuid,
956                         msq->q_perm.cgid,
957                         msq->q_stime,
958                         msq->q_rtime,
959                         msq->q_ctime);
960 }
961 #endif
962 
  This page was automatically generated by the LXR engine.