mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH resend] Opteron support for mqueues-4.00 +bug fixes
@ 2003-11-20 14:32 Joe Korty
  0 siblings, 0 replies; 3+ messages in thread
From: Joe Korty @ 2003-11-20 14:32 UTC (permalink / raw)
  To: wrona, golbi; +Cc: linux-kernel

[ resending from another account, the previous didn't make it to the list ]


Hi Michal, Krzysztof,

Applies against 2.6.0-test9-bk1 + the mqueues-4.00 kernel patch.

 o adds Opteron native and ia32 interfaces for posix message queues
 o fixes sys_mq_unlink OOPs for nonexistant filename
 o mq_open now returns EINVAL when (flags & 3) == 3

Some comments:

2.6.0-test9-bk1 was used as 2.6.0-test9 doesn't boot on Opteron.

Opteron (and probably the other 64 bit archs) require that a kernel
system call definition return a long (hence the s/asmlinkage int
sys_/asmlinkage long sys_/ changes throughout the patch).

Passes the mqueue portion of posixtestsuites-1.3.0 on i386, and also
passes on Opteron in native and in ia32 compatibility mode.

Regards,
Joe



diff -ura 4.00/arch/x86_64/ia32/ia32entry.S new/arch/x86_64/ia32/ia32entry.S
--- 4.00/arch/x86_64/ia32/ia32entry.S	2003-10-25 14:43:32.000000000 -0400
+++ new/arch/x86_64/ia32/ia32entry.S	2003-11-19 17:12:53.000000000 -0500
@@ -476,6 +476,16 @@
 	.quad sys_tgkill
 	.quad compat_sys_utimes
 	.quad sys32_fadvise64_64
+	.quad ni_syscall
+
+	.quad compat_sys_mq_open
+	.quad sys_mq_unlink
+	.quad compat_sys_mq_timedsend
+	.quad compat_sys_mq_timedreceive
+	.quad compat_sys_mq_notify
+	.quad compat_sys_mq_getattr
+	.quad compat_sys_mq_setattr
+
 	/* don't forget to change IA32_NR_syscalls */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
diff -ura 4.00/include/asm-x86_64/ia32_unistd.h new/include/asm-x86_64/ia32_unistd.h
--- 4.00/include/asm-x86_64/ia32_unistd.h	2003-10-25 14:43:59.000000000 -0400
+++ new/include/asm-x86_64/ia32_unistd.h	2003-11-19 14:53:14.000000000 -0500
@@ -279,6 +279,14 @@
 #define __NR_ia32_utimes		271
 #define __NR_ia32_fadvise64_64		272
 
-#define IA32_NR_syscalls 275	/* must be > than biggest syscall! */	
+#define __NR_ia32_mq_open 		274
+#define __NR_ia32_mq_unlink		(__NR_ia32_mqopen+1)
+#define __NR_ia32_mq_timedsend		(__NR_ia32_mqopen+2)
+#define __NR_ia32_mq_timedreceive	(__NR_ia32_mqopen+3)
+#define __NR_ia32_mq_notify		(__NR_ia32_mqopen+4)
+#define __NR_ia32_mq_getattr		(__NR_ia32_mqopen+5)
+#define __NR_ia32_mq_setattr		(__NR_ia32_mqopen+6)
+
+#define IA32_NR_syscalls 281	/* must be > than biggest syscall! */	
 
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff -ura 4.00/include/asm-x86_64/unistd.h new/include/asm-x86_64/unistd.h
--- 4.00/include/asm-x86_64/unistd.h	2003-10-25 14:44:03.000000000 -0400
+++ new/include/asm-x86_64/unistd.h	2003-11-19 14:52:17.000000000 -0500
@@ -532,8 +532,23 @@
 __SYSCALL(__NR_utimes, sys_utimes)
 #define __NR_vserver		236
 __SYSCALL(__NR_vserver, sys_ni_syscall)
+#define __NR_mq_open			274
+__SYSCALL(__NR_mq_open, sys_mq_open)
+#define __NR_mq_unlink			275
+__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
+#define __NR_mq_timedsend		276
+__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend)
+#define __NR_mq_timedreceive		277
+__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive)
+#define __NR_mq_notify			278
+__SYSCALL(__NR_mq_notify, sys_mq_notify)
+#define __NR_mq_getattr			279
+__SYSCALL(__NR_mq_getattr, sys_mq_getattr)
+#define __NR_mq_setattr			280
+__SYSCALL(__NR_mq_setattr, sys_mq_setattr)
 
