
From: Arnd Bergmann <arnd@arndb.de>

- handle SIGEV_THREAD

- don't try to convert u_attr in sys_mq_open if !O_CREAT 

- handle __SI_MESGQ in copy_siginfo_to_user32 (still missing for ppc64
  and parisc)


---

 25-akpm/arch/ia64/ia32/ia32_signal.c     |    7 ++++++-
 25-akpm/arch/mips/kernel/signal32.c      |    7 ++++++-
 25-akpm/arch/s390/kernel/compat_signal.c |    5 ++++-
 25-akpm/arch/sparc64/kernel/signal32.c   |    7 ++++++-
 25-akpm/arch/x86_64/ia32/ia32_signal.c   |    6 +++++-
 25-akpm/ipc/compat_mq.c                  |   13 ++++++++++++-
 6 files changed, 39 insertions(+), 6 deletions(-)

diff -puN arch/ia64/ia32/ia32_signal.c~more-fixups-for-compat_mq arch/ia64/ia32/ia32_signal.c
--- 25/arch/ia64/ia32/ia32_signal.c~more-fixups-for-compat_mq	2004-04-10 14:54:55.418844448 -0700
+++ 25-akpm/arch/ia64/ia32/ia32_signal.c	2004-04-10 14:54:55.434842016 -0700
@@ -114,7 +114,12 @@ copy_siginfo_from_user32 (siginfo_t *to,
 			err |= __get_user(to->si_band, &from->si_band);
 			err |= __get_user(to->si_fd, &from->si_fd);
 			break;
-			/* case __SI_RT: This is not generated by the kernel as of now.  */
+		      case __SI_RT: /* This is not generated by the kernel as of now.  */
+		      case __SI_MESGQ:
+			err |= __get_user(to->si_pid, &from->si_pid);
+			err |= __get_user(to->si_uid, &from->si_uid);
+			err |= __get_user(to->si_int, &from->si_int);
+			break;
 		}
 	}
 	return err;
diff -puN arch/mips/kernel/signal32.c~more-fixups-for-compat_mq arch/mips/kernel/signal32.c
--- 25/arch/mips/kernel/signal32.c~more-fixups-for-compat_mq	2004-04-10 14:54:55.419844296 -0700
+++ 25-akpm/arch/mips/kernel/signal32.c	2004-04-10 14:54:55.434842016 -0700
@@ -358,7 +358,12 @@ static int copy_siginfo_to_user32(siginf
 			err |= __put_user(from->si_band, &to->si_band);
 			err |= __put_user(from->si_fd, &to->si_fd);
 			break;
-		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		case __SI_RT: /* This is not generated by the kernel as of now.  */
+		case __SI_MESGQ:
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_uid, &to->si_uid);
+			err |= __put_user(from->si_int, &to->si_int);
+			break;
 		}
 	}
 	return err;
diff -puN arch/s390/kernel/compat_signal.c~more-fixups-for-compat_mq arch/s390/kernel/compat_signal.c
--- 25/arch/s390/kernel/compat_signal.c~more-fixups-for-compat_mq	2004-04-10 14:54:55.422843840 -0700
+++ 25-akpm/arch/s390/kernel/compat_signal.c	2004-04-10 14:54:55.435841864 -0700
@@ -74,6 +74,10 @@ int copy_siginfo_to_user32(siginfo_t32 *
 		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 	else {
 		switch (from->si_code >> 16) {
+		case __SI_RT: /* This is not generated by the kernel as of now.  */
+		case __SI_MESGQ:
+			err |= __put_user(from->si_int, &to->si_int);
+			/* fallthrough */
 		case __SI_KILL >> 16:
 			err |= __put_user(from->si_pid, &to->si_pid);
 			err |= __put_user(from->si_uid, &to->si_uid);
@@ -96,7 +100,6 @@ int copy_siginfo_to_user32(siginfo_t32 *
 			break;
 		default:
 			break;
-		/* case __SI_RT: This is not generated by the kernel as of now.  */
 		}
 	}
 	return err;
diff -puN arch/sparc64/kernel/signal32.c~more-fixups-for-compat_mq arch/sparc64/kernel/signal32.c
--- 25/arch/sparc64/kernel/signal32.c~more-fixups-for-compat_mq	2004-04-10 14:54:55.425843384 -0700
+++ 25-akpm/arch/sparc64/kernel/signal32.c	2004-04-10 14:54:55.436841712 -0700
@@ -129,7 +129,12 @@ int copy_siginfo_to_user32(siginfo_t32 _
 			err |= __put_user(from->si_trapno, &to->si_trapno);
 			err |= __put_user((long)from->si_addr, &to->si_addr);
 			break;
-		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		case __SI_RT: /* This is not generated by the kernel as of now.  */
+		case __SI_MESGQ:
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_uid, &to->si_uid);
+			err |= __put_user(from->si_int, &to->si_int);
+			break;
 		}
 	}
 	return err;
diff -puN arch/x86_64/ia32/ia32_signal.c~more-fixups-for-compat_mq arch/x86_64/ia32/ia32_signal.c
--- 25/arch/x86_64/ia32/ia32_signal.c~more-fixups-for-compat_mq	2004-04-10 14:54:55.427843080 -0700
+++ 25-akpm/arch/x86_64/ia32/ia32_signal.c	2004-04-10 14:54:55.437841560 -0700
@@ -85,7 +85,11 @@ int ia32_copy_siginfo_to_user(siginfo_t3
 			err |= __put_user(from->si_overrun, &to->si_overrun); 
 			err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr);
 			break;
-		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		case __SI_RT: /* This is not generated by the kernel as of now.  */
+		case __SI_MESGQ:
+			err |= __put_user(from->si_uid, &to->si_uid);
+			err |= __put_user(from->si_int, &to->si_int);
+			break;
 		}
 	}
 	return err;
diff -puN ipc/compat_mq.c~more-fixups-for-compat_mq ipc/compat_mq.c
--- 25/ipc/compat_mq.c~more-fixups-for-compat_mq	2004-04-10 14:54:55.429842776 -0700
+++ 25-akpm/ipc/compat_mq.c	2004-04-10 14:54:55.432842320 -0700
@@ -55,7 +55,7 @@ asmlinkage long compat_sys_mq_open(const
 	char *name;
 	long ret;
 
-	if (!u_attr)
+	if ((oflag & O_CREAT) == 0 || !u_attr)
 		return sys_mq_open(u_name, oflag, mode, 0);
 
 	if (get_compat_mq_attr(&attr, u_attr))
@@ -139,6 +139,8 @@ asmlinkage long compat_sys_mq_notify(mqd
 {
 	mm_segment_t oldfs;
 	struct sigevent notification;
+	char cookie[NOTIFY_COOKIE_LEN];
+	compat_uptr_t u_cookie;
 	long ret;
 
 	if (!u_notification)
@@ -147,6 +149,15 @@ asmlinkage long compat_sys_mq_notify(mqd
 	if (get_compat_sigevent(&notification, u_notification))
 		return -EFAULT;
 
+	if (notification.sigev_notify == SIGEV_THREAD) {
+		u_cookie = (compat_uptr_t)notification.sigev_value.sival_int;
+		if (copy_from_user(cookie, compat_ptr(u_cookie),
+						NOTIFY_COOKIE_LEN)) {
+			return -EFAULT;
+		}
+		notification.sigev_value.sival_ptr = cookie;
+	}
+
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
 	ret = sys_mq_notify(mqdes, &notification);

_
