Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-11-20 13:21:38.000000000 -0700 +++ qemu/linux-user/syscall.c 2007-11-20 13:51:28.000000000 -0700 @@ -3026,28 +3026,36 @@ } #endif -static inline abi_long target_to_host_timespec(struct timespec *host_ts, - abi_ulong target_addr) +static inline abi_long copy_from_user_timespec(struct timespec *host_ts, + abi_ulong target_ts_addr) { struct target_timespec *target_ts; - if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) + if (!lock_user_struct(VERIFY_READ, target_ts, target_ts_addr, 1)) return -TARGET_EFAULT; - host_ts->tv_sec = tswapl(target_ts->tv_sec); - host_ts->tv_nsec = tswapl(target_ts->tv_nsec); - unlock_user_struct(target_ts, target_addr, 0); + + __get_user(host_ts->tv_sec, &target_ts->tv_sec); + __get_user(host_ts->tv_nsec, &target_ts->tv_nsec); + + unlock_user_struct(target_ts, target_ts_addr, 0); + + return 0; } -static inline abi_long host_to_target_timespec(abi_ulong target_addr, - struct timespec *host_ts) +static inline abi_long copy_to_user_timespec(abi_ulong target_ts_addr, + const struct timespec *host_ts) { struct target_timespec *target_ts; - if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) + if (!lock_user_struct(VERIFY_WRITE, target_ts, target_ts_addr, 0)) return -TARGET_EFAULT; - target_ts->tv_sec = tswapl(host_ts->tv_sec); - target_ts->tv_nsec = tswapl(host_ts->tv_nsec); - unlock_user_struct(target_ts, target_addr, 1); + + __put_user(host_ts->tv_sec, &target_ts->tv_sec); + __put_user(host_ts->tv_nsec, &target_ts->tv_nsec); + + unlock_user_struct(target_ts, target_ts_addr, 1); + + return 0; } /* do_syscall() should always have a single exit point at the end so @@ -3855,7 +3863,8 @@ unlock_user(p, arg1, 0); if (arg3) { puts = &uts; - target_to_host_timespec(puts, arg3); + if (copy_from_user_timespec(puts, arg3)) + goto efault; } else { puts = NULL; } @@ -4807,17 +4816,21 @@ struct timespec ts; ret = get_errno(sched_rr_get_interval(arg1, &ts)); if (!is_error(ret)) { - host_to_target_timespec(arg2, &ts); + if (copy_to_user_timespec(arg2, &ts)) + goto efault; } } break; case TARGET_NR_nanosleep: { struct timespec req, rem; - target_to_host_timespec(&req, arg1); + + if (copy_from_user_timespec(&req, arg1)) + goto efault; ret = get_errno(nanosleep(&req, &rem)); - if (is_error(ret) && arg2) { - host_to_target_timespec(arg2, &rem); + if (!is_error(ret) && arg2) { + if (copy_to_user_timespec(arg2, &rem)) + goto efault; } } break; @@ -5491,7 +5504,8 @@ struct timespec ts; ret = get_errno(clock_gettime(arg1, &ts)); if (!is_error(ret)) { - host_to_target_timespec(arg2, &ts); + if (copy_to_user_timespec(arg2, &ts)) + goto efault; } break; } @@ -5502,7 +5516,8 @@ struct timespec ts; ret = get_errno(clock_getres(arg1, &ts)); if (!is_error(ret)) { - host_to_target_timespec(arg2, &ts); + if (copy_to_user_timespec(arg2, &ts)) + goto efault; } break; } @@ -5535,8 +5550,10 @@ case TARGET_NR_utimensat: { struct timespec ts[2]; - target_to_host_timespec(ts, arg3); - target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); + + if (copy_from_user_timespec(ts, arg3) + || copy_from_user_timespec(ts+1, arg3+sizeof(struct target_timespec))) + goto efault; if (!arg2) ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4)); else {