summaryrefslogtreecommitdiff
path: root/sys/kern/sys_mqueue.c
diff options
context:
space:
mode:
authorrmind <rmind@NetBSD.org>2008-09-29 10:27:53 +0000
committerrmind <rmind@NetBSD.org>2008-09-29 10:27:53 +0000
commit03fe669395538c50bc865a6e8fc7ebb53ff77bd2 (patch)
treeda0426f02e30df383fd44b9f36216c9c496b7c57 /sys/kern/sys_mqueue.c
parent844fcfc979eb95968668309dac39e3caf3e08839 (diff)
- Fix message queue permissions problems.
- Rake into account umask when creating mqueue. - Restore DDB command, which was accidentally lost (hi martin). - Misc.
Diffstat (limited to 'sys/kern/sys_mqueue.c')
-rw-r--r--sys/kern/sys_mqueue.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/sys/kern/sys_mqueue.c b/sys/kern/sys_mqueue.c
index b2a75c63814..f14f090702d 100644
--- a/sys/kern/sys_mqueue.c
+++ b/sys/kern/sys_mqueue.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_mqueue.c,v 1.11 2008/07/02 20:06:09 rmind Exp $ */
+/* $NetBSD: sys_mqueue.c,v 1.12 2008/09/29 10:27:53 rmind Exp $ */
/*
* Copyright (c) 2007, 2008 Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -29,11 +29,12 @@
/*
* Implementation of POSIX message queues.
* Defined in the Base Definitions volume of IEEE Std 1003.1-2001.
- *
+ *
* Locking
- * Global list of message queues and proc::p_mqueue_cnt counter are protected
- * by mqlist_mtx lock. Concrete message queue and its members are protected
- * by mqueue::mq_mtx.
+ *
+ * Global list of message queues (mqueue_head) and proc_t::p_mqueue_cnt
+ * counter are protected by mqlist_mtx lock. The very message queue and
+ * its members are protected by mqueue::mq_mtx.
*
* Lock order:
* mqlist_mtx
@@ -41,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.11 2008/07/02 20:06:09 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12 2008/09/29 10:27:53 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -63,6 +64,7 @@ __KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.11 2008/07/02 20:06:09 rmind Exp $"
#include <sys/select.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
+#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/syscallargs.h>
#include <sys/systm.h>
@@ -84,6 +86,8 @@ static LIST_HEAD(, mqueue) mqueue_head =
static int mq_poll_fop(file_t *, int);
static int mq_close_fop(file_t *);
+#define FNOVAL -1
+
static const struct fileops mqops = {
fbadop_read, fbadop_write, fbadop_ioctl, fnullop_fcntl, mq_poll_fop,
fbadop_stat, mq_close_fop, fnullop_kqfilter
@@ -97,7 +101,7 @@ mqueue_sysinit(void)
{
mqmsg_cache = pool_cache_init(MQ_DEF_MSGSIZE, coherency_unit,
- 0, 0, "mqmsg_cache", NULL, IPL_NONE, NULL, NULL, NULL);
+ 0, 0, "mqmsgpl", NULL, IPL_NONE, NULL, NULL, NULL);
mutex_init(&mqlist_mtx, MUTEX_DEFAULT, IPL_NONE);
}
@@ -158,21 +162,30 @@ mqueue_lookup(char *name)
* Check access against message queue.
*/
static inline int
-mqueue_access(struct lwp *l, struct mqueue *mq, mode_t acc_mode)
+mqueue_access(struct lwp *l, struct mqueue *mq, int access)
{
+ mode_t acc_mode = 0;
KASSERT(mutex_owned(&mq->mq_mtx));
+ KASSERT(access != FNOVAL);
+
+ /* Note the difference between VREAD/VWRITE and FREAD/FWRITE */
+ if (access & FREAD)
+ acc_mode |= VREAD;
+ if (access & FWRITE)
+ acc_mode |= VWRITE;
+
return vaccess(VNON, mq->mq_mode, mq->mq_euid, mq->mq_egid,
acc_mode, l->l_cred);
}
/*
* Get the mqueue from the descriptor.
- * => locks the message queue
+ * => locks the message queue, if found
* => increments the reference on file entry
*/
static int
-mqueue_get(struct lwp *l, mqd_t mqd, mode_t acc_mode, file_t **fpr)
+mqueue_get(struct lwp *l, mqd_t mqd, int access, file_t **fpr)
{
file_t *fp;
struct mqueue *mq;
@@ -186,16 +199,17 @@ mqueue_get(struct lwp *l, mqd_t mqd, mode_t acc_mode, file_t **fpr)
mq = fp->f_data;
*fpr = fp;
mutex_enter(&mq->mq_mtx);
-
- /* Check the access mode and permission if needed */
- if (acc_mode == VNOVAL)
+ if (access == FNOVAL) {
+ KASSERT(mutex_owned(&mq->mq_mtx));
return 0;
- if ((acc_mode & fp->f_flag) == 0 || mqueue_access(l, mq, acc_mode)) {
+ }
+
+ /* Check the access mode and permission */
+ if ((fp->f_flag & access) != access || mqueue_access(l, mq, access)) {
mutex_exit(&mq->mq_mtx);
fd_putfile((int)mqd);
return EPERM;
}
-
return 0;
}
@@ -308,7 +322,7 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
/* Check access mode flags */
oflag = SCARG(uap, oflag);
- if ((oflag & (O_RDWR | O_RDONLY | O_WRONLY)) == 0)
+ if ((oflag & O_ACCMODE) == 0)
return EINVAL;
/* Get the name from the user-space */
@@ -320,6 +334,7 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
}
if (oflag & O_CREAT) {
+ struct cwdinfo *cwdi = p->p_cwdi;
struct mq_attr attr;
/* Check the limit */
@@ -367,7 +382,8 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
mq_new->mq_attrib.mq_flags = oflag;
/* Store mode and effective UID with GID */
- mq_new->mq_mode = SCARG(uap, mode);
+ mq_new->mq_mode = ((SCARG(uap, mode) &
+ ~cwdi->cwdi_cmask) & ALLPERMS) & ~S_ISTXT;
mq_new->mq_euid = kauth_cred_geteuid(l->l_cred);
mq_new->mq_egid = kauth_cred_getegid(l->l_cred);
}
@@ -388,10 +404,8 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
mutex_enter(&mqlist_mtx);
mq = mqueue_lookup(name);
if (mq) {
- const int acc_mode = (oflag & O_RDWR) ? (VREAD | VWRITE) :
- ((oflag & O_RDONLY) ? VREAD : VWRITE);
-
KASSERT(mutex_owned(&mq->mq_mtx));
+
/* Check if mqueue is not marked as unlinking */
if (mq->mq_attrib.mq_flags & MQ_UNLINK) {
error = EACCES;
@@ -403,7 +417,7 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
goto exit;
}
/* Check the permission */
- if (mqueue_access(l, mq, acc_mode)) {
+ if (mqueue_access(l, mq, fp->f_flag)) {
error = EACCES;
goto exit;
}
@@ -472,7 +486,7 @@ mq_receive1(struct lwp *l, mqd_t mqdes, void *msg_ptr, size_t msg_len,
int error;
/* Get the message queue */
- error = mqueue_get(l, mqdes, VREAD, &fp);
+ error = mqueue_get(l, mqdes, FREAD, &fp);
if (error)
return error;
mq = fp->f_data;
@@ -627,7 +641,7 @@ mq_send1(struct lwp *l, mqd_t mqdes, const char *msg_ptr, size_t msg_len,
msg->msg_prio = msg_prio;
/* Get the mqueue */
- error = mqueue_get(l, mqdes, VWRITE, &fp);
+ error = mqueue_get(l, mqdes, FWRITE, &fp);
if (error) {
mqueue_freemsg(msg, size);
return error;
@@ -764,7 +778,7 @@ sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap,
return error;
}
- error = mqueue_get(l, SCARG(uap, mqdes), VNOVAL, &fp);
+ error = mqueue_get(l, SCARG(uap, mqdes), FNOVAL, &fp);
if (error)
return error;
mq = fp->f_data;
@@ -803,7 +817,7 @@ sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap,
int error;
/* Get the message queue */
- error = mqueue_get(l, SCARG(uap, mqdes), VNOVAL, &fp);
+ error = mqueue_get(l, SCARG(uap, mqdes), FNOVAL, &fp);
if (error)
return error;
mq = fp->f_data;
@@ -834,7 +848,7 @@ sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap,
nonblock = (attr.mq_flags & O_NONBLOCK);
/* Get the message queue */
- error = mqueue_get(l, SCARG(uap, mqdes), VNOVAL, &fp);
+ error = mqueue_get(l, SCARG(uap, mqdes), FNOVAL, &fp);
if (error)
return error;
mq = fp->f_data;
@@ -892,7 +906,7 @@ sys_mq_unlink(struct lwp *l, const struct sys_mq_unlink_args *uap,
}
/* Check the permissions */
- if (mqueue_access(l, mq, VWRITE)) {
+ if (mqueue_access(l, mq, FWRITE)) {
mutex_exit(&mq->mq_mtx);
error = EACCES;
goto error;