From: Manfred Spraul <manfred@colorfullife.com>

I found a security bug in the new mqueue code: a process that has only
write permissions to a message queue could call mq_notify(SIGEV_THREAD) and
use the returned notification file descriptor to read from the message
queue.


---

 ipc/mqueue.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff -puN ipc/mqueue.c~mq-security-fix ipc/mqueue.c
--- 25/ipc/mqueue.c~mq-security-fix	2004-03-07 01:16:50.000000000 -0800
+++ 25-akpm/ipc/mqueue.c	2004-03-07 01:16:50.000000000 -0800
@@ -837,11 +837,11 @@ asmlinkage long sys_mq_timedsend(mqd_t m
 		goto out;
 
 	inode = filp->f_dentry->d_inode;
-	if (unlikely(inode->i_sb != mqueue_mnt->mnt_sb))
+	if (unlikely(filp->f_op != &mqueue_file_operations))
 		goto out_fput;
 	info = MQUEUE_I(inode);
 
-	if (unlikely((filp->f_flags & O_ACCMODE) == O_RDONLY))
+	if (unlikely(!(filp->f_mode & FMODE_WRITE)))
 		goto out_fput;
 
 	if (unlikely(msg_len > info->attr.mq_msgsize)) {
@@ -915,11 +915,11 @@ asmlinkage ssize_t sys_mq_timedreceive(m
 		goto out;
 
 	inode = filp->f_dentry->d_inode;
-	if (unlikely(inode->i_sb != mqueue_mnt->mnt_sb))
+	if (unlikely(filp->f_op != &mqueue_file_operations))
 		goto out_fput;
 	info = MQUEUE_I(inode);
 
-	if (unlikely((filp->f_flags & O_ACCMODE) == O_WRONLY))
+	if (unlikely(!(filp->f_mode & FMODE_READ)))
 		goto out_fput;
 
 	/* checks if buffer is big enough */
@@ -1004,7 +1004,7 @@ asmlinkage long sys_mq_notify(mqd_t mqde
 		goto out;
 
 	inode = filp->f_dentry->d_inode;
-	if (unlikely(inode->i_sb != mqueue_mnt->mnt_sb))
+	if (unlikely(filp->f_op != &mqueue_file_operations))
 		goto out_fput;
 	info = MQUEUE_I(inode);
 
@@ -1024,6 +1024,7 @@ asmlinkage long sys_mq_notify(mqd_t mqde
 		nfilp->f_vfsmnt = mntget(mqueue_mnt);
 		nfilp->f_dentry = dget(filp->f_dentry);
 		nfilp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+		nfilp->f_flags = O_RDONLY;
 		nfilp->f_mode = FMODE_READ;
 	} else {
 		nfilp = NULL;
@@ -1088,7 +1089,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t 
 		goto out;
 
 	inode = filp->f_dentry->d_inode;
-	if (unlikely(inode->i_sb != mqueue_mnt->mnt_sb))
+	if (unlikely(filp->f_op != &mqueue_file_operations))
 		goto out_fput;
 	info = MQUEUE_I(inode);
 

_