diff options
| author | rmind <rmind@NetBSD.org> | 2008-09-29 10:27:53 +0000 |
|---|---|---|
| committer | rmind <rmind@NetBSD.org> | 2008-09-29 10:27:53 +0000 |
| commit | 03fe669395538c50bc865a6e8fc7ebb53ff77bd2 (patch) | |
| tree | da0426f02e30df383fd44b9f36216c9c496b7c57 /sys/kern/sys_mqueue.c | |
| parent | 844fcfc979eb95968668309dac39e3caf3e08839 (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.c | 68 |
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; |