-#define __NR_syscall_max __NR_vserver
+#undef __NR_syscall_max
+#define __NR_syscall_max __NR_mq_setattr
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
diff -ura 4.00/include/linux/compat.h new/include/linux/compat.h
--- 4.00/include/linux/compat.h	2003-10-25 14:43:34.000000000 -0400
+++ new/include/linux/compat.h	2003-11-19 16:21:40.000000000 -0500
@@ -44,8 +44,8 @@
 } compat_sigset_t;
 
 extern int cp_compat_stat(struct kstat *, struct compat_stat *);
-extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
-extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
+extern int get_compat_timespec(struct timespec *, const struct compat_timespec *);
+extern int put_compat_timespec(struct timespec *, const struct compat_timespec *);
 
 struct compat_iovec {
 	compat_uptr_t	iov_base;
diff -ura 4.00/include/linux/mqueue.h new/include/linux/mqueue.h
--- 4.00/include/linux/mqueue.h	2003-11-19 10:57:58.000000000 -0500
+++ new/include/linux/mqueue.h	2003-11-19 15:06:55.000000000 -0500
@@ -21,12 +21,14 @@
 	long mq_curmsgs;	/* number of messages currently queued */
 };
 
-asmlinkage mqd_t sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr);
-asmlinkage int sys_mq_unlink(const char __user *name);
-asmlinkage int mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec __user *abs_timeout);
+#ifdef __KERNEL__
+asmlinkage long sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr);
+asmlinkage long sys_mq_unlink(const char __user *name);
+asmlinkage long mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec __user *abs_timeout);
 asmlinkage ssize_t mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct timespec __user *abs_timeout);
-asmlinkage int mq_notify(mqd_t mqdes, const struct sigevent __user *notification);
-asmlinkage int mq_getattr(mqd_t mqdes, struct mq_attr __user *mqstat);
-asmlinkage int mq_setattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat);
+asmlinkage long mq_notify(mqd_t mqdes, const struct sigevent __user *notification);
+asmlinkage long mq_getattr(mqd_t mqdes, struct mq_attr __user *mqstat);
+asmlinkage long mq_setattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat);
+#endif
 
 #endif
diff -ura 4.00/ipc/mqueue.c new/ipc/mqueue.c
--- 4.00/ipc/mqueue.c	2003-11-19 10:57:58.000000000 -0500
+++ new/ipc/mqueue.c	2003-11-19 16:20:08.000000000 -0500
@@ -724,6 +724,9 @@
 	struct file *filp;
 	static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, MAY_READ | MAY_WRITE };
 
+	if ((oflag & O_ACCMODE) == 3)
+		return ERR_PTR(-EINVAL);
+
 	if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL))
 		return ERR_PTR(-EACCES);
 
@@ -735,7 +738,7 @@
 	return filp;
 }
 
-asmlinkage mqd_t sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
+asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
 	struct mq_attr __user *attr)
 {
 	struct dentry *dentry;
@@ -790,7 +793,7 @@
 }
 
 
-asmlinkage int sys_mq_unlink(const char __user *u_name)
+asmlinkage long sys_mq_unlink(const char __user *u_name)
 {
 	int err;
 	char *name;
@@ -807,6 +810,11 @@
 		err = PTR_ERR(dentry);
 		goto out_unlock;
 	}
