From: Manfred Spraul <manfred@colorfullife.com>

My discussion with Ulrich had one result:

- mq_setattr can accept implementation defined flags.  Right now we have
  none, but we might add some later (e.g.  switch to CLOCK_MONOTONIC for
  mq_timed{send,receive} or something similar).  When we add flags, we
  might need the fields for additional information.  And they don't hurt. 
  Therefore add four __reserved fields to mq_attr.

- fail mq_setattr if we get unknown flags - otherwise glibc can't detect
  if it's running on a future kernel that supports new features.

- use memset to initialize the mq_attr structure - theoretically we could
  leak kernel memory.

- Only set O_NONBLOCK in mq_attr, explicitely clear O_RDWR & friends. 
  openposix uses getattr, attr |=O_NONBLOCK, setattr - a sane approach. 
  Without clearing O_RDWR, this fails.

I've retested all openposix conformance tests with the new patch - the two
new FAILED tests check undefined behavior.  Note that I won't have net
access until Sunday - if the message queue patch breaks something important
either ask Krzysztof or drop it.

Ulrich had another good idea for SIGEV_THREAD, but I must think about it. 
It would mean less complexitiy in glibc, but more code in the kernel.  I'm
not yet convinced that it's overall better.


---

 25-akpm/include/linux/mqueue.h |    1 +
 25-akpm/ipc/mqueue.c           |    6 ++++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff -puN include/linux/mqueue.h~mq-update-01 include/linux/mqueue.h
--- 25/include/linux/mqueue.h~mq-update-01	Wed Apr  7 12:12:46 2004
+++ 25-akpm/include/linux/mqueue.h	Wed Apr  7 12:12:46 2004
@@ -27,6 +27,7 @@ struct mq_attr {
 	long	mq_maxmsg;	/* maximum number of messages		*/
 	long	mq_msgsize;	/* maximum message size			*/
 	long	mq_curmsgs;	/* number of messages currently queued	*/
+	long	__reserved[4];	/* ignored for input, zeroed for output */
 };
 
 #define NOTIFY_NONE	0
diff -puN ipc/mqueue.c~mq-update-01 ipc/mqueue.c
--- 25/ipc/mqueue.c~mq-update-01	Wed Apr  7 12:12:46 2004
+++ 25-akpm/ipc/mqueue.c	Wed Apr  7 12:12:46 2004
@@ -121,7 +121,7 @@ static struct inode *mqueue_get_inode(st
 			INIT_LIST_HEAD(&info->e_wait_q[1].list);
 			info->notify_owner = 0;
 			info->qsize = 0;
-			info->attr.mq_curmsgs = 0;
+			memset(&info->attr, 0, sizeof(info->attr));
 			info->attr.mq_maxmsg = DFLT_MSGMAX;
 			info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
 			info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL);
@@ -1078,6 +1078,8 @@ asmlinkage long sys_mq_getsetattr(mqd_t 
 	if (u_mqstat != NULL) {
 		if (copy_from_user(&mqstat, u_mqstat, sizeof(struct mq_attr)))
 			return -EFAULT;
+		if (mqstat.mq_flags & (~O_NONBLOCK))
+			return -EINVAL;
 	}
 
 	ret = -EBADF;
@@ -1093,7 +1095,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t 
 	spin_lock(&info->lock);
 
 	omqstat = info->attr;
-	omqstat.mq_flags = filp->f_flags;
+	omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
 	if (u_mqstat) {
 		if (mqstat.mq_flags & O_NONBLOCK)
 			filp->f_flags |= O_NONBLOCK;

_