All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arun Sharma <arun.sharma@intel.com>
To: Andrew Morton <akpm@osdl.org>
Cc: Arnd Bergmann <arnd@arndb.de>,
	"David S. Miller" <davem@redhat.com>,
	linux-arch@vger.kernel.org
Subject: Re: sys getdents64 needs compat wrapper ?
Date: Thu, 17 Jun 2004 15:28:39 -0700	[thread overview]
Message-ID: <40D21B17.4060603@intel.com> (raw)
In-Reply-To: <40CDEB59.3040203@intel.com>

[-- Attachment #1: Type: text/plain, Size: 813 bytes --]

On 6/14/2004 11:15 AM, Arun Sharma wrote:

>> I just realized your code is broken on big-endian architectures, so
>> we should either get back to __copy_to_user or find the optimal solution
>> now.
>>
>> How about a {__,}{get,put}_user_unaligned() that gets defined per
>> architecture in one of these two ways:
> 
> 
> We'll go for the optimal solution now. We'll provide an 
> <asm-generic/uaccess.h> that does __copy_to_user and a 
> <asm-ia64/uaccess.h> that's optimized for ia64. Archs which don't care 
> about alignment can override appropriately.
> 
> Should have the patch tested by tomorrow.

It took us a bit longer :) But here's the promised patch. Using __put_user_unaligned() on ia64 may still cause unaligned faults, but we chose to optimize for the common case, where it's 4 byte aligned.

	-Arun