+	if (!dentry->d_inode) {
+		err = -ENOENT;
+		goto out_unlock;
+	}
+
 	if (permission(dentry->d_inode, MAY_WRITE, NULL))
 	{	
 		err = -EACCES;
@@ -829,23 +837,18 @@
 	return err;
 }
 
-
-asmlinkage int sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 
-	size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
+static asmlinkage long do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 
+	size_t msg_len, unsigned int msg_prio, const long timeout)
 {
 	struct file *filp;
 	struct inode *ino;
 	struct ext_wait_queue *wq_ptr;
 	struct msg_msg *msg_ptr;
-	long timeout;
 	int ret;
 	struct mqueue_inode_info *info = MQUEUE_I(ino);
 
 	if (msg_prio >= (unsigned long) MQ_PRIO_MAX)
 		return -EINVAL;
-
-	if ((timeout = prepare_timeout(u_abs_timeout)) < 0)
-		return timeout;
 	
 	ret = -EBADF;
 	filp = fget(mqdes);
@@ -944,10 +947,19 @@
 	return ret;
 }
 
-asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 
-	size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
+asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 
+	size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
 {
 	long timeout;
+
+	if ((timeout = prepare_timeout(u_abs_timeout)) < 0)
+		return timeout;
+	return do_mq_timedsend(mqdes, u_msg_ptr, msg_len, msg_prio, timeout);
+}
+
+static asmlinkage ssize_t do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 
+	size_t msg_len, unsigned int __user *u_msg_prio, const long timeout)
+{
 	ssize_t ret;
 	struct msg_msg *msg_ptr;
 	struct file *filp;
@@ -955,9 +967,6 @@
 	struct mqueue_inode_info *info;
 	struct ext_wait_queue *wq_ptr;
 	
-	if ((timeout = prepare_timeout(u_abs_timeout)) < 0)
-		return timeout;	
-	
 	ret = -EBADF;
 	filp = fget(mqdes);
 	if (!filp)
@@ -1040,12 +1049,23 @@
 	return ret;
 }
 
+asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 
+	size_t msg_len, unsigned int __user *u_msg_prio,
+	const struct timespec __user *u_abs_timeout)
+{
+	long timeout;
+	
+	if ((timeout = prepare_timeout(u_abs_timeout)) < 0)
+		return timeout;	
+	return do_mq_timedreceive(mqdes, u_msg_ptr, msg_len, u_msg_prio, timeout);
+}
+
 
 /* Notes: the case when user wants us to deregister (with NULL as pointer or SIGEV_NONE)
  * and he isn't currently owner of notification will be silently discarded. 
  * It isn't explicitly defined in the POSIX. 
  */
-asmlinkage int sys_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
 {
 	int ret;
 	struct file *filp;
@@ -1105,7 +1125,7 @@
 	return ret;
 }
 
-asmlinkage int sys_mq_getattr(mqd_t mqdes, struct mq_attr __user *u_mqstat)
+asmlinkage long sys_mq_getattr(mqd_t mqdes, struct mq_attr __user *u_mqstat)
 {
 	int ret;
 	struct mq_attr attr;
@@ -1143,7 +1163,7 @@
 	return ret;
 }
 
