generic compat_sys_ustat
PATCH 1/1 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.
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.
arch/x86/ia32/ia32entry.S +1 -1
@@ -555,7 +555,7 @@ ia32_sys_call_table: .quad sys32_olduname .quad sys_umask /* 60 */ .quad sys_chroot - .quad sys32_ustat + .quad compat_sys_ustat .quad sys_dup2 .quad sys_getppid .quad sys_getpgrp /* 65 */
arch/x86/ia32/sys_ia32.c +0 -22
@@ -638,28 +638,6 @@ long sys32_uname(struct old_utsname __usreturn err ? -EFAULT :0 ; } -long sys32_ustat (unsigned dev,struct ustat32 __user *u32p) -{ -struct ustat u; -mm_segment_t seg; -int ret; - - seg =get_fs (); -set_fs (KERNEL_DS ); - ret =sys_ustat (dev, (struct ustat __user *)&u); -set_fs (seg); -if (ret <0 ) -return ret; - -if (!access_ok (VERIFY_WRITE , u32p,sizeof (struct ustat32 )) || -__put_user ((__u32 ) u.f_tfree, &u32p->f_tfree) || -__put_user ((__u32 ) u.f_tinode, &u32p->f_tfree) || -__copy_to_user (&u32p->f_fname, u.f_fname,sizeof (u.f_fname)) || -__copy_to_user (&u32p->f_fpack, u.f_fpack,sizeof (u.f_fpack))) - ret = -EFAULT ; -return ret; -} -asmlinkage long sys32_execve (char __user *name,compat_uptr_t __user *argv,compat_uptr_t __user *envp,struct pt_regs *regs) {
arch/x86/include/asm/ia32.h +0 -7
@@ -147,13 +147,6 @@ struct rt_sigframe32 {struct _fpstate_ia32 fpstate; }; -struct ustat32 { -__u32 f_tfree; -compat_ino_t f_tinode; -char f_fname[6 ]; -char f_fpack[6 ]; -}; -#define IA32_STACK_TOP IA32_PAGE_OFFSET#ifdef __KERNEL__
fs/compat.c +18 -0
@@ -378,6 +378,24 @@ out:return error; } +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u32) +{ +struct ustat *u =compat_alloc_user_space (sizeof (*u)); +int ret; + + ret =sys_ustat (dev, u); +if (ret <0 ) +return ret; + +if (!access_ok (VERIFY_WRITE , u32,sizeof (*u32)) || +__put_user ((compat_daddr_t ) u->f_tfree, &u32->f_tfree) || +__put_user ((compat_ino_t ) u->f_tinode, &u32->f_tfree) || +__copy_to_user (&u32->f_fname, u->f_fname,sizeof (u32->f_fname)) || +__copy_to_user (&u32->f_fpack, u->f_fpack,sizeof (u32->f_fpack))) +return -EFAULT ; +return 0 ; +} +static int get_compat_flock (struct flock *kfl,struct compat_flock __user *ufl) { if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
include/linux/compat.h +8 -0
@@ -125,6 +125,13 @@ struct compat_dirent {char d_name[256 ]; }; +struct compat_ustat { +compat_daddr_t f_tfree; +compat_ino_t f_tinode; +char f_fname[6 ]; +char f_fpack[6 ]; +}; + typedef union compat_sigval { compat_int_t sival_int; compat_uptr_t sival_ptr;
@@ -178,6 +185,7 @@ long compat_sys_semtimedop(int semid, st unsigned nsems, const struct compat_timespec __user *timeout);asmlinkage long compat_sys_keyctl (u32 option,u32 arg2,u32 arg3,u32 arg4,u32 arg5); +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u32); asmlinkage ssize_t compat_sys_readv(unsigned long fd,const struct compat_iovec __user *vec,unsigned long vlen);
arch/ia64/ia32/ia32_entry.S +1 -1
@@ -240,7 +240,7 @@ ia32_syscall_table: data8 sys_ni_syscall data8 sys_umask /* 60 */ data8 sys_chroot - data8 sys_ustat + data8 compat_sys_ustat data8 sys_dup2 data8 sys_getppid data8 sys_getpgrp /* 65 */
arch/mips/kernel/linux32.c +0 -34
@@ -347,40 +347,6 @@ asmlinkage int sys32_personality(unsignereturn ret; } -/* ustat compatibility */ -struct ustat32 { -compat_daddr_t f_tfree; -compat_ino_t f_tinode; -char f_fname[6 ]; -char f_fpack[6 ]; -}; - -extern asmlinkage long sys_ustat (dev_t dev,struct ustat __user * ubuf); - -asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) -{ -int err; -struct ustat tmp; -struct ustat32 tmp32; -mm_segment_t old_fs =get_fs (); - -set_fs (KERNEL_DS ); - err =sys_ustat (dev, (struct ustat __user *)&tmp); -set_fs (old_fs); - -if (err) - goto out; - -memset (&tmp32,0 ,sizeof (struct ustat32 )); - tmp32.f_tfree = tmp.f_tfree; - tmp32.f_tinode = tmp.f_tinode; - - err =copy_to_user (ubuf32, &tmp32,sizeof (struct ustat32 )) ? -EFAULT :0 ; - -out: -return err; -} - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,s32 count) {
arch/mips/kernel/scall64-n32.S +1 -1
@@ -253,7 +253,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_utime /* 6130 */ PTR sys_mknod PTR sys32_personality - PTR sys32_ustat + PTR compat_sys_ustat PTR compat_sys_statfs PTR compat_sys_fstatfs /* 6135 */ PTR sys_sysfs
arch/mips/kernel/scall64-o32.S +1 -1
@@ -267,7 +267,7 @@ sys_call_table: PTR sys_olduname PTR sys_umask /* 4060 */ PTR sys_chroot - PTR sys32_ustat + PTR compat_sys_ustat PTR sys_dup2 PTR sys_getppid PTR sys_getpgrp /* 4065 */
arch/parisc/kernel/syscall_table.S +1 -1
@@ -130,7 +130,7 @@ ENTRY_OURS(newuname) ENTRY_SAME(umask) /* 60 */ ENTRY_SAME(chroot) - ENTRY_SAME(ustat) + ENTRY_COMP(ustat) ENTRY_SAME(dup2) ENTRY_SAME(getppid) ENTRY_SAME(getpgrp) /* 65 */
arch/powerpc/include/asm/systbl.h +1 -1
@@ -65,7 +65,7 @@ SYSCALL(ni_syscall) SYSX(sys_ni_syscall,sys_olduname, sys_olduname) COMPAT_SYS_SPU(umask) SYSCALL_SPU(chroot) -SYSCALL(ustat) +COMPAT_SYS(ustat) SYSCALL_SPU(dup2) SYSCALL_SPU(getppid) SYSCALL_SPU(getpgrp)
arch/s390/kernel/compat_wrapper.S +1 -1
@@ -252,7 +252,7 @@ sys32_chroot_wrapper: sys32_ustat_wrapper: llgfr %r2,%r2 # dev_t llgtr %r3,%r3 # struct ustat * - jg sys_ustat + jg compat_sys_ustat .globl sys32_dup2_wrapper sys32_dup2_wrapper:
arch/sparc64/kernel/systbls.S +1 -1
@@ -51,7 +51,7 @@ sys_call_table32: /*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall - .word sys_quotactl, sys_set_tid_address, compat_sys_mount, sys_ustat, sys32_setxattr + .word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys32_setxattr /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
Quoted 10 lines · Christoph Hellwig
Due to a different size of
ino_tustat needs a compat handler, but currently only x86 and mips provide one. Add a genericcompat_sys_ustatand switch all architectures over to it.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 <[email protected]>
For the MIPS bits:
Ralf
Quoted 10 lines · Christoph Hellwig
Due to a different size of
ino_tustat needs a compat handler, but currently only x86 and mips provide one. Add a genericcompat_sys_ustatand switch all architectures over to it.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 <[email protected]>
Works for me (fixes the case I had), thanks.
-Eric
Quoted 7 lines · Christoph Hellwig
Due to a different size of
ino_tustat needs a compat handler, but currently only x86 and mips provide one. Add a genericcompat_sys_ustatand switch all architectures over to it.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.
...
fs/compat.c out: · line 381
Quoted 9 lines
Index:
linux-2.6/fs/compat.c
===================================================================fs/compat.c +1
-0@@ -378,6 +378,24 @@ out:return error; } +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u32)
Oh, I had also suggested that the use of "u32" here was slightly confusing, it at least made me do a double-take with the unsigned 32 bit type... not a big deal, but just thought I'd mention it.
Thanks,
-Eric
Quoted 17 lines
fs/compat.c +17
-0+{ +struct ustat *u =compat_alloc_user_space (sizeof (*u)); +int ret; + + ret =sys_ustat (dev, u); +if (ret <0 ) +return ret; + +if (!access_ok (VERIFY_WRITE , u32,sizeof (*u32)) || +__put_user ((compat_daddr_t ) u->f_tfree, &u32->f_tfree) || +__put_user ((compat_ino_t ) u->f_tinode, &u32->f_tfree) || +__copy_to_user (&u32->f_fname, u->f_fname,sizeof (u32->f_fname)) || +__copy_to_user (&u32->f_fpack, u->f_fpack,sizeof (u32->f_fpack))) +return -EFAULT ; +return 0 ; +} +
Christoph Hellwig wrote:
...
fs/compat.c out: · line 383
Quoted 11 lines
Index:
linux-2.6/fs/compat.c
===================================================================fs/compat.c +3
-0@@ -378,6 +378,24 @@ out:return error; } +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u32) +{ +struct ustat *u =compat_alloc_user_space (sizeof (*u));
Also, Pete Zaitcev pointed out to me:
Quoted 2 lines
Quoted 2 lines
Isn't this supposed to be:
struct ustat __user *u = compat_alloc_user_space(sizeof(*u));
-Eric
Quoted 11 lines · Christoph Hellwig
Due to a different size of
ino_tustat needs a compat handler, but currently only x86 and mips provide one. Add a genericcompat_sys_ustatand switch all architectures over to it.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 <[email protected]>
Interesting we've been missing this without noticing...
Quoted 7 lines · Christoph Hellwig
Due to a different size of
ino_tustat needs a compat handler, but currently only x86 and mips provide one. Add a genericcompat_sys_ustatand switch all architectures over to it.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.
Updayed version fixing the naming issues Eric pointed out and some mess with kernel vs user pointers fixed by sparse.
arch/x86/ia32/ia32entry.S +1 -1
@@ -555,7 +555,7 @@ ia32_sys_call_table: .quad sys32_olduname .quad sys_umask /* 60 */ .quad sys_chroot - .quad sys32_ustat + .quad compat_sys_ustat .quad sys_dup2 .quad sys_getppid .quad sys_getpgrp /* 65 */
arch/x86/ia32/sys_ia32.c +0 -22
@@ -638,28 +638,6 @@ long sys32_uname(struct old_utsname __usreturn err ? -EFAULT :0 ; } -long sys32_ustat (unsigned dev,struct ustat32 __user *u32p) -{ -struct ustat u; -mm_segment_t seg; -int ret; - - seg =get_fs (); -set_fs (KERNEL_DS ); - ret =sys_ustat (dev, (struct ustat __user *)&u); -set_fs (seg); -if (ret <0 ) -return ret; - -if (!access_ok (VERIFY_WRITE , u32p,sizeof (struct ustat32 )) || -__put_user ((__u32 ) u.f_tfree, &u32p->f_tfree) || -__put_user ((__u32 ) u.f_tinode, &u32p->f_tfree) || -__copy_to_user (&u32p->f_fname, u.f_fname,sizeof (u.f_fname)) || -__copy_to_user (&u32p->f_fpack, u.f_fpack,sizeof (u.f_fpack))) - ret = -EFAULT ; -return ret; -} -asmlinkage long sys32_execve (char __user *name,compat_uptr_t __user *argv,compat_uptr_t __user *envp,struct pt_regs *regs) {
arch/x86/include/asm/ia32.h +0 -7
@@ -147,13 +147,6 @@ struct rt_sigframe32 {struct _fpstate_ia32 fpstate; }; -struct ustat32 { -__u32 f_tfree; -compat_ino_t f_tinode; -char f_fname[6 ]; -char f_fpack[6 ]; -}; -#define IA32_STACK_TOP IA32_PAGE_OFFSET#ifdef __KERNEL__
fs/compat.c +18 -0
@@ -378,6 +378,24 @@ out:return error; } +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *cu) +{ +struct ustat __user *u =compat_alloc_user_space (sizeof (*u)); +int ret; + + ret =sys_ustat (dev, u); +if (ret <0 ) +return ret; + +if (!access_ok (VERIFY_WRITE , cu,sizeof (*cu)) || +__copy_in_user (&cu->f_tfree, &u->f_tfree,sizeof (compat_daddr_t)) || +__copy_in_user (&cu->f_tinode, &u->f_tinode,sizeof (compat_ino_t)) || +__copy_in_user (&cu->f_fname, u->f_fname,sizeof (cu->f_fname)) || +__copy_in_user (&cu->f_fpack, u->f_fpack,sizeof (cu->f_fpack))) +return -EFAULT ; +return 0 ; +} +static int get_compat_flock (struct flock *kfl,struct compat_flock __user *ufl) { if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
include/linux/compat.h +8 -0
@@ -125,6 +125,13 @@ struct compat_dirent {char d_name[256 ]; }; +struct compat_ustat { +compat_daddr_t f_tfree; +compat_ino_t f_tinode; +char f_fname[6 ]; +char f_fpack[6 ]; +}; + typedef union compat_sigval { compat_int_t sival_int; compat_uptr_t sival_ptr;
@@ -178,6 +185,7 @@ long compat_sys_semtimedop(int semid, st unsigned nsems, const struct compat_timespec __user *timeout);asmlinkage long compat_sys_keyctl (u32 option,u32 arg2,u32 arg3,u32 arg4,u32 arg5); +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u32); asmlinkage ssize_t compat_sys_readv(unsigned long fd,const struct compat_iovec __user *vec,unsigned long vlen);
arch/ia64/ia32/ia32_entry.S +1 -1
@@ -240,7 +240,7 @@ ia32_syscall_table: data8 sys_ni_syscall data8 sys_umask /* 60 */ data8 sys_chroot - data8 sys_ustat + data8 compat_sys_ustat data8 sys_dup2 data8 sys_getppid data8 sys_getpgrp /* 65 */
arch/mips/kernel/linux32.c +0 -34
@@ -347,40 +347,6 @@ asmlinkage int sys32_personality(unsignereturn ret; } -/* ustat compatibility */ -struct ustat32 { -compat_daddr_t f_tfree; -compat_ino_t f_tinode; -char f_fname[6 ]; -char f_fpack[6 ]; -}; - -extern asmlinkage long sys_ustat (dev_t dev,struct ustat __user * ubuf); - -asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) -{ -int err; -struct ustat tmp; -struct ustat32 tmp32; -mm_segment_t old_fs =get_fs (); - -set_fs (KERNEL_DS ); - err =sys_ustat (dev, (struct ustat __user *)&tmp); -set_fs (old_fs); - -if (err) - goto out; - -memset (&tmp32,0 ,sizeof (struct ustat32 )); - tmp32.f_tfree = tmp.f_tfree; - tmp32.f_tinode = tmp.f_tinode; - - err =copy_to_user (ubuf32, &tmp32,sizeof (struct ustat32 )) ? -EFAULT :0 ; - -out: -return err; -} - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,s32 count) {
arch/mips/kernel/scall64-n32.S +1 -1
@@ -253,7 +253,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_utime /* 6130 */ PTR sys_mknod PTR sys32_personality - PTR sys32_ustat + PTR compat_sys_ustat PTR compat_sys_statfs PTR compat_sys_fstatfs /* 6135 */ PTR sys_sysfs
arch/mips/kernel/scall64-o32.S +1 -1
@@ -267,7 +267,7 @@ sys_call_table: PTR sys_olduname PTR sys_umask /* 4060 */ PTR sys_chroot - PTR sys32_ustat + PTR compat_sys_ustat PTR sys_dup2 PTR sys_getppid PTR sys_getpgrp /* 4065 */
arch/parisc/kernel/syscall_table.S +1 -1
@@ -130,7 +130,7 @@ ENTRY_OURS(newuname) ENTRY_SAME(umask) /* 60 */ ENTRY_SAME(chroot) - ENTRY_SAME(ustat) + ENTRY_COMP(ustat) ENTRY_SAME(dup2) ENTRY_SAME(getppid) ENTRY_SAME(getpgrp) /* 65 */
arch/powerpc/include/asm/systbl.h +1 -1
@@ -65,7 +65,7 @@ SYSCALL(ni_syscall) SYSX(sys_ni_syscall,sys_olduname, sys_olduname) COMPAT_SYS_SPU(umask) SYSCALL_SPU(chroot) -SYSCALL(ustat) +COMPAT_SYS(ustat) SYSCALL_SPU(dup2) SYSCALL_SPU(getppid) SYSCALL_SPU(getpgrp)
arch/s390/kernel/compat_wrapper.S +1 -1
@@ -252,7 +252,7 @@ sys32_chroot_wrapper: sys32_ustat_wrapper: llgfr %r2,%r2 # dev_t llgtr %r3,%r3 # struct ustat * - jg sys_ustat + jg compat_sys_ustat .globl sys32_dup2_wrapper sys32_dup2_wrapper:
arch/sparc64/kernel/systbls.S +1 -1
@@ -51,7 +51,7 @@ sys_call_table32: /*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall - .word sys_quotactl, sys_set_tid_address, compat_sys_mount, sys_ustat, sys32_setxattr + .word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys32_setxattr /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
Quoted 7 lines · Christoph Hellwig
fs/compat.c +7
-0+asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *cu) +{ + struct ustat __user *u = compat_alloc_user_space(sizeof(*u)); + int ret; + + ret = sys_ustat(dev, u); + if (ret < 0)
fs/compat.c out: · line 397
Quoted 10 lines
fs/compat.c +10
-0+ return ret; + + if (!access_ok(VERIFY_WRITE, cu, sizeof(*cu)) || + __copy_in_user(&cu->f_tfree, &u->f_tfree, sizeof(compat_daddr_t)) || + __copy_in_user(&cu->f_tinode, &u->f_tinode, sizeof(compat_ino_t)) || + __copy_in_user(&cu->f_fname, u->f_fname, sizeof(cu->f_fname)) || + __copy_in_user(&cu->f_fpack, u->f_fpack, sizeof(cu->f_fpack))) + return -EFAULT; + return 0; +}
The __copy_in_user for f_tinode and f_tfree only work on little-endian systems, or if the sizes are the same for 32 and 64 bit. f_fname and f_fpack don't need to be copied at all, as they are always zero-filled in the current implementation (which is unlikely to ever change).
Also, this function is not much simpler than the actual sys_ustat function, so have you considered implementing it directly like this?
asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user * ubuf)
{
struct super_block *s;
struct compat_ustat tmp;
struct kstatfs sbuf;
int err = -EINVAL;
s = user_get_super(new_decode_dev(dev));
if (s == NULL)
goto out;
err = vfs_statfs(s->s_root, &sbuf);
drop_super(s);
if (err)
goto out;
memset(&tmp,0,sizeof(struct compat_ustat));
tmp.f_tfree = sbuf.f_bfree;
tmp.f_tinode = sbuf.f_ffree;
err = copy_to_user(ubuf,&tmp,sizeof(struct compat_ustat)) ? -EFAULT : 0;
out:
return err;
}This code is directly lifted from the sys_ustat implementation, with a few compat_ added in the right places.
Arnd <><
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.
arch/x86/ia32/ia32entry.S +1 -1
@@ -555,7 +555,7 @@ ia32_sys_call_table: .quad sys32_olduname .quad sys_umask /* 60 */ .quad sys_chroot - .quad sys32_ustat + .quad compat_sys_ustat .quad sys_dup2 .quad sys_getppid .quad sys_getpgrp /* 65 */
arch/x86/ia32/sys_ia32.c +0 -22
@@ -638,28 +638,6 @@ long sys32_uname(struct old_utsname __usreturn err ? -EFAULT :0 ; } -long sys32_ustat (unsigned dev,struct ustat32 __user *u32p) -{ -struct ustat u; -mm_segment_t seg; -int ret; - - seg =get_fs (); -set_fs (KERNEL_DS ); - ret =sys_ustat (dev, (struct ustat __user *)&u); -set_fs (seg); -if (ret <0 ) -return ret; - -if (!access_ok (VERIFY_WRITE , u32p,sizeof (struct ustat32 )) || -__put_user ((__u32 ) u.f_tfree, &u32p->f_tfree) || -__put_user ((__u32 ) u.f_tinode, &u32p->f_tfree) || -__copy_to_user (&u32p->f_fname, u.f_fname,sizeof (u.f_fname)) || -__copy_to_user (&u32p->f_fpack, u.f_fpack,sizeof (u.f_fpack))) - ret = -EFAULT ; -return ret; -} -asmlinkage long sys32_execve (char __user *name,compat_uptr_t __user *argv,compat_uptr_t __user *envp,struct pt_regs *regs) {
fs/compat.c +28 -0
@@ -378,6 +378,34 @@ out:return error; } +/* +* This is a copy of sys_ustat, just dealing with a structure layout. +* Given how simple this syscall is that apporach is more maintainable +* than the various conversion hacks. +*/ +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u) +{ +struct super_block *sb; +struct compat_ustat tmp; +struct kstatfs sbuf; +int err; + + sb =user_get_super (new_decode_dev (dev)); +if (!sb) +return -EINVAL ; + err =vfs_statfs (sb->s_root, &sbuf); +drop_super (sb); +if (err) +return err; + +memset (&tmp,0 ,sizeof (struct compat_ustat )); + tmp.f_tfree = sbuf.f_bfree; + tmp.f_tinode = sbuf.f_ffree; +if (copy_to_user (u, &tmp,sizeof (struct compat_ustat ))) +return -EFAULT ; +return 0 ; +} +static int get_compat_flock (struct flock *kfl,struct compat_flock __user *ufl) { if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
include/linux/compat.h +8 -0
@@ -125,6 +125,13 @@ struct compat_dirent {char d_name[256 ]; }; +struct compat_ustat { +compat_daddr_t f_tfree; +compat_ino_t f_tinode; +char f_fname[6 ]; +char f_fpack[6 ]; +}; + typedef union compat_sigval { compat_int_t sival_int; compat_uptr_t sival_ptr;
@@ -178,6 +185,7 @@ long compat_sys_semtimedop(int semid, st unsigned nsems, const struct compat_timespec __user *timeout);asmlinkage long compat_sys_keyctl (u32 option,u32 arg2,u32 arg3,u32 arg4,u32 arg5); +asmlinkage long compat_sys_ustat (unsigned dev,struct compat_ustat __user *u32); asmlinkage ssize_t compat_sys_readv(unsigned long fd,const struct compat_iovec __user *vec,unsigned long vlen);
arch/ia64/ia32/ia32_entry.S +1 -1
@@ -240,7 +240,7 @@ ia32_syscall_table: data8 sys_ni_syscall data8 sys_umask /* 60 */ data8 sys_chroot - data8 sys_ustat + data8 compat_sys_ustat data8 sys_dup2 data8 sys_getppid data8 sys_getpgrp /* 65 */
arch/mips/kernel/linux32.c +0 -34
@@ -347,40 +347,6 @@ asmlinkage int sys32_personality(unsignereturn ret; } -/* ustat compatibility */ -struct ustat32 { -compat_daddr_t f_tfree; -compat_ino_t f_tinode; -char f_fname[6 ]; -char f_fpack[6 ]; -}; - -extern asmlinkage long sys_ustat (dev_t dev,struct ustat __user * ubuf); - -asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) -{ -int err; -struct ustat tmp; -struct ustat32 tmp32; -mm_segment_t old_fs =get_fs (); - -set_fs (KERNEL_DS ); - err =sys_ustat (dev, (struct ustat __user *)&tmp); -set_fs (old_fs); - -if (err) - goto out; - -memset (&tmp32,0 ,sizeof (struct ustat32 )); - tmp32.f_tfree = tmp.f_tfree; - tmp32.f_tinode = tmp.f_tinode; - - err =copy_to_user (ubuf32, &tmp32,sizeof (struct ustat32 )) ? -EFAULT :0 ; - -out: -return err; -} - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,s32 count) {
arch/mips/kernel/scall64-n32.S +1 -1
@@ -253,7 +253,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_utime /* 6130 */ PTR sys_mknod PTR sys32_personality - PTR sys32_ustat + PTR compat_sys_ustat PTR compat_sys_statfs PTR compat_sys_fstatfs /* 6135 */ PTR sys_sysfs
arch/mips/kernel/scall64-o32.S +1 -1
@@ -267,7 +267,7 @@ sys_call_table: PTR sys_olduname PTR sys_umask /* 4060 */ PTR sys_chroot - PTR sys32_ustat + PTR compat_sys_ustat PTR sys_dup2 PTR sys_getppid PTR sys_getpgrp /* 4065 */
arch/parisc/kernel/syscall_table.S +1 -1
@@ -130,7 +130,7 @@ ENTRY_OURS(newuname) ENTRY_SAME(umask) /* 60 */ ENTRY_SAME(chroot) - ENTRY_SAME(ustat) + ENTRY_COMP(ustat) ENTRY_SAME(dup2) ENTRY_SAME(getppid) ENTRY_SAME(getpgrp) /* 65 */
arch/powerpc/include/asm/systbl.h +1 -1
@@ -65,7 +65,7 @@ SYSCALL(ni_syscall) SYSX(sys_ni_syscall,sys_olduname, sys_olduname) COMPAT_SYS_SPU(umask) SYSCALL_SPU(chroot) -SYSCALL(ustat) +COMPAT_SYS(ustat) SYSCALL_SPU(dup2) SYSCALL_SPU(getppid) SYSCALL_SPU(getpgrp)
arch/s390/kernel/compat_wrapper.S +1 -1
@@ -252,7 +252,7 @@ sys32_chroot_wrapper: sys32_ustat_wrapper: llgfr %r2,%r2 # dev_t llgtr %r3,%r3 # struct ustat * - jg sys_ustat + jg compat_sys_ustat .globl sys32_dup2_wrapper sys32_dup2_wrapper:
arch/sparc64/kernel/systbls.S +1 -1
@@ -51,7 +51,7 @@ sys_call_table32: /*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall - .word sys_quotactl, sys_set_tid_address, compat_sys_mount, sys_ustat, sys32_setxattr + .word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys32_setxattr /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
arch/x86/include/asm/ia32.h +0 -7
@@ -147,13 +147,6 @@ struct rt_sigframe32 {struct _fpstate_ia32 fpstate; }; -struct ustat32 { -__u32 f_tfree; -compat_ino_t f_tinode; -char f_fname[6 ]; -char f_fpack[6 ]; -}; -#define IA32_STACK_TOP IA32_PAGE_OFFSET#ifdef __KERNEL__
Quoted 11 lines · Christoph Hellwig
Due to a different size of
ino_tustat needs a compat handler, but currently only x86 and mips provide one. Add a genericcompat_sys_ustatand switch all architectures over to it. Instead of doing various user copy hackscompat_sys_ustatjust reimplementssys_ustatas 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 <[email protected]>
Looks like this got lost?
-Eric
Quoted 14 lines
Index:
linux-2.6/arch/x86/ia32/ia32entry.S
===================================================================arch/x86/ia32/ia32entry.S +1
-1@@ -555,7 +555,7 @@ ia32_sys_call_table: .quad sys32_olduname .quad sys_umask /* 60 */ .quad sys_chroot - .quad sys32_ustat + .quad compat_sys_ustat .quad sys_dup2 .quad sys_getppid .quad sys_getpgrp /* 65 */
....
Quoted 2 lines · Eric Sandeen
Looks like this got lost?
Al promised to take it via the vfs queue, so hopefully it 'll go in for the next releases..