public inbox for linux-arch@vger.kernel.org
 help / color / mirror / Atom feed
* sys_getdents64 needs compat wrapper ?
@ 2004-05-20 18:32 Arun Sharma
  2004-05-20 20:58 ` David S. Miller
  0 siblings, 1 reply; 15+ messages in thread
From: Arun Sharma @ 2004-05-20 18:32 UTC (permalink / raw)
  To: linux-arch


Running 32 bit ls on ia64 produces kernel mode unaligned faults with the attached backtrace on 2.6.6. I'm curious why this isn't a problem for other compat archs.

	-Arun

> 
> 0xa0000001000405e0 ia64_handle_unaligned
>         args (0x805f7cc, 0xe000000105aa7bc0)
>         kernel 0xa0000001000405e0 0xa000000100040d00
> 0xa00000010000e650 ia64_prepare_handle_unaligned+0x30
>         args (0x805f7cc, 0xe000000105aa7bc0)
>         kernel 0xa00000010000e620 0xa00000010000e680
> 0xa00000010000e080 ia64_leave_kernel
>         kernel 0xa00000010000e080 0xa00000010000e2e0
> 0xa000000100142480 filldir64+0xa0
>         args (0xe000000105aa7e20, 0xe0000001fa100008, 0x1, 0x0, 0x14eb01)
>         kernel 0xa0000001001423e0 0xa000000100142680
> 0xa000000100203400 ext3_readdir+0x660
>         args (0xe0000001fae79c80, 0xe000000105aa7e20, 
> 0xa0000001006bc720, 0xa000
> 0001001423e0, 0xe0000001fa100004)
>         kernel 0xa000000100202da0 0xa000000100203660
> 0xa000000100141f20 vfs_readdir+0x160
>         args (0xe0000001fae79c80, 0xa0000001006bc720, 
> 0xe000000105aa7e20, 0xa000
> 000100920000, 0xe0000001fd3968e0)
>         kernel 0xa000000100141dc0 0xa000000100141f60
> 0xa000000100142760 sys_getdents64+0xe0
>         args (0x3, 0x805f7cc, 0x4000, 0x805f7b0, 0x4015fd98)
>         kernel 0xa000000100142680 0xa000000100142820
> 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread
* =?iso-8859-1?Q?Re:_sys_getdents64_needs_compat_wrapper_??=
@ 2004-05-20 21:06 Arnd Bergmann
  2004-06-05  0:16 ` =?iso-8859-1?Q?Re:_sys_getdents64_needs_compat_wrapper_??= Arun Sharma
  0 siblings, 1 reply; 15+ messages in thread
From: Arnd Bergmann @ 2004-05-20 21:06 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Arun Sharma, linux-arch

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

Arnd Bergmann <arnd@arndb.de> schrieb am 20.05.2004, 22:54:01:
> 
> The attachment has an older (but so far untested) patch of mine
> to consolidate the syscalls from fs/readdir.c. 

Ok, so here goes the attachment (I hope). Stupid webmail...