-asmlinkage int sys_mq_setattr(mqd_t mqdes, const struct mq_attr __user *u_mqstat,
+asmlinkage long sys_mq_setattr(mqd_t mqdes, const struct mq_attr __user *u_mqstat,
 	struct mq_attr __user *u_omqstat)
 {
 	int ret;
@@ -1192,6 +1212,220 @@
 	return ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+#include <linux/compat.h>
+
+struct compat_mq_attr {
+	u32	mq_flags;
+	s32	mq_maxmsg;
+	s32	mq_msgsize;
+	s32	mq_curmsgs;
+};
+
+static asmlinkage long load_mq_attr(struct mq_attr *attrp,
+		const struct compat_mq_attr __user *compat_attrp_user)
+{
+	struct compat_mq_attr compat_attr;
+
+	if (copy_from_user(&compat_attr, compat_attrp_user, sizeof(compat_attr))) {
+		return -EFAULT;
+	}
+	attrp->mq_flags = compat_attr.mq_flags;
+	attrp->mq_maxmsg = compat_attr.mq_maxmsg;
+	attrp->mq_msgsize = compat_attr.mq_msgsize;
+	attrp->mq_curmsgs = compat_attr.mq_curmsgs;
+	return 0;
+}
+
+static asmlinkage long store_mq_attr(struct compat_mq_attr __user *compat_attrp_user,
+		const struct mq_attr *attrp)
+{
+	struct compat_mq_attr compat_attr;
+
+	compat_attr.mq_flags = attrp->mq_flags;
+	compat_attr.mq_maxmsg = attrp->mq_maxmsg;
+	compat_attr.mq_msgsize = attrp->mq_msgsize;
+	compat_attr.mq_curmsgs = attrp->mq_curmsgs;
+
+	if (copy_to_user(compat_attrp_user, &compat_attr, sizeof(compat_attr))) {
+		return -EFAULT;
+	}
+	return 0;
+}
+
+asmlinkage long compat_sys_mq_open(const char __user *name_user, int oflag, mode_t mode,
+		struct compat_mq_attr __user *compat_attrp_user)
+{
+	char *name = NULL;
+	struct mq_attr attr, *attrp = NULL;
+	mm_segment_t oldfs;
+	long stat;
+
+	if (compat_attrp_user) {
+		attrp = &attr;
+		if (load_mq_attr(attrp, compat_attrp_user))
+			return -EFAULT;
+	}
+	if (name_user) {
+		name = getname(name_user);
+		if (IS_ERR(name)) {
+			return PTR_ERR(name);
+		}
+	}
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	stat = sys_mq_open(name, oflag, mode, attrp);
+	set_fs(oldfs);
+
+	if (name)
+		putname(name);
+	return stat;
+}
+
+asmlinkage long compat_sys_mq_getattr(mqd_t mqdes, struct compat_mq_attr __user *compat_attrp_user)
+{
+	struct mq_attr attr, *attrp = NULL;
+	mm_segment_t oldfs;
+	long stat;
+
+	if (compat_attrp_user) {
+		attrp = &attr;
+	}
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	stat = sys_mq_getattr(mqdes, attrp);
+	set_fs(oldfs);
+
+	if (!stat && compat_attrp_user) {
+		stat = store_mq_attr(compat_attrp_user, attrp);
+	}
+	return stat;
+}
+
+asmlinkage long compat_sys_mq_setattr(mqd_t mqdes,
+		const struct compat_mq_attr __user *compat_attrp_user,
+		struct compat_mq_attr __user *compat_oattrp_user)
+
+{
+	struct mq_attr attr, *attrp = NULL;
+	struct mq_attr oattr, *oattrp = NULL;
+	mm_segment_t oldfs;
+	long stat;
+
+	if (compat_attrp_user) {
+		attrp = &attr;
+		if (load_mq_attr(attrp, compat_attrp_user))
+			return -EFAULT;
+	}
+	if (compat_oattrp_user) {
+		oattrp = &oattr;
+	}
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	stat = sys_mq_setattr(mqdes, attrp, oattrp);
+	set_fs(oldfs);
+
+	if (!stat && compat_oattrp_user) {
+		stat = store_mq_attr(compat_oattrp_user, oattrp);
+	}
+	return stat;
+}
+
+asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes, char __user *msgp_user, 
+		size_t msg_len, unsigned int msg_prio,
+		const struct compat_timespec __user *compat_abs_timeoutp_user)
+{
+	mm_segment_t oldfs;
+	struct timespec abs_timeout, *abs_timeoutp = NULL;
+	long timeout;
+
+	if (compat_abs_timeoutp_user) {
+		abs_timeoutp = &abs_timeout;
+		if (get_compat_timespec(&abs_timeout, compat_abs_timeoutp_user))
+			return -EFAULT;
+	}
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	timeout = prepare_timeout(abs_timeoutp);
+	set_fs(oldfs);
+
+	if (timeout < 0)
+		return timeout;
+
+	return do_mq_timedsend(mqdes, msgp_user, msg_len, msg_prio, timeout);
+}
+
+asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, char __user *msgp_user, 
+		size_t msg_len, unsigned int __user *msg_priop_user,
+		const struct compat_timespec __user *compat_abs_timeoutp_user)
+{
+	mm_segment_t oldfs;
+	struct timespec abs_timeout, *abs_timeoutp = NULL;
+	long timeout;
+
+	if (compat_abs_timeoutp_user) {
+		abs_timeoutp = &abs_timeout;
+		if (get_compat_timespec(abs_timeoutp, compat_abs_timeoutp_user))
+			return -EFAULT;
+	}
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	timeout = prepare_timeout(abs_timeoutp);
+	set_fs(oldfs);
+
+	if (timeout < 0)
+		return timeout;
+
+	return do_mq_timedreceive(mqdes, msgp_user, msg_len, msg_priop_user, timeout);
+}
+
+struct compat_sigevent_partial {
+	s32	sigev_value;
+	u32	sigev_signo;
+	u32	sigev_notify;
+};
+
+static asmlinkage long get_sigevent_partial(struct sigevent *attrp,
+		const struct compat_sigevent_partial __user *compat_sigevent_partialp_user)
+{
+	struct compat_sigevent_partial compat_sigevent_partial;
+
+	if (copy_from_user(&compat_sigevent_partial, compat_sigevent_partialp_user,
+			sizeof(compat_sigevent_partial))) {
+		return -EFAULT;
+	}
+	attrp->sigev_value.sival_ptr = NULL; /* zero unused bits in union */
+	attrp->sigev_value.sival_int = compat_sigevent_partial.sigev_value;
+	attrp->sigev_signo = compat_sigevent_partial.sigev_signo;
+	attrp->sigev_notify = compat_sigevent_partial.sigev_notify;
+	return 0;
+}
+
+asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
+		const struct compat_sigevent_partial __user *notifyp_user)
+{
+	long stat;
+	struct sigevent notify, *notifyp = NULL;
+	mm_segment_t oldfs;
+
+	if (notifyp_user) {
+		notifyp = &notify;
+		if (get_sigevent_partial(notifyp, notifyp_user))
+			return -EFAULT;
+	}
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	stat = sys_mq_notify(mqdes, notifyp);
+	set_fs(oldfs);
+
+	return stat;
+}
+
+#endif
 
 static struct inode_operations mqueue_dir_inode_operations = {
 	.lookup = mqueue_lookup,
diff -ura 4.00/kernel/compat.c new/kernel/compat.c
--- 4.00/kernel/compat.c	2003-10-25 14:43:40.000000000 -0400
+++ new/kernel/compat.c	2003-11-19 16:21:01.000000000 -0500
@@ -22,14 +22,14 @@
 
 #include <asm/uaccess.h>
 
-int get_compat_timespec(struct timespec *ts, struct compat_timespec *cts)
+int get_compat_timespec(struct timespec *ts, const struct compat_timespec *cts)
 {
 	return (verify_area(VERIFY_READ, cts, sizeof(*cts)) ||
 			__get_user(ts->tv_sec, &cts->tv_sec) ||
 			__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
 
-int put_compat_timespec(struct timespec *ts, struct compat_timespec *cts)
+int put_compat_timespec(struct timespec *ts, const struct compat_timespec *cts)
 {
 	return (verify_area(VERIFY_WRITE, cts, sizeof(*cts)) ||
 			__put_user(ts->tv_sec, &cts->tv_sec) ||

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-11-20 16:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <200311201432.OAA05361@rudolph.ccur.com.suse.lists.linux.kernel>
2003-11-20 15:02 ` [PATCH resend] Opteron support for mqueues-4.00 +bug fixes Andi Kleen
2003-11-20 16:41   ` Joe Korty
2003-11-20 14:32 Joe Korty

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®