Wed May 27 21:33:50 2009 UTC ()
Pull up following revision(s) (requested by rmind in ticket #779):
	sys/kern/sys_mqueue.c: revision 1.18
- Slightly rework the way permissions are checked. Neither mq_receive() not
  mq_send() should fail due to permissions.  Noted by Stathis Kamperis!
- Check for empty message queue name (POSIX does not allow this for regular
  files, and it's weird), check for DTYPE_MQUEUE, fix permission check in
  mq_unlink(), clean up.


(snj)
diff -r1.12.4.1.2.1 -r1.12.4.1.2.2 src/sys/kern/sys_mqueue.c

cvs diff -r1.12.4.1.2.1 -r1.12.4.1.2.2 src/sys/kern/sys_mqueue.c (expand / switch to unified diff)

--- src/sys/kern/sys_mqueue.c 2009/05/18 19:50:13 1.12.4.1.2.1
+++ src/sys/kern/sys_mqueue.c 2009/05/27 21:33:50 1.12.4.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sys_mqueue.c,v 1.12.4.1.2.1 2009/05/18 19:50:13 bouyer Exp $ */ 1/* $NetBSD: sys_mqueue.c,v 1.12.4.1.2.2 2009/05/27 21:33:50 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.1.2.1 2009/05/18 19:50:13 bouyer Exp $"); 45__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12.4.1.2.2 2009/05/27 21:33:50 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>
@@ -76,28 +76,26 @@ static u_int mq_open_max = MQ_OPEN_MAX @@ -76,28 +76,26 @@ static u_int mq_open_max = MQ_OPEN_MAX
76static u_int mq_prio_max = MQ_PRIO_MAX; 76static u_int mq_prio_max = MQ_PRIO_MAX;
77 77
78static u_int mq_max_msgsize = 16 * MQ_DEF_MSGSIZE; 78static u_int mq_max_msgsize = 16 * MQ_DEF_MSGSIZE;
79static u_int mq_def_maxmsg = 32; 79static u_int mq_def_maxmsg = 32;
80 80
81static kmutex_t mqlist_mtx; 81static kmutex_t mqlist_mtx;
82static pool_cache_t mqmsg_cache; 82static pool_cache_t mqmsg_cache;
83static LIST_HEAD(, mqueue) mqueue_head = 83static LIST_HEAD(, mqueue) mqueue_head =
84 LIST_HEAD_INITIALIZER(mqueue_head); 84 LIST_HEAD_INITIALIZER(mqueue_head);
85 85
86static int mq_poll_fop(file_t *, int); 86static int mq_poll_fop(file_t *, int);
87static int mq_close_fop(file_t *); 87static int mq_close_fop(file_t *);
88 88
89#define FNOVAL -1 
90 
91static const struct fileops mqops = { 89static const struct fileops mqops = {
92 .fo_read = fbadop_read, 90 .fo_read = fbadop_read,
93 .fo_write = fbadop_write, 91 .fo_write = fbadop_write,
94 .fo_ioctl = fbadop_ioctl, 92 .fo_ioctl = fbadop_ioctl,
95 .fo_fcntl = fnullop_fcntl, 93 .fo_fcntl = fnullop_fcntl,
96 .fo_poll = mq_poll_fop, 94 .fo_poll = mq_poll_fop,
97 .fo_stat = fbadop_stat, 95 .fo_stat = fbadop_stat,
98 .fo_close = mq_close_fop, 96 .fo_close = mq_close_fop,
99 .fo_kqfilter = fnullop_kqfilter, 97 .fo_kqfilter = fnullop_kqfilter,
100 .fo_drain = fnullop_drain, 98 .fo_drain = fnullop_drain,
101}; 99};
102 100
103/* 101/*
@@ -156,77 +154,48 @@ mqueue_lookup(char *name) @@ -156,77 +154,48 @@ mqueue_lookup(char *name)
156 KASSERT(mutex_owned(&mqlist_mtx)); 154 KASSERT(mutex_owned(&mqlist_mtx));
157 155
158 LIST_FOREACH(mq, &mqueue_head, mq_list) { 156 LIST_FOREACH(mq, &mqueue_head, mq_list) {
159 if (strncmp(mq->mq_name, name, MQ_NAMELEN) == 0) { 157 if (strncmp(mq->mq_name, name, MQ_NAMELEN) == 0) {
160 mutex_enter(&mq->mq_mtx); 158 mutex_enter(&mq->mq_mtx);
161 return mq; 159 return mq;
162 } 160 }
163 } 161 }
164 162
165 return NULL; 163 return NULL;
166} 164}
167 165
168/* 166/*
169 * Check access against message queue. 167 * mqueue_get: get the mqueue from the descriptor.
170 */ 168 * => locks the message queue, if found.
171static inline int 169 * => holds a reference on the file descriptor.
172mqueue_access(struct lwp *l, struct mqueue *mq, int access) 
173{ 
174 mode_t acc_mode = 0; 
175 
176 KASSERT(mutex_owned(&mq->mq_mtx)); 
177 KASSERT(access != FNOVAL); 
178 
179 /* Note the difference between VREAD/VWRITE and FREAD/FWRITE */ 
180 if (access & FREAD) 
181 acc_mode |= VREAD; 
182 if (access & FWRITE) 
183 acc_mode |= VWRITE; 
184 
185 return vaccess(VNON, mq->mq_mode, mq->mq_euid, mq->mq_egid, 
186 acc_mode, l->l_cred); 
187} 
188 
189/* 
190 * Get the mqueue from the descriptor. 
191 * => locks the message queue, if found 
192 * => increments the reference on file entry 
193 */ 170 */
194static int 171static int
195mqueue_get(struct lwp *l, mqd_t mqd, int access, file_t **fpr) 172mqueue_get(mqd_t mqd, file_t **fpr)
196{ 173{
197 file_t *fp; 
198 struct mqueue *mq; 174 struct mqueue *mq;
 175 file_t *fp;
199 176
200 /* Get the file and descriptor */ 
201 fp = fd_getfile((int)mqd); 177 fp = fd_getfile((int)mqd);
202 if (fp == NULL) 178 if (__predict_false(fp == NULL)) {
203 return EBADF; 179 return EBADF;
204 
205 /* Increment the reference of file entry, and lock the mqueue */ 
206 mq = fp->f_data; 
207 *fpr = fp; 
208 mutex_enter(&mq->mq_mtx); 
209 if (access == FNOVAL) { 
210 KASSERT(mutex_owned(&mq->mq_mtx)); 
211 return 0; 
212 } 180 }
213 181 if (__predict_false(fp->f_type != DTYPE_MQUEUE)) {
214 /* Check the access mode and permission */ 
215 if ((fp->f_flag & access) != access || mqueue_access(l, mq, access)) { 
216 mutex_exit(&mq->mq_mtx); 
217 fd_putfile((int)mqd); 182 fd_putfile((int)mqd);
218 return EPERM; 183 return EBADF;
219 } 184 }
 185 mq = fp->f_data;
 186 mutex_enter(&mq->mq_mtx);
 187
 188 *fpr = fp;
220 return 0; 189 return 0;
221} 190}
222 191
223/* 192/*
224 * Converter from struct timespec to the ticks. 193 * Converter from struct timespec to the ticks.
225 * Used by mq_timedreceive(), mq_timedsend(). 194 * Used by mq_timedreceive(), mq_timedsend().
226 */ 195 */
227static int 196static int
228abstimeout2timo(const void *uaddr, int *timo) 197abstimeout2timo(const void *uaddr, int *timo)
229{ 198{
230 struct timespec ts; 199 struct timespec ts;
231 int error; 200 int error;
232 201
@@ -337,26 +306,32 @@ sys_mq_open(struct lwp *l, const struct  @@ -337,26 +306,32 @@ sys_mq_open(struct lwp *l, const struct
337 return error; 306 return error;
338 } 307 }
339 308
340 if (oflag & O_CREAT) { 309 if (oflag & O_CREAT) {
341 struct cwdinfo *cwdi = p->p_cwdi; 310 struct cwdinfo *cwdi = p->p_cwdi;
342 struct mq_attr attr; 311 struct mq_attr attr;
343 312
344 /* Check the limit */ 313 /* Check the limit */
345 if (p->p_mqueue_cnt == mq_open_max) { 314 if (p->p_mqueue_cnt == mq_open_max) {
346 kmem_free(name, MQ_NAMELEN); 315 kmem_free(name, MQ_NAMELEN);
347 return EMFILE; 316 return EMFILE;
348 } 317 }
349 318
 319 /* Empty name is invalid */
 320 if (name[0] == '\0') {
 321 kmem_free(name, MQ_NAMELEN);
 322 return EINVAL;
 323 }
 324
350 /* Check for mqueue attributes */ 325 /* Check for mqueue attributes */
351 if (SCARG(uap, attr)) { 326 if (SCARG(uap, attr)) {
352 error = copyin(SCARG(uap, attr), &attr, 327 error = copyin(SCARG(uap, attr), &attr,
353 sizeof(struct mq_attr)); 328 sizeof(struct mq_attr));
354 if (error) { 329 if (error) {
355 kmem_free(name, MQ_NAMELEN); 330 kmem_free(name, MQ_NAMELEN);
356 return error; 331 return error;
357 } 332 }
358 if (attr.mq_maxmsg <= 0 || attr.mq_msgsize <= 0 || 333 if (attr.mq_maxmsg <= 0 || attr.mq_msgsize <= 0 ||
359 attr.mq_msgsize > mq_max_msgsize) { 334 attr.mq_msgsize > mq_max_msgsize) {
360 kmem_free(name, MQ_NAMELEN); 335 kmem_free(name, MQ_NAMELEN);
361 return EINVAL; 336 return EINVAL;
362 } 337 }
@@ -373,65 +348,81 @@ sys_mq_open(struct lwp *l, const struct  @@ -373,65 +348,81 @@ sys_mq_open(struct lwp *l, const struct
373 * copy the name, attributes and set the flag. 348 * copy the name, attributes and set the flag.
374 */ 349 */
375 mq_new = kmem_zalloc(sizeof(struct mqueue), KM_SLEEP); 350 mq_new = kmem_zalloc(sizeof(struct mqueue), KM_SLEEP);
376 351
377 mutex_init(&mq_new->mq_mtx, MUTEX_DEFAULT, IPL_NONE); 352 mutex_init(&mq_new->mq_mtx, MUTEX_DEFAULT, IPL_NONE);
378 cv_init(&mq_new->mq_send_cv, "mqsendcv"); 353 cv_init(&mq_new->mq_send_cv, "mqsendcv");
379 cv_init(&mq_new->mq_recv_cv, "mqrecvcv"); 354 cv_init(&mq_new->mq_recv_cv, "mqrecvcv");
380 TAILQ_INIT(&mq_new->mq_head); 355 TAILQ_INIT(&mq_new->mq_head);
381 selinit(&mq_new->mq_rsel); 356 selinit(&mq_new->mq_rsel);
382 selinit(&mq_new->mq_wsel); 357 selinit(&mq_new->mq_wsel);
383 358
384 strlcpy(mq_new->mq_name, name, MQ_NAMELEN); 359 strlcpy(mq_new->mq_name, name, MQ_NAMELEN);
385 memcpy(&mq_new->mq_attrib, &attr, sizeof(struct mq_attr)); 360 memcpy(&mq_new->mq_attrib, &attr, sizeof(struct mq_attr));
386 mq_new->mq_attrib.mq_flags = oflag; 361
 362 CTASSERT((O_MASK & (MQ_UNLINK | MQ_RECEIVE)) == 0);
 363 mq_new->mq_attrib.mq_flags = (O_MASK & oflag);
387 364
388 /* Store mode and effective UID with GID */ 365 /* Store mode and effective UID with GID */
389 mq_new->mq_mode = ((SCARG(uap, mode) & 366 mq_new->mq_mode = ((SCARG(uap, mode) &
390 ~cwdi->cwdi_cmask) & ALLPERMS) & ~S_ISTXT; 367 ~cwdi->cwdi_cmask) & ALLPERMS) & ~S_ISTXT;
391 mq_new->mq_euid = kauth_cred_geteuid(l->l_cred); 368 mq_new->mq_euid = kauth_cred_geteuid(l->l_cred);
392 mq_new->mq_egid = kauth_cred_getegid(l->l_cred); 369 mq_new->mq_egid = kauth_cred_getegid(l->l_cred);
393 } 370 }
394 371
395 /* Allocate file structure and descriptor */ 372 /* Allocate file structure and descriptor */
396 error = fd_allocfile(&fp, &mqd); 373 error = fd_allocfile(&fp, &mqd);
397 if (error) { 374 if (error) {
398 if (mq_new) 375 if (mq_new)
399 mqueue_destroy(mq_new); 376 mqueue_destroy(mq_new);
400 kmem_free(name, MQ_NAMELEN); 377 kmem_free(name, MQ_NAMELEN);
401 return error; 378 return error;
402 } 379 }
403 fp->f_type = DTYPE_MQUEUE; 380 fp->f_type = DTYPE_MQUEUE;
404 fp->f_flag = FFLAGS(oflag) & (FREAD | FWRITE); 381 fp->f_flag = FFLAGS(oflag) & (FREAD | FWRITE);
405 fp->f_ops = &mqops; 382 fp->f_ops = &mqops;
406 383
407 /* Look up for mqueue with such name */ 384 /* Look up for mqueue with such name */
408 mutex_enter(&mqlist_mtx); 385 mutex_enter(&mqlist_mtx);
409 mq = mqueue_lookup(name); 386 mq = mqueue_lookup(name);
410 if (mq) { 387 if (mq) {
 388 mode_t acc_mode;
 389
411 KASSERT(mutex_owned(&mq->mq_mtx)); 390 KASSERT(mutex_owned(&mq->mq_mtx));
412 391
413 /* Check if mqueue is not marked as unlinking */ 392 /* Check if mqueue is not marked as unlinking */
414 if (mq->mq_attrib.mq_flags & MQ_UNLINK) { 393 if (mq->mq_attrib.mq_flags & MQ_UNLINK) {
415 error = EACCES; 394 error = EACCES;
416 goto exit; 395 goto exit;
417 } 396 }
418 /* Fail if O_EXCL is set, and mqueue already exists */ 397 /* Fail if O_EXCL is set, and mqueue already exists */
419 if ((oflag & O_CREAT) && (oflag & O_EXCL)) { 398 if ((oflag & O_CREAT) && (oflag & O_EXCL)) {
420 error = EEXIST; 399 error = EEXIST;
421 goto exit; 400 goto exit;
422 } 401 }
423 /* Check the permission */ 402
424 if (mqueue_access(l, mq, fp->f_flag)) { 403 /*
 404 * Check the permissions. Note the difference between
 405 * VREAD/VWRITE and FREAD/FWRITE.
 406 */
 407 acc_mode = 0;
 408 if (fp->f_flag & FREAD) {
 409 acc_mode |= VREAD;
 410 }
 411 if (fp->f_flag & FWRITE) {
 412 acc_mode |= VWRITE;
 413 }
 414 if (vaccess(VNON, mq->mq_mode, mq->mq_euid, mq->mq_egid,
 415 acc_mode, l->l_cred)) {
425 error = EACCES; 416 error = EACCES;
426 goto exit; 417 goto exit;
427 } 418 }
428 } else { 419 } else {
429 /* Fail if mqueue neither exists, nor we create it */ 420 /* Fail if mqueue neither exists, nor we create it */
430 if ((oflag & O_CREAT) == 0) { 421 if ((oflag & O_CREAT) == 0) {
431 mutex_exit(&mqlist_mtx); 422 mutex_exit(&mqlist_mtx);
432 KASSERT(mq_new == NULL); 423 KASSERT(mq_new == NULL);
433 fd_abort(p, fp, mqd); 424 fd_abort(p, fp, mqd);
434 kmem_free(name, MQ_NAMELEN); 425 kmem_free(name, MQ_NAMELEN);
435 return ENOENT; 426 return ENOENT;
436 } 427 }
437 428
@@ -480,27 +471,27 @@ sys_mq_close(struct lwp *l, const struct @@ -480,27 +471,27 @@ sys_mq_close(struct lwp *l, const struct
480/* 471/*
481 * Primary mq_receive1() function. 472 * Primary mq_receive1() function.
482 */ 473 */
483static int 474static int
484mq_receive1(struct lwp *l, mqd_t mqdes, void *msg_ptr, size_t msg_len, 475mq_receive1(struct lwp *l, mqd_t mqdes, void *msg_ptr, size_t msg_len,
485 unsigned *msg_prio, int t, ssize_t *mlen) 476 unsigned *msg_prio, int t, ssize_t *mlen)
486{ 477{
487 file_t *fp = NULL; 478 file_t *fp = NULL;
488 struct mqueue *mq; 479 struct mqueue *mq;
489 struct mq_msg *msg = NULL; 480 struct mq_msg *msg = NULL;
490 int error; 481 int error;
491 482
492 /* Get the message queue */ 483 /* Get the message queue */
493 error = mqueue_get(l, mqdes, FREAD, &fp); 484 error = mqueue_get(mqdes, &fp);
494 if (error) 485 if (error)
495 return error; 486 return error;
496 mq = fp->f_data; 487 mq = fp->f_data;
497 488
498 /* Check the message size limits */ 489 /* Check the message size limits */
499 if (msg_len < mq->mq_attrib.mq_msgsize) { 490 if (msg_len < mq->mq_attrib.mq_msgsize) {
500 error = EMSGSIZE; 491 error = EMSGSIZE;
501 goto error; 492 goto error;
502 } 493 }
503 494
504 /* Check if queue is empty */ 495 /* Check if queue is empty */
505 while (TAILQ_EMPTY(&mq->mq_head)) { 496 while (TAILQ_EMPTY(&mq->mq_head)) {
506 if (mq->mq_attrib.mq_flags & O_NONBLOCK) { 497 if (mq->mq_attrib.mq_flags & O_NONBLOCK) {
@@ -635,27 +626,27 @@ mq_send1(struct lwp *l, mqd_t mqdes, con @@ -635,27 +626,27 @@ mq_send1(struct lwp *l, mqd_t mqdes, con
635 else 626 else
636 msg = pool_cache_get(mqmsg_cache, PR_WAITOK); 627 msg = pool_cache_get(mqmsg_cache, PR_WAITOK);
637 628
638 /* Get the data from user-space */ 629 /* Get the data from user-space */
639 error = copyin(msg_ptr, msg->msg_ptr, msg_len); 630 error = copyin(msg_ptr, msg->msg_ptr, msg_len);
640 if (error) { 631 if (error) {
641 mqueue_freemsg(msg, size); 632 mqueue_freemsg(msg, size);
642 return error; 633 return error;
643 } 634 }
644 msg->msg_len = msg_len; 635 msg->msg_len = msg_len;
645 msg->msg_prio = msg_prio; 636 msg->msg_prio = msg_prio;
646 637
647 /* Get the mqueue */ 638 /* Get the mqueue */
648 error = mqueue_get(l, mqdes, FWRITE, &fp); 639 error = mqueue_get(mqdes, &fp);
649 if (error) { 640 if (error) {
650 mqueue_freemsg(msg, size); 641 mqueue_freemsg(msg, size);
651 return error; 642 return error;
652 } 643 }
653 mq = fp->f_data; 644 mq = fp->f_data;
654 645
655 /* Check the message size limit */ 646 /* Check the message size limit */
656 if (msg_len <= 0 || msg_len > mq->mq_attrib.mq_msgsize) { 647 if (msg_len <= 0 || msg_len > mq->mq_attrib.mq_msgsize) {
657 error = EMSGSIZE; 648 error = EMSGSIZE;
658 goto error; 649 goto error;
659 } 650 }
660 651
661 /* Check if queue is full */ 652 /* Check if queue is full */
@@ -772,27 +763,27 @@ sys_mq_notify(struct lwp *l, const struc @@ -772,27 +763,27 @@ sys_mq_notify(struct lwp *l, const struc
772 file_t *fp = NULL; 763 file_t *fp = NULL;
773 struct mqueue *mq; 764 struct mqueue *mq;
774 struct sigevent sig; 765 struct sigevent sig;
775 int error; 766 int error;
776 767
777 if (SCARG(uap, notification)) { 768 if (SCARG(uap, notification)) {
778 /* Get the signal from user-space */ 769 /* Get the signal from user-space */
779 error = copyin(SCARG(uap, notification), &sig, 770 error = copyin(SCARG(uap, notification), &sig,
780 sizeof(struct sigevent)); 771 sizeof(struct sigevent));
781 if (error) 772 if (error)
782 return error; 773 return error;
783 } 774 }
784 775
785 error = mqueue_get(l, SCARG(uap, mqdes), FNOVAL, &fp); 776 error = mqueue_get(SCARG(uap, mqdes), &fp);
786 if (error) 777 if (error)
787 return error; 778 return error;
788 mq = fp->f_data; 779 mq = fp->f_data;
789 780
790 if (SCARG(uap, notification)) { 781 if (SCARG(uap, notification)) {
791 /* Register notification: set the signal and target process */ 782 /* Register notification: set the signal and target process */
792 if (mq->mq_notify_proc == NULL) { 783 if (mq->mq_notify_proc == NULL) {
793 memcpy(&mq->mq_sig_notify, &sig, 784 memcpy(&mq->mq_sig_notify, &sig,
794 sizeof(struct sigevent)); 785 sizeof(struct sigevent));
795 mq->mq_notify_proc = l->l_proc; 786 mq->mq_notify_proc = l->l_proc;
796 } else { 787 } else {
797 /* Fail if someone else already registered */ 788 /* Fail if someone else already registered */
798 error = EBUSY; 789 error = EBUSY;
@@ -811,27 +802,27 @@ int @@ -811,27 +802,27 @@ int
811sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap, 802sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap,
812 register_t *retval) 803 register_t *retval)
813{ 804{
814 /* { 805 /* {
815 syscallarg(mqd_t) mqdes; 806 syscallarg(mqd_t) mqdes;
816 syscallarg(struct mq_attr *) mqstat; 807 syscallarg(struct mq_attr *) mqstat;
817 } */ 808 } */
818 file_t *fp = NULL; 809 file_t *fp = NULL;
819 struct mqueue *mq; 810 struct mqueue *mq;
820 struct mq_attr attr; 811 struct mq_attr attr;
821 int error; 812 int error;
822 813
823 /* Get the message queue */ 814 /* Get the message queue */
824 error = mqueue_get(l, SCARG(uap, mqdes), FNOVAL, &fp); 815 error = mqueue_get(SCARG(uap, mqdes), &fp);
825 if (error) 816 if (error)
826 return error; 817 return error;
827 mq = fp->f_data; 818 mq = fp->f_data;
828 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); 819 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
829 mutex_exit(&mq->mq_mtx); 820 mutex_exit(&mq->mq_mtx);
830 fd_putfile((int)SCARG(uap, mqdes)); 821 fd_putfile((int)SCARG(uap, mqdes));
831 822
832 return copyout(&attr, SCARG(uap, mqstat), sizeof(struct mq_attr)); 823 return copyout(&attr, SCARG(uap, mqstat), sizeof(struct mq_attr));
833} 824}
834 825
835int 826int
836sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap, 827sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap,
837 register_t *retval) 828 register_t *retval)
@@ -842,27 +833,27 @@ sys_mq_setattr(struct lwp *l, const stru @@ -842,27 +833,27 @@ sys_mq_setattr(struct lwp *l, const stru
842 syscallarg(struct mq_attr *) omqstat; 833 syscallarg(struct mq_attr *) omqstat;
843 } */ 834 } */
844 file_t *fp = NULL; 835 file_t *fp = NULL;
845 struct mqueue *mq; 836 struct mqueue *mq;
846 struct mq_attr attr; 837 struct mq_attr attr;
847 int error, nonblock; 838 int error, nonblock;
848 839
849 error = copyin(SCARG(uap, mqstat), &attr, sizeof(struct mq_attr)); 840 error = copyin(SCARG(uap, mqstat), &attr, sizeof(struct mq_attr));
850 if (error) 841 if (error)
851 return error; 842 return error;
852 nonblock = (attr.mq_flags & O_NONBLOCK); 843 nonblock = (attr.mq_flags & O_NONBLOCK);
853 844
854 /* Get the message queue */ 845 /* Get the message queue */
855 error = mqueue_get(l, SCARG(uap, mqdes), FNOVAL, &fp); 846 error = mqueue_get(SCARG(uap, mqdes), &fp);
856 if (error) 847 if (error)
857 return error; 848 return error;
858 mq = fp->f_data; 849 mq = fp->f_data;
859 850
860 /* Copy the old attributes, if needed */ 851 /* Copy the old attributes, if needed */
861 if (SCARG(uap, omqstat)) 852 if (SCARG(uap, omqstat))
862 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); 853 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
863 854
864 /* Ignore everything, except O_NONBLOCK */ 855 /* Ignore everything, except O_NONBLOCK */
865 if (nonblock) 856 if (nonblock)
866 mq->mq_attrib.mq_flags |= O_NONBLOCK; 857 mq->mq_attrib.mq_flags |= O_NONBLOCK;
867 else 858 else
868 mq->mq_attrib.mq_flags &= ~O_NONBLOCK; 859 mq->mq_attrib.mq_flags &= ~O_NONBLOCK;
@@ -900,27 +891,28 @@ sys_mq_unlink(struct lwp *l, const struc @@ -900,27 +891,28 @@ sys_mq_unlink(struct lwp *l, const struc
900 kmem_free(name, MQ_NAMELEN); 891 kmem_free(name, MQ_NAMELEN);
901 return error; 892 return error;
902 } 893 }
903 894
904 /* Lookup for this file */ 895 /* Lookup for this file */
905 mutex_enter(&mqlist_mtx); 896 mutex_enter(&mqlist_mtx);
906 mq = mqueue_lookup(name); 897 mq = mqueue_lookup(name);
907 if (mq == NULL) { 898 if (mq == NULL) {
908 error = ENOENT; 899 error = ENOENT;
909 goto error; 900 goto error;
910 } 901 }
911 902
912 /* Check the permissions */ 903 /* Check the permissions */
913 if (mqueue_access(l, mq, FWRITE)) { 904 if (kauth_cred_geteuid(l->l_cred) != mq->mq_euid &&
 905 kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
914 mutex_exit(&mq->mq_mtx); 906 mutex_exit(&mq->mq_mtx);
915 error = EACCES; 907 error = EACCES;
916 goto error; 908 goto error;
917 } 909 }
918 910
919 /* Mark message queue as unlinking, before leaving the window */ 911 /* Mark message queue as unlinking, before leaving the window */
920 mq->mq_attrib.mq_flags |= MQ_UNLINK; 912 mq->mq_attrib.mq_flags |= MQ_UNLINK;
921 913
922 /* Wake up all waiters, if there are such */ 914 /* Wake up all waiters, if there are such */
923 cv_broadcast(&mq->mq_send_cv); 915 cv_broadcast(&mq->mq_send_cv);
924 cv_broadcast(&mq->mq_recv_cv); 916 cv_broadcast(&mq->mq_recv_cv);
925 917
926 selnotify(&mq->mq_rsel, POLLHUP, 0); 918 selnotify(&mq->mq_rsel, POLLHUP, 0);