| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: sys_mqueue.c,v 1.12.4.3 2009/05/27 21:32:05 snj Exp $ */ | | 1 | /* $NetBSD: sys_mqueue.c,v 1.12.4.4 2009/07/21 00:23:01 snj Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2007, 2008 Mindaugas Rasiukevicius <rmind at NetBSD org> | | 4 | * Copyright (c) 2007, 2008 Mindaugas Rasiukevicius <rmind at NetBSD org> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -32,27 +32,27 @@ | | | @@ -32,27 +32,27 @@ |
32 | * | | 32 | * |
33 | * Locking | | 33 | * Locking |
34 | * | | 34 | * |
35 | * Global list of message queues (mqueue_head) and proc_t::p_mqueue_cnt | | 35 | * Global list of message queues (mqueue_head) and proc_t::p_mqueue_cnt |
36 | * counter are protected by mqlist_mtx lock. The very message queue and | | 36 | * counter are protected by mqlist_mtx lock. The very message queue and |
37 | * its members are protected by mqueue::mq_mtx. | | 37 | * its members are protected by mqueue::mq_mtx. |
38 | * | | 38 | * |
39 | * Lock order: | | 39 | * Lock order: |
40 | * mqlist_mtx | | 40 | * mqlist_mtx |
41 | * -> mqueue::mq_mtx | | 41 | * -> mqueue::mq_mtx |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/cdefs.h> | | 44 | #include <sys/cdefs.h> |
45 | __KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12.4.3 2009/05/27 21:32:05 snj Exp $"); | | 45 | __KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12.4.4 2009/07/21 00:23:01 snj Exp $"); |
46 | | | 46 | |
47 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
48 | #include <sys/types.h> | | 48 | #include <sys/types.h> |
49 | #include <sys/condvar.h> | | 49 | #include <sys/condvar.h> |
50 | #include <sys/errno.h> | | 50 | #include <sys/errno.h> |
51 | #include <sys/fcntl.h> | | 51 | #include <sys/fcntl.h> |
52 | #include <sys/file.h> | | 52 | #include <sys/file.h> |
53 | #include <sys/filedesc.h> | | 53 | #include <sys/filedesc.h> |
54 | #include <sys/kauth.h> | | 54 | #include <sys/kauth.h> |
55 | #include <sys/kernel.h> | | 55 | #include <sys/kernel.h> |
56 | #include <sys/kmem.h> | | 56 | #include <sys/kmem.h> |
57 | #include <sys/lwp.h> | | 57 | #include <sys/lwp.h> |
58 | #include <sys/mqueue.h> | | 58 | #include <sys/mqueue.h> |
| @@ -472,29 +472,34 @@ sys_mq_close(struct lwp *l, const struct | | | @@ -472,29 +472,34 @@ sys_mq_close(struct lwp *l, const struct |
472 | * Primary mq_receive1() function. | | 472 | * Primary mq_receive1() function. |
473 | */ | | 473 | */ |
474 | static int | | 474 | static int |
475 | mq_receive1(struct lwp *l, mqd_t mqdes, void *msg_ptr, size_t msg_len, | | 475 | mq_receive1(struct lwp *l, mqd_t mqdes, void *msg_ptr, size_t msg_len, |
476 | unsigned *msg_prio, int t, ssize_t *mlen) | | 476 | unsigned *msg_prio, int t, ssize_t *mlen) |
477 | { | | 477 | { |
478 | file_t *fp = NULL; | | 478 | file_t *fp = NULL; |
479 | struct mqueue *mq; | | 479 | struct mqueue *mq; |
480 | struct mq_msg *msg = NULL; | | 480 | struct mq_msg *msg = NULL; |
481 | int error; | | 481 | int error; |
482 | | | 482 | |
483 | /* Get the message queue */ | | 483 | /* Get the message queue */ |
484 | error = mqueue_get(mqdes, &fp); | | 484 | error = mqueue_get(mqdes, &fp); |
485 | if (error) | | 485 | if (error) { |
486 | return error; | | 486 | return error; |
| | | 487 | } |
487 | mq = fp->f_data; | | 488 | mq = fp->f_data; |
| | | 489 | if ((fp->f_flag & FREAD) == 0) { |
| | | 490 | error = EBADF; |
| | | 491 | goto error; |
| | | 492 | } |
488 | | | 493 | |
489 | /* Check the message size limits */ | | 494 | /* Check the message size limits */ |
490 | if (msg_len < mq->mq_attrib.mq_msgsize) { | | 495 | if (msg_len < mq->mq_attrib.mq_msgsize) { |
491 | error = EMSGSIZE; | | 496 | error = EMSGSIZE; |
492 | goto error; | | 497 | goto error; |
493 | } | | 498 | } |
494 | | | 499 | |
495 | /* Check if queue is empty */ | | 500 | /* Check if queue is empty */ |
496 | while (TAILQ_EMPTY(&mq->mq_head)) { | | 501 | while (TAILQ_EMPTY(&mq->mq_head)) { |
497 | if (mq->mq_attrib.mq_flags & O_NONBLOCK) { | | 502 | if (mq->mq_attrib.mq_flags & O_NONBLOCK) { |
498 | error = EAGAIN; | | 503 | error = EAGAIN; |
499 | goto error; | | 504 | goto error; |
500 | } | | 505 | } |
| @@ -632,26 +637,30 @@ mq_send1(struct lwp *l, mqd_t mqdes, con | | | @@ -632,26 +637,30 @@ mq_send1(struct lwp *l, mqd_t mqdes, con |
632 | mqueue_freemsg(msg, size); | | 637 | mqueue_freemsg(msg, size); |
633 | return error; | | 638 | return error; |
634 | } | | 639 | } |
635 | msg->msg_len = msg_len; | | 640 | msg->msg_len = msg_len; |
636 | msg->msg_prio = msg_prio; | | 641 | msg->msg_prio = msg_prio; |
637 | | | 642 | |
638 | /* Get the mqueue */ | | 643 | /* Get the mqueue */ |
639 | error = mqueue_get(mqdes, &fp); | | 644 | error = mqueue_get(mqdes, &fp); |
640 | if (error) { | | 645 | if (error) { |
641 | mqueue_freemsg(msg, size); | | 646 | mqueue_freemsg(msg, size); |
642 | return error; | | 647 | return error; |
643 | } | | 648 | } |
644 | mq = fp->f_data; | | 649 | mq = fp->f_data; |
| | | 650 | if ((fp->f_flag & FWRITE) == 0) { |
| | | 651 | error = EBADF; |
| | | 652 | goto error; |
| | | 653 | } |
645 | | | 654 | |
646 | /* Check the message size limit */ | | 655 | /* Check the message size limit */ |
647 | if (msg_len <= 0 || msg_len > mq->mq_attrib.mq_msgsize) { | | 656 | if (msg_len <= 0 || msg_len > mq->mq_attrib.mq_msgsize) { |
648 | error = EMSGSIZE; | | 657 | error = EMSGSIZE; |
649 | goto error; | | 658 | goto error; |
650 | } | | 659 | } |
651 | | | 660 | |
652 | /* Check if queue is full */ | | 661 | /* Check if queue is full */ |
653 | while (mq->mq_attrib.mq_curmsgs >= mq->mq_attrib.mq_maxmsg) { | | 662 | while (mq->mq_attrib.mq_curmsgs >= mq->mq_attrib.mq_maxmsg) { |
654 | if (mq->mq_attrib.mq_flags & O_NONBLOCK) { | | 663 | if (mq->mq_attrib.mq_flags & O_NONBLOCK) { |
655 | error = EAGAIN; | | 664 | error = EAGAIN; |
656 | goto error; | | 665 | goto error; |
657 | } | | 666 | } |