From: Arun Sharma <arun.sharma@intel.com>
To: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Subject: Re: =?iso-8859-1?Q?Re:_sys_getdents64_needs_compat_wrapper_??=
Date: Fri, 04 Jun 2004 17:16:09 -0700 [thread overview]
Message-ID: <40C110C9.2060900@intel.com> (raw)
In-Reply-To: <26879984$108508699040ad1d0eba5381.88033699@config20.schlund.de>
[-- Attachment #1: Type: text/plain, Size: 614 bytes --]
On 5/20/2004 2:06 PM, Arnd Bergmann wrote:
> 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.
>
Thanks for the patch. We made a few changes to the patch:
- use put_user instead of copy_to_user for simple data types.
- Couple of more instances where a 64 bit copy needs to be split into two
compat_filldir64(): __put_user(offset, &dirent->d_off)
compat_sys_getdents64(): __put_user(d_off, &lastdirent->d_off)
With these changes, we don't see unaligned faults anymore.
-Arun
[-- Attachment #2: readdir_ive.1.diff --]
[-- Type: text/plain, Size: 7576 bytes --]
diff -Nurap a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S 2004-05-10 10:32:38.000000000 +0800
+++ b/arch/ia64/ia32/ia32_entry.S 2004-06-01 16:08:09.268146780 +0800
@@ -349,7 +349,7 @@ ia32_syscall_table:
data8 sys_setfsuid /* 16-bit version */
data8 sys_setfsgid /* 16-bit version */
data8 sys_llseek /* 140 */
- data8 sys32_getdents
+ data8 compat_sys_getdents
data8 sys32_select
data8 sys_flock
data8 sys32_msync
@@ -428,7 +428,7 @@ ia32_syscall_table:
data8 sys_pivot_root
data8 sys_mincore
data8 sys_madvise
- data8 sys_getdents64 /* 220 */
+ data8 compat_sys_getdents64 /* 220 */
data8 compat_sys_fcntl64
data8 sys_ni_syscall /* reserved for TUX */
data8 sys_ni_syscall /* reserved for Security */
diff -Nurap a/fs/compat.c b/fs/compat.c
--- a/fs/compat.c 2004-05-10 10:32:29.000000000 +0800
+++ b/fs/compat.c 2004-06-01 16:08:38.474201110 +0800
@@ -34,6 +34,7 @@
#include <linux/syscalls.h>
#include <linux/ctype.h>
#include <linux/module.h>
+#include <linux/dirent.h>
#include <net/sock.h> /* siocdevprivate_ioctl */
#include <asm/uaccess.h>
@@ -794,3 +795,252 @@ asmlinkage int compat_sys_mount(char __u
return retval;
}
+#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 jj = NAME_OFFSET(dirent);
+ int reclen = COMPAT_ROUND_UP64(jj + 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, (u32 *)&dirent->d_off))
+ || (__put_user(offset >> 32, ((u32 *)&dirent->d_off) + 1)))
+ goto efault;
+ }
+ dirent = buf->current_dir;
+ if ((__put_user(ino, (u32 *)&dirent->d_ino))
+ || (__put_user(ino >> 32, ((u32 *)&dirent->d_ino) + 1)))
+ goto efault;
+ off = 0;
+ if ((__put_user(off, (u32 *)&dirent->d_off))
+ || (__put_user(off >> 32, ((u32 *)&dirent->d_off) + 1)))
+ 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, (u32 *)&lastdirent->d_off);
+ __put_user(d_off >> 32, ((u32 *)&lastdirent->d_off) + 1);
+ error = count - buf.count;
+ }
+
+out_putf:
+ fput(file);
+out:
+ return error;
+}
+#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
+
next prev parent reply other threads:[~2004-06-05 0:16 UTC|newest]
Thread overview: 14+ 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 ` Arun Sharma [this message]
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
-- strict thread matches above, loose matches on Subject: below --
2004-05-20 20:54 =?iso-8859-1?Q?Re:_sys_getdents64_needs_compat_wrapper_??= Arnd Bergmann
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=40C110C9.2060900@intel.com \
--to=arun.sharma@intel.com \
--cc=arnd@arndb.de \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox