From: Manfred Spraul 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 Mon Mar 1 15:40:35 2004 +++ 25-akpm/include/linux/mqueue.h Mon Mar 1 15:40:35 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 Mon Mar 1 15:40:35 2004 +++ 25-akpm/ipc/mqueue.c Mon Mar 1 15:40:35 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; _