aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-11-28 04:09:09 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2009-03-27 14:43:57 -0400
commit2b1c6bd77d4e6a727ffac8630cd154b2144b751a (patch)
treeffc4237dbeed66492124ef2ccecf48db0767531a
parentec1ab0abde0af586a59541ad71841f022dcac3e7 (diff)
generic compat_sys_ustat
Due to a different size of ino_t ustat needs a compat handler, but currently only x86 and mips provide one. Add a generic compat_sys_ustat and switch all architectures over to it. Instead of doing various user copy hacks compat_sys_ustat just reimplements sys_ustat as it's trivial. This was suggested by Arnd Bergmann. Found by Eric Sandeen when running xfstests/017 on ppc64, which causes stack smashing warnings on RHEL/Fedora due to the too large amount of data writen by the syscall. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/mips/kernel/linux32.c34
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/parisc/kernel/syscall_table.S2
-rw-r--r--arch/powerpc/include/asm/systbl.h2
-rw-r--r--arch/s390/kernel/compat_wrapper.S2
-rw-r--r--arch/x86/ia32/ia32entry.S2
-rw-r--r--arch/x86/ia32/sys_ia32.c22
-rw-r--r--arch/x86/include/asm/ia32.h7
-rw-r--r--arch/x86/include/asm/sys_ia32.h2
-rw-r--r--fs/compat.c28
-rw-r--r--include/linux/compat.h8
13 files changed, 43 insertions, 72 deletions
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index a46f8395e9a5..af9405cd70e5 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -240,7 +240,7 @@ ia32_syscall_table:
240 data8 sys_ni_syscall 240 data8 sys_ni_syscall
241 data8 sys_umask /* 60 */ 241 data8 sys_umask /* 60 */
242 data8 sys_chroot 242 data8 sys_chroot
243 data8 sys_ustat 243 data8 compat_sys_ustat
244 data8 sys_dup2 244 data8 sys_dup2
245 data8 sys_getppid 245 data8 sys_getppid
246 data8 sys_getpgrp /* 65 */ 246 data8 sys_getpgrp /* 65 */
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 1a86f84fa947..784859cedef7 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -356,40 +356,6 @@ SYSCALL_DEFINE1(32_personality, unsigned long, personality)
356 return ret; 356 return ret;
357} 357}
358 358
359/* ustat compatibility */
360struct ustat32 {
361 compat_daddr_t f_tfree;
362 compat_ino_t f_tinode;
363 char f_fname[6];
364 char f_fpack[6];
365};
366
367extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
368
369SYSCALL_DEFINE2(32_ustat, dev_t, dev, struct ustat32 __user *, ubuf32)
370{
371 int err;
372 struct ustat tmp;
373 struct ustat32 tmp32;
374 mm_segment_t old_fs = get_fs();
375
376 set_fs(KERNEL_DS);
377 err = sys_ustat(dev, (struct ustat __user *)&tmp);
378 set_fs(old_fs);
379
380 if (err)
381 goto out;
382
383 memset(&tmp32, 0, sizeof(struct ustat32));
384 tmp32.f_tfree = tmp.f_tfree;
385 tmp32.f_tinode = tmp.f_tinode;
386
387 err = copy_to_user(ubuf32, &tmp32, sizeof(struct ustat32)) ? -EFAULT : 0;
388
389out:
390 return err;
391}
392
393SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd, 359SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd,
394 compat_off_t __user *, offset, s32, count) 360 compat_off_t __user *, offset, s32, count)
395{ 361{
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 7438e92f8a01..f61d6b0e5731 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -253,7 +253,7 @@ EXPORT(sysn32_call_table)
253 PTR compat_sys_utime /* 6130 */ 253 PTR compat_sys_utime /* 6130 */
254 PTR sys_mknod 254 PTR sys_mknod
255 PTR sys_32_personality 255 PTR sys_32_personality
256 PTR sys_32_ustat 256 PTR compat_sys_ustat
257 PTR compat_sys_statfs 257 PTR compat_sys_statfs
258 PTR compat_sys_fstatfs /* 6135 */ 258 PTR compat_sys_fstatfs /* 6135 */
259 PTR sys_sysfs 259 PTR sys_sysfs
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index b0fef4ff9827..60997f1f69d4 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -265,7 +265,7 @@ sys_call_table:
265 PTR sys_olduname 265 PTR sys_olduname
266 PTR sys_umask /* 4060 */ 266 PTR sys_umask /* 4060 */
267 PTR sys_chroot 267 PTR sys_chroot
268 PTR sys_32_ustat 268 PTR compat_sys_ustat
269 PTR sys_dup2 269 PTR sys_dup2
270 PTR sys_getppid 270 PTR sys_getppid
271 PTR sys_getpgrp /* 4065 */ 271 PTR sys_getpgrp /* 4065 */
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 303d2b647e41..03b9a01bc16c 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -130,7 +130,7 @@
130 ENTRY_OURS(newuname) 130 ENTRY_OURS(newuname)
131 ENTRY_SAME(umask) /* 60 */ 131 ENTRY_SAME(umask) /* 60 */
132 ENTRY_SAME(chroot) 132 ENTRY_SAME(chroot)
133 ENTRY_SAME(ustat) 133 ENTRY_COMP(ustat)
134 ENTRY_SAME(dup2) 134 ENTRY_SAME(dup2)
135 ENTRY_SAME(getppid) 135 ENTRY_SAME(getppid)
136 ENTRY_SAME(getpgrp) /* 65 */ 136 ENTRY_SAME(getpgrp) /* 65 */
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 72353f6070a4..fe166491e9dc 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -65,7 +65,7 @@ SYSCALL(ni_syscall)
65SYSX(sys_ni_syscall,sys_olduname, sys_olduname) 65SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
66COMPAT_SYS_SPU(umask) 66COMPAT_SYS_SPU(umask)
67SYSCALL_SPU(chroot) 67SYSCALL_SPU(chroot)
68SYSCALL(ustat) 68COMPAT_SYS(ustat)
69SYSCALL_SPU(dup2) 69SYSCALL_SPU(dup2)
70SYSCALL_SPU(getppid) 70SYSCALL_SPU(getppid)
71SYSCALL_SPU(getpgrp) 71SYSCALL_SPU(getpgrp)
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 62c706eb0de6..87cf5a79a351 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -252,7 +252,7 @@ sys32_chroot_wrapper:
252sys32_ustat_wrapper: 252sys32_ustat_wrapper:
253 llgfr %r2,%r2 # dev_t 253 llgfr %r2,%r2 # dev_t
254 llgtr %r3,%r3 # struct ustat * 254 llgtr %r3,%r3 # struct ustat *
255 jg sys_ustat 255 jg compat_sys_ustat
256 256
257 .globl sys32_dup2_wrapper 257 .globl sys32_dup2_wrapper
258sys32_dup2_wrapper: 258sys32_dup2_wrapper:
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 5a0d76dc56a4..8ef8876666b2 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -557,7 +557,7 @@ ia32_sys_call_table:
557 .quad sys32_olduname 557 .quad sys32_olduname
558 .quad sys_umask /* 60 */ 558 .quad sys_umask /* 60 */
559 .quad sys_chroot 559 .quad sys_chroot
560 .quad sys32_ustat 560 .quad compat_sys_ustat
561 .quad sys_dup2 561 .quad sys_dup2
562 .quad sys_getppid 562 .quad sys_getppid
563 .quad sys_getpgrp /* 65 */ 563 .quad sys_getpgrp /* 65 */
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 6c0d7f6231af..efac92fd1efb 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -638,28 +638,6 @@ long sys32_uname(struct old_utsname __user *name)
638 return err ? -EFAULT : 0; 638 return err ? -EFAULT : 0;
639} 639}
640 640
641long sys32_ustat(unsigned dev, struct ustat32 __user *u32p)
642{
643 struct ustat u;
644 mm_segment_t seg;
645 int ret;
646
647 seg = get_fs();
648 set_fs(KERNEL_DS);
649 ret = sys_ustat(dev, (struct ustat __user *)&u);
650 set_fs(seg);
651 if (ret < 0)
652 return ret;
653
654 if (!access_ok(VERIFY_WRITE, u32p, sizeof(struct ustat32)) ||
655 __put_user((__u32) u.f_tfree, &u32p->f_tfree) ||
656 __put_user((__u32) u.f_tinode, &u32p->f_tfree) ||
657 __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) ||
658 __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack)))
659 ret = -EFAULT;
660 return ret;
661}
662
663asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, 641asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
664 compat_uptr_t __user *envp, struct pt_regs *regs) 642 compat_uptr_t __user *envp, struct pt_regs *regs)
665{ 643{
diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
index 50ca486fd88c..1f7e62517284 100644
--- a/arch/x86/include/asm/ia32.h
+++ b/arch/x86/include/asm/ia32.h
@@ -129,13 +129,6 @@ typedef struct compat_siginfo {
129 } _sifields; 129 } _sifields;
130} compat_siginfo_t; 130} compat_siginfo_t;
131 131
132struct ustat32 {
133 __u32 f_tfree;
134 compat_ino_t f_tinode;
135 char f_fname[6];
136 char f_fpack[6];
137};
138
139#define IA32_STACK_TOP IA32_PAGE_OFFSET 132#define IA32_STACK_TOP IA32_PAGE_OFFSET
140 133
141#ifdef __KERNEL__ 134#ifdef __KERNEL__
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index ffb08be2a530..72a6dcd1299b 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -70,8 +70,6 @@ struct old_utsname;
70asmlinkage long sys32_olduname(struct oldold_utsname __user *); 70asmlinkage long sys32_olduname(struct oldold_utsname __user *);
71long sys32_uname(struct old_utsname __user *); 71long sys32_uname(struct old_utsname __user *);
72 72
73long sys32_ustat(unsigned, struct ustat32 __user *);
74
75asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *, 73asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *,
76 compat_uptr_t __user *, struct pt_regs *); 74 compat_uptr_t __user *, struct pt_regs *);
77asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); 75asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
diff --git a/fs/compat.c b/fs/compat.c
index d0145ca27572..4e0db94b5353 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -378,6 +378,34 @@ out:
378 return error; 378 return error;
379} 379}
380 380
381/*
382 * This is a copy of sys_ustat, just dealing with a structure layout.
383 * Given how simple this syscall is that apporach is more maintainable
384 * than the various conversion hacks.
385 */
386asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u)
387{
388 struct super_block *sb;
389 struct compat_ustat tmp;
390 struct kstatfs sbuf;
391 int err;
392
393 sb = user_get_super(new_decode_dev(dev));
394 if (!sb)
395 return -EINVAL;
396 err = vfs_statfs(sb->s_root, &sbuf);
397 drop_super(sb);
398 if (err)
399 return err;
400
401 memset(&tmp, 0, sizeof(struct compat_ustat));
402 tmp.f_tfree = sbuf.f_bfree;
403 tmp.f_tinode = sbuf.f_ffree;
404 if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
405 return -EFAULT;
406 return 0;
407}
408
381static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 409static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
382{ 410{
383 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || 411 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 3fd2194ff573..b880864672de 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -125,6 +125,13 @@ struct compat_dirent {
125 char d_name[256]; 125 char d_name[256];
126}; 126};
127 127
128struct compat_ustat {
129 compat_daddr_t f_tfree;
130 compat_ino_t f_tinode;
131 char f_fname[6];
132 char f_fpack[6];
133};
134
128typedef union compat_sigval { 135typedef union compat_sigval {
129 compat_int_t sival_int; 136 compat_int_t sival_int;
130 compat_uptr_t sival_ptr; 137 compat_uptr_t sival_ptr;
@@ -178,6 +185,7 @@ long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
178 unsigned nsems, const struct compat_timespec __user *timeout); 185 unsigned nsems, const struct compat_timespec __user *timeout);
179asmlinkage long compat_sys_keyctl(u32 option, 186asmlinkage long compat_sys_keyctl(u32 option,
180 u32 arg2, u32 arg3, u32 arg4, u32 arg5); 187 u32 arg2, u32 arg3, u32 arg4, u32 arg5);
188asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);
181 189
182asmlinkage ssize_t compat_sys_readv(unsigned long fd, 190asmlinkage ssize_t compat_sys_readv(unsigned long fd,
183 const struct compat_iovec __user *vec, unsigned long vlen); 191 const struct compat_iovec __user *vec, unsigned long vlen);