[-- Attachment #2: compat_readdir.diff --]
[-- Type: text/plain, Size: 6293 bytes --]

===== fs/compat.c 1.24 vs edited =====
--- 1.24/fs/compat.c	Wed May 19 09:12:47 2004
+++ edited/fs/compat.c	Thu May 20 22:39:43 2004
@@ -1632,3 +1632,246 @@
 	return sys_ni_syscall();
 }
 #endif
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define COMPAT_ROUND_UP(x) (((x)+sizeof(compat_long_t)-1) & ~(sizeof(compat_long_t)-1))
+
+struct compat_old_linux_dirent {
+	compat_ulong_t	d_ino;
+	compat_ulong_t	d_offset;
+	unsigned short	d_namlen;
+	char		d_name[1];
+};
+
+struct compat_readdir_callback {
+	struct compat_old_linux_dirent __user * dirent;
+	int result;
+};
+
+static int compat_fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
+		      ino_t ino, unsigned int d_type)
+{
+	struct compat_readdir_callback * buf = __buf;
+	struct compat_old_linux_dirent __user * dirent;
+
+	if (buf->result)
+		return -EINVAL;
+	buf->result++;
+	dirent = buf->dirent;
+	if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
+			(unsigned long)(dirent->d_name + namlen + 1) -
+				(unsigned long)dirent))
+		goto efault;
+	if (	__put_user(ino, &dirent->d_ino) ||
+		__put_user(offset, &dirent->d_offset) ||
+		__put_user(namlen, &dirent->d_namlen) ||
+		__copy_to_user(dirent->d_name, name, namlen) ||
+		__put_user(0, dirent->d_name + namlen))
+		goto efault;
+	return 0;
+efault:
+	buf->result = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long compat_old_readdir(unsigned int fd,
+	struct compat_old_linux_dirent __user * dirent, unsigned int count)
+{
+	int error;
+	struct file * file;
+	struct compat_readdir_callback buf;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.result = 0;
+	buf.dirent = dirent;
+
+	error = vfs_readdir(file, compat_fillonedir, &buf);
+	if (error >= 0)
+		error = buf.result;
+
+	fput(file);
+out:
+	return error;
+}
+
+struct compat_linux_dirent {
+	compat_ulong_t	d_ino;
+	compat_ulong_t	d_off;
+	unsigned short	d_reclen;
+	char		d_name[1];
+};
+
+struct compat_getdents_callback {
+	struct compat_linux_dirent __user * current_dir;
+	struct compat_linux_dirent __user * previous;
+	int count;
+	int error;
+};
+
+static int compat_filldir(void * __buf, const char * name, int namlen, loff_t offset,
+		   ino_t ino, unsigned int d_type)
+{
+	struct compat_linux_dirent __user * dirent;
+	struct compat_getdents_callback * buf = (struct compat_getdents_callback *) __buf;
+	int reclen = COMPAT_ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent) {
+		if (__put_user(offset, &dirent->d_off))
+			goto efault;
+	}
+	dirent = buf->current_dir;
+	if (__put_user(ino, &dirent->d_ino))
+		goto efault;
+	if (__put_user(reclen, &dirent->d_reclen))
+		goto efault;
+	if (copy_to_user(dirent->d_name, name, namlen))
+		goto efault;
+	if (__put_user(0, dirent->d_name + namlen))
+		goto efault;
+	if (__put_user(d_type, (char *) dirent + reclen - 1))
+		goto efault;
+	buf->previous = dirent;
+	dirent = (void __user *)dirent + reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+efault:
+	buf->error = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long compat_sys_getdents(unsigned int fd, struct compat_linux_dirent __user * dirent, unsigned int count)
+{
+	struct file * file;
+	struct compat_linux_dirent __user * lastdirent;
+	struct compat_getdents_callback buf;
+	int error;
+
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdir(file, compat_filldir, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		if (put_user(file->f_pos, &lastdirent->d_off))
+			error = -EFAULT;
+		else
+			error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+
+#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
+#define COMPAT_ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
+
+struct compat_getdents_callback64 {
+	struct linux_dirent64 __user * current_dir;
+	struct linux_dirent64 __user * previous;
+	int count;
+	int error;
+};
+
+static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t offset,
+		     ino_t ino, unsigned int d_type)
+{
+	struct linux_dirent64 __user *dirent;
+	struct compat_getdents_callback64 * buf = (struct compat_getdents_callback64 *) __buf;
+	int reclen = COMPAT_ROUND_UP64(NAME_OFFSET(dirent) + namlen + 1);
+	u64 off;
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent) {
+		if (__put_user(offset, &dirent->d_off))
+			goto efault;
+	}
+	dirent = buf->current_dir;
+	if (__copy_to_user(&dirent->d_ino, &ino, sizeof(ino)))
+		goto efault;
+	off = 0;
+	if (__copy_to_user(&dirent->d_off, &off, sizeof(off)))
+		goto efault;
+	if (__put_user(reclen, &dirent->d_reclen))
+		goto efault;
+	if (__put_user(d_type, &dirent->d_type))
+		goto efault;
+	if (copy_to_user(dirent->d_name, name, namlen))
+		goto efault;
+	if (__put_user(0, dirent->d_name + namlen))
+		goto efault;
+	buf->previous = dirent;
+	dirent = (void __user *)dirent + reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+efault:
+	buf->error = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long compat_sys_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, unsigned int count)
+{
+	struct file * file;
+	struct linux_dirent64 __user * lastdirent;
+	struct compat_getdents_callback64 buf;
+	int error;
+
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdir(file, compat_filldir64, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		typeof(lastdirent->d_off) d_off = file->f_pos;
+		__put_user(d_off, &lastdirent->d_off);
+		error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */


^ permalink raw reply	[flat|nested] 15+ messages in thread
* =?iso-8859-1?Q?Re:_Re:_Re:_sys_getdents64_needs_compat_wrapper_??=
@ 2004-06-05 14:52 Arnd Bergmann
  2004-06-05 18:41 ` sys getdents64 needs compat wrapper ? Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Arnd Bergmann @ 2004-06-05 14:52 UTC (permalink / raw)
  To: Arun Sharma; +Cc: Arnd Bergmann, linux-arch


Arun Sharma <arun.sharma@intel.com> schrieb am 05.06.2004, 02:16:09:

> - use put_user instead of copy_to_user for simple data types.

Not that I care too much, but what's the point of this change? A single
__copy_to_user should be both faster and easier to read than two 
seperate __put_user when writing an unaligned 64 bit value.

       Arnd <><

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

end of thread, other threads:[~2004-06-22 18:21 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-20 18:32 sys_getdents64 needs compat wrapper ? Arun Sharma
2004-05-20 20:58 ` David S. Miller
  -- strict thread matches above, loose matches on Subject: below --
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
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
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

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