[-- Attachment #2: __get_put_user_unaligned.patch --]
[-- Type: text/plain, Size: 8037 bytes --]

(1) Fix compat_filldir64() which is broken on big-endian machines.
(2) Introduce new APIs __{get,put}_user_unaligned.
(3) Optimize __{get,put}_user_unaligned for ia64.

Signed-off-by: Gordon Jin <gordon.jin@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>

---

 fs/compat.c                   |   14 ++++----------
 include/asm-generic/uaccess.h |   25 +++++++++++++++++++++++++
 include/asm-ia64/uaccess.h    |   36 ++++++++++++++++++++++++++++++++++++
 include/asm-mips/uaccess.h    |    1 +
 include/asm-ppc64/uaccess.h   |    1 +
 include/asm-s390/uaccess.h    |    1 +
 include/asm-sparc64/uaccess.h |    1 +
 include/asm-x86_64/uaccess.h  |    1 +
 8 files changed, 70 insertions(+), 10 deletions(-)

diff -purN -X dontdiff linux-2.6.7-rc3-getdents/fs/compat.c linux-2.6.7-rc3-getdents-user_unaligned/fs/compat.c
--- linux-2.6.7-rc3-getdents/fs/compat.c	2004-06-16 22:13:46.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/fs/compat.c	2004-06-17 14:51:42.019623885 +0800
@@ -979,19 +979,14 @@ static int compat_filldir64(void * __buf
 	dirent = buf->previous;
 
 	if (dirent) {
-		if (__put_user(offset, (u32 __user *)&dirent->d_off))
-			goto efault;
-		if (__put_user(offset >> 32,
-				((u32 __user *)&dirent->d_off) + 1))
+		if (__put_user_unaligned(offset, &dirent->d_off))
 			goto efault;
 	}
 	dirent = buf->current_dir;
-	if ((__put_user(ino, (u32 __user *)&dirent->d_ino))
-	 || (__put_user(ino >> 32, ((u32 __user *)&dirent->d_ino) + 1)))
+	if (__put_user_unaligned(ino, &dirent->d_ino))
 		goto efault;
 	off = 0;
-	if ((__put_user(off, (u32 __user *)&dirent->d_off))
-	 || (__put_user(off >> 32, ((u32 __user *)&dirent->d_off) + 1)))
+	if (__put_user_unaligned(off, &dirent->d_off))
 		goto efault;
 	if (__put_user(reclen, &dirent->d_reclen))
 		goto efault;
@@ -1040,8 +1035,7 @@ asmlinkage long compat_sys_getdents64(un
 	lastdirent = buf.previous;
 	if (lastdirent) {
 		typeof(lastdirent->d_off) d_off = file->f_pos;
-		__put_user(d_off, (u32 __user *)&lastdirent->d_off);
-		__put_user(d_off >> 32, ((u32 __user *)&lastdirent->d_off) + 1);
+		__put_user_unaligned(d_off, &lastdirent->d_off);
 		error = count - buf.count;
 	}
 
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-generic/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-generic/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-generic/uaccess.h	1970-01-01 08:00:00.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-generic/uaccess.h	2004-06-17 15:06:28.391683339 +0800
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_UACCESS_H_
+#define _ASM_GENERIC_UACCESS_H_
+
+/* 
+ * This macro should be used instead of __get_user() when accessing
+ * values at locations that are unknown to be aligned.
+ */
+#define __get_user_unaligned(x, ptr)					\
+({									\
+	__typeof__ (*(ptr)) __x = (x);					\
+	copy_from_user(&__x, (ptr), sizeof(*(ptr))) ? -EFAULT : 0;	\
+})
+
+
+/* 
+ * This macro should be used instead of __put_user() when accessing
+ * values at locations that are unknown to be aligned.
+ */
+#define __put_user_unaligned(x, ptr)					\
+({									\
+	__typeof__ (*(ptr)) __x = (x);					\
+	copy_to_user((ptr), &__x, sizeof(*(ptr))) ? -EFAULT : 0;	\
+})
+
+#endif /* _ASM_GENERIC_UACCESS_H */
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-ia64/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-ia64/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-ia64/uaccess.h	2004-06-16 22:13:46.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-ia64/uaccess.h	2004-06-17 15:13:34.646560930 +0800
@@ -91,6 +91,42 @@ verify_area (int type, const void *addr,
 #define __put_user(x, ptr)	__put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
 #define __get_user(x, ptr)	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
 
+extern long __put_user_unaligned_unknown (void);
+
+#define __put_user_unaligned(x, ptr)								\
+({												\
+	long __ret;										\
+	switch (sizeof(*(ptr))) {								\
+		case 1: __ret = __put_user((x), (ptr)); break;					\
+		case 2: __ret = (__put_user((x), (u8 __user *)(ptr)))				\
+			|| (__put_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break;		\
+		case 4: __ret = (__put_user((x), (u16 __user *)(ptr)))				\
+			|| (__put_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break;		\
+		case 8: __ret = (__put_user((x), (u32 __user *)(ptr)))				\
+			|| (__put_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break;		\
+		default: __ret = __put_user_unaligned_unknown();				\
+	}											\
+	__ret;											\
+})
+
+extern long __get_user_unaligned_unknown (void);
+
+#define __get_user_unaligned(x, ptr)								\
+({												\
+	long __ret;										\
+	switch (sizeof(*(ptr))) {								\
+		case 1: __ret = __get_user((x), (ptr)); break;					\
+		case 2: __ret = (__get_user((x), (u8 __user *)(ptr)))				\
+			|| (__get_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break;		\
+		case 4: __ret = (__get_user((x), (u16 __user *)(ptr)))				\
+			|| (__get_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break;		\
+		case 8: __ret = (__get_user((x), (u32 __user *)(ptr)))				\
+			|| (__get_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break;		\
+		default: __ret = __get_user_unaligned_unknown();				\
+	}											\
+	__ret;											\
+})
+
 #ifdef ASM_SUPPORTED
   struct __large_struct { unsigned long buf[100]; };
 # define __m(x) (*(struct __large_struct *)(x))
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-mips/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-mips/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-mips/uaccess.h	2004-06-15 13:41:35.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-mips/uaccess.h	2004-06-17 14:51:42.020600447 +0800
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
+#include <asm-generic/uaccess.h>
 
 /*
  * The fs value determines whether argument validity checking should be
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-ppc64/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-ppc64/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-ppc64/uaccess.h	2004-06-15 13:41:35.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-ppc64/uaccess.h	2004-06-17 14:51:42.020600447 +0800
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <asm/processor.h>
+#include <asm-generic/uaccess.h>
 
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-s390/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-s390/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-s390/uaccess.h	2004-06-15 13:41:39.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-s390/uaccess.h	2004-06-17 14:51:42.021577010 +0800
@@ -16,6 +16,7 @@
  */
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <asm-generic/uaccess.h>
 
 #define VERIFY_READ     0
 #define VERIFY_WRITE    1
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-sparc64/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-sparc64/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-sparc64/uaccess.h	2004-06-15 13:41:39.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-sparc64/uaccess.h	2004-06-17 14:51:42.021577010 +0800
@@ -14,6 +14,7 @@
 #include <asm/asi.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
+#include <asm-generic/uaccess.h>
 #endif
 
 #ifndef __ASSEMBLY__
diff -purN -X dontdiff linux-2.6.7-rc3-getdents/include/asm-x86_64/uaccess.h linux-2.6.7-rc3-getdents-user_unaligned/include/asm-x86_64/uaccess.h
--- linux-2.6.7-rc3-getdents/include/asm-x86_64/uaccess.h	2004-06-15 13:41:34.000000000 +0800
+++ linux-2.6.7-rc3-getdents-user_unaligned/include/asm-x86_64/uaccess.h	2004-06-17 14:51:42.022553572 +0800
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 #include <linux/prefetch.h>
 #include <asm/page.h>
+#include <asm-generic/uaccess.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1

  reply	other threads:[~2004-06-17 22:29 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-20 21:06 =?iso-8859-1?Q?Re:_sys_getdents64_needs_compat_wrapper_??= Arnd Bergmann
2004-06-05  0:16 ` =?iso-8859-1?Q?Re:_sys_getdents64_needs_compat_wrapper_??= Arun Sharma
2004-06-05  0:28   ` sys getdents64 needs compat wrapper ? David S. Miller
2004-06-07 21:13     ` Arun Sharma
2004-06-07 21:58       ` David S. Miller
2004-06-11 15:09       ` Arnd Bergmann
2004-06-14 18:15         ` Arun Sharma
2004-06-17 22:28           ` Arun Sharma [this message]
2004-06-17 23:36             ` Arnd Bergmann
2004-06-18  0:56               ` Arun Sharma
2004-06-18 17:05                 ` Arun Sharma
2004-06-20 21:50                   ` Arnd Bergmann
2004-06-22 18:21                     ` Arun Sharma
  -- strict thread matches above, loose matches on Subject: below --
2004-06-05 14:52 =?iso-8859-1?Q?Re:_Re:_Re:_sys_getdents64_needs_compat_wrapper_??= Arnd Bergmann
2004-06-05 18:41 ` sys getdents64 needs compat wrapper ? Andrew Morton
2004-06-05 19:31   ` David S. Miller
2004-05-20 18:32 sys_getdents64 " Arun Sharma
2004-05-20 20:58 ` David S. Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=40D21B17.4060603@intel.com \
    --to=arun.sharma@intel.com \
    --cc=akpm@osdl.org \
    --cc=arnd@arndb.de \
    --cc=davem@redhat.com \
    --cc=linux-arch@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.