Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-09-19 06:28:30.000000000 -0600 +++ qemu/linux-user/syscall.c 2007-09-19 06:28:34.000000000 -0600 @@ -526,6 +526,77 @@ return 0; } +#ifdef TARGET_ARM +#define copy_to_user_statbuf64_wrapper(tsb,hsb) \ + ((((CPUARMState *)cpu_env)->eabi) \ + ? copy_to_user_statbuf64_eabi((tsb),(hsb)) \ + : copy_to_user_statbuf64((tsb),(hsb))) +#else +#define copy_to_user_statbuf64_wrapper(tsb,hsb) \ + copy_to_user_eabi_statbuf64((tsb),(hsb)) +#endif + +#ifdef TARGET_ARM +static inline long copy_to_user_statbuf64_eabi(void *gen_target_stbuf, + const struct stat *host_stbuf) +{ + struct target_eabi_stat64 *target_stbuf = (struct target_eabi_stat64 *)gen_target_stbuf; + int i; + + if( !access_ok(VERIFY_WRITE,target_stbuf,sizeof(struct target_eabi_stat64)) ) return -EFAULT; + memset(target_stbuf, 0, sizeof(struct target_eabi_stat64)); + /* use __put_user() since we just checked that the buffer is valid */ + __put_user(host_stbuf->st_dev, &target_stbuf->st_dev); + __put_user(host_stbuf->st_ino, &target_stbuf->st_ino); +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO + __put_user(host_stbuf->st_ino, &target_stbuf->__st_ino); +#endif + __put_user(host_stbuf->st_mode, &target_stbuf->st_mode); + __put_user(host_stbuf->st_nlink, &target_stbuf->st_nlink); + __put_user(host_stbuf->st_uid, &target_stbuf->st_uid); + __put_user(host_stbuf->st_gid, &target_stbuf->st_gid); + __put_user(host_stbuf->st_rdev, &target_stbuf->st_rdev); + /* XXX: better use of kernel struct */ + __put_user(host_stbuf->st_size, &target_stbuf->st_size); + __put_user(host_stbuf->st_blksize, &target_stbuf->st_blksize); + __put_user(host_stbuf->st_blocks, &target_stbuf->st_blocks); + __put_user(host_stbuf->st_atime, &target_stbuf->target_st_atime); + __put_user(host_stbuf->st_mtime, &target_stbuf->target_st_mtime); + __put_user(host_stbuf->st_ctime, &target_stbuf->target_st_ctime); + + return 0; +} +#endif + +static inline long copy_to_user_statbuf64(void *gen_target_stbuf, + const struct stat *host_stbuf) +{ + struct target_stat64 *target_stbuf = (struct target_stat64 *)gen_target_stbuf; + gemu_log("%s()\n", __func__); + if( !access_ok(VERIFY_WRITE,target_stbuf,sizeof(struct target_stat64)) ) return -EFAULT; + memset(target_stbuf, 0, sizeof(struct target_stat64)); + /* use __put_user() since we just checked that the buffer is valid */ + __put_user(host_stbuf->st_dev, &target_stbuf->st_dev); + __put_user(host_stbuf->st_ino, &target_stbuf->st_ino); +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO + __put_user(host_stbuf->st_ino, &target_stbuf->__st_ino); +#endif + __put_user(host_stbuf->st_mode, &target_stbuf->st_mode); + __put_user(host_stbuf->st_nlink, &target_stbuf->st_nlink); + __put_user(host_stbuf->st_uid, &target_stbuf->st_uid); + __put_user(host_stbuf->st_gid, &target_stbuf->st_gid); + __put_user(host_stbuf->st_rdev, &target_stbuf->st_rdev); + /* XXX: better use of kernel struct */ + __put_user(host_stbuf->st_size, &target_stbuf->st_size); + __put_user(host_stbuf->st_blksize, &target_stbuf->st_blksize); + __put_user(host_stbuf->st_blocks, &target_stbuf->st_blocks); + __put_user(host_stbuf->st_atime, &target_stbuf->target_st_atime); + __put_user(host_stbuf->st_mtime, &target_stbuf->target_st_mtime); + __put_user(host_stbuf->st_ctime, &target_stbuf->target_st_ctime); + return 0; +} + + static inline long copy_from_user_timeval(struct timeval *tv, struct target_timeval *target_tv) { @@ -4562,7 +4633,10 @@ if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT; ret = get_errno(stat(path(p), &st)); unlock_user(p, arg1, 0); - goto do_stat64; + if (!is_error(ret) + && copy_to_user_statbuf64_wrapper(arg2,&st)) + return -EFAULT; + break; #endif #ifdef TARGET_NR_lstat64 case TARGET_NR_lstat64: @@ -4570,65 +4644,18 @@ if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT; ret = get_errno(lstat(path(p), &st)); unlock_user(p, arg1, 0); - goto do_stat64; + if (!is_error(ret) + && copy_to_user_statbuf64_wrapper(arg2,&st)) + return -EFAULT; + break; #endif #ifdef TARGET_NR_fstat64 case TARGET_NR_fstat64: - { - ret = get_errno(fstat(arg1, &st)); - do_stat64: - if (!is_error(ret)) { -#ifdef TARGET_ARM - if (((CPUARMState *)cpu_env)->eabi) { - struct target_eabi_stat64 *target_st = (struct target_eabi_stat64 *)arg2; - if( !access_ok(VERIFY_WRITE,target_st,sizeof(struct target_eabi_stat64)) ) return -EFAULT; - memset(target_st, 0, sizeof(struct target_eabi_stat64)); - /* use __put_user() since we just checked that the buffer is valid */ - __put_user(st.st_dev, &target_st->st_dev); - __put_user(st.st_ino, &target_st->st_ino); -#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO - __put_user(st.st_ino, &target_st->__st_ino); -#endif - __put_user(st.st_mode, &target_st->st_mode); - __put_user(st.st_nlink, &target_st->st_nlink); - __put_user(st.st_uid, &target_st->st_uid); - __put_user(st.st_gid, &target_st->st_gid); - __put_user(st.st_rdev, &target_st->st_rdev); - /* XXX: better use of kernel struct */ - __put_user(st.st_size, &target_st->st_size); - __put_user(st.st_blksize, &target_st->st_blksize); - __put_user(st.st_blocks, &target_st->st_blocks); - __put_user(st.st_atime, &target_st->target_st_atime); - __put_user(st.st_mtime, &target_st->target_st_mtime); - __put_user(st.st_ctime, &target_st->target_st_ctime); - } else -#endif - { - struct target_stat64 *target_st = (struct target_stat64 *)arg2; - if( !access_ok(VERIFY_WRITE,target_st,sizeof(struct target_stat64)) ) return -EFAULT; - memset(target_st, 0, sizeof(struct target_stat64)); - /* use __put_user() since we just checked that the buffer is valid */ - __put_user(st.st_dev, &target_st->st_dev); - __put_user(st.st_ino, &target_st->st_ino); -#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO - __put_user(st.st_ino, &target_st->__st_ino); -#endif - __put_user(st.st_mode, &target_st->st_mode); - __put_user(st.st_nlink, &target_st->st_nlink); - __put_user(st.st_uid, &target_st->st_uid); - __put_user(st.st_gid, &target_st->st_gid); - __put_user(st.st_rdev, &target_st->st_rdev); - /* XXX: better use of kernel struct */ - __put_user(st.st_size, &target_st->st_size); - __put_user(st.st_blksize, &target_st->st_blksize); - __put_user(st.st_blocks, &target_st->st_blocks); - __put_user(st.st_atime, &target_st->target_st_atime); - __put_user(st.st_mtime, &target_st->target_st_mtime); - __put_user(st.st_ctime, &target_st->target_st_ctime); - } - } - } - break; + ret = get_errno(fstat(arg1, &st)); + if (!is_error(ret) + && copy_to_user_statbuf64_wrapper(arg2,&st)) + return -EFAULT; + break; #endif #ifdef USE_UID16 case TARGET_NR_lchown: