Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-09-17 16:17:38.000000000 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 21:07:35.000000000 -0400 @@ -363,13 +363,15 @@ } } -static inline fd_set *target_to_host_fds(fd_set *fds, +#define FD_MASK_SIZE (FD_SETSIZE/NFDBITS) + +static inline long copy_from_user_fdset(fd_set *fds, target_long *target_fds, int n) { -#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) - return (fd_set *)target_fds; -#else int i, b; + + if( !access_ok(VERIFY_READ,target_fds,FD_MASK_SIZE) ) return -1; + if (target_fds) { FD_ZERO(fds); for(i = 0;i < n; i++) { @@ -378,22 +380,18 @@ if (b) FD_SET(i, fds); } - return fds; - } else { - return NULL; } -#endif + return 0; } -static inline void host_to_target_fds(target_long *target_fds, +static inline long copy_to_user_fdset(target_long *target_fds, fd_set *fds, int n) { -#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) - /* nothing to do */ -#else int i, nw, j, k; target_long v; + if( !access_ok(VERIFY_WRITE,target_fds,FD_MASK_SIZE) ) return -1; + if (target_fds) { nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS; k = 0; @@ -406,7 +404,7 @@ target_fds[i] = tswapl(v); } } -#endif + return 0; } #if defined(__alpha__) @@ -424,53 +422,50 @@ #endif } -static inline void host_to_target_rusage(target_ulong target_addr, +static inline long copy_to_user_rusage(struct target_rusage *target_rusage, const struct rusage *rusage) { - struct target_rusage *target_rusage; + if( !access_ok(VERIFY_WRITE,target_rusage,sizeof(*target_rusage)) ) return -1; + __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec); + __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec); + __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec); + __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec); + __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss); + __put_user(rusage->ru_ixrss, &target_rusage->ru_ixrss); + __put_user(rusage->ru_idrss, &target_rusage->ru_idrss); + __put_user(rusage->ru_isrss, &target_rusage->ru_isrss); + __put_user(rusage->ru_minflt, &target_rusage->ru_minflt); + __put_user(rusage->ru_majflt, &target_rusage->ru_majflt); + __put_user(rusage->ru_nswap, &target_rusage->ru_nswap); + __put_user(rusage->ru_inblock, &target_rusage->ru_inblock); + __put_user(rusage->ru_oublock, &target_rusage->ru_oublock); + __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd); + __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv); + __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals); + __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw); + __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw); - lock_user_struct(target_rusage, target_addr, 0); - target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); - target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); - target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); - target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec); - target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss); - target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss); - target_rusage->ru_idrss = tswapl(rusage->ru_idrss); - target_rusage->ru_isrss = tswapl(rusage->ru_isrss); - target_rusage->ru_minflt = tswapl(rusage->ru_minflt); - target_rusage->ru_majflt = tswapl(rusage->ru_majflt); - target_rusage->ru_nswap = tswapl(rusage->ru_nswap); - target_rusage->ru_inblock = tswapl(rusage->ru_inblock); - target_rusage->ru_oublock = tswapl(rusage->ru_oublock); - target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd); - target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv); - target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); - target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); - target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); - unlock_user_struct(target_rusage, target_addr, 1); + return 0; } -static inline void target_to_host_timeval(struct timeval *tv, - target_ulong target_addr) +static inline long copy_from_user_timeval(struct timeval *tv, + struct target_timeval *target_tv) { - struct target_timeval *target_tv; + if( !access_ok(VERIFY_READ,target_tv,sizeof(*target_tv)) ) return -1; + __get_user(tv->tv_sec, &target_tv->tv_sec); + __get_user(tv->tv_usec, &target_tv->tv_usec); - lock_user_struct(target_tv, target_addr, 1); - tv->tv_sec = tswapl(target_tv->tv_sec); - tv->tv_usec = tswapl(target_tv->tv_usec); - unlock_user_struct(target_tv, target_addr, 0); + return 0; } -static inline void host_to_target_timeval(target_ulong target_addr, +static inline long copy_to_user_timeval(struct target_timeval *target_tv, const struct timeval *tv) { - struct target_timeval *target_tv; + if( !access_ok(VERIFY_WRITE,target_tv,sizeof(*target_tv)) ) return -1; + __put_user(tv->tv_sec, &target_tv->tv_sec); + __put_user(tv->tv_usec, &target_tv->tv_usec); - lock_user_struct(target_tv, target_addr, 0); - target_tv->tv_sec = tswapl(tv->tv_sec); - target_tv->tv_usec = tswapl(tv->tv_usec); - unlock_user_struct(target_tv, target_addr, 1); + return 0; } @@ -486,29 +481,32 @@ int ok; if (rfd_p) { - target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1); - rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); + if( copy_from_user_fdset(&rfds, rfd_p, n) ) return -EFAULT; + rfds_ptr = &rfds; + target_rfds = rfd_p; } else { target_rfds = NULL; rfds_ptr = NULL; } if (wfd_p) { - target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1); - wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); + if( copy_from_user_fdset(&wfds, wfd_p, n) ) return -EFAULT; + wfds_ptr = &wfds; + target_wfds = wfd_p; } else { target_wfds = NULL; wfds_ptr = NULL; } if (efd_p) { - target_efds = lock_user(efd_p, sizeof(target_long) * n, 1); - efds_ptr = target_to_host_fds(&efds, target_efds, n); + if( copy_from_user_fdset(&efds, efd_p, n) ) return -EFAULT; + efds_ptr = &efds; + target_efds = efd_p; } else { target_efds = NULL; efds_ptr = NULL; } if (target_tv) { - target_to_host_timeval(&tv, target_tv); + if( copy_from_user_timeval(&tv, (struct target_timeval *)target_tv) ) return -EFAULT; tv_ptr = &tv; } else { tv_ptr = NULL; @@ -517,20 +515,14 @@ ok = !is_error(ret); if (ok) { - host_to_target_fds(target_rfds, rfds_ptr, n); - host_to_target_fds(target_wfds, wfds_ptr, n); - host_to_target_fds(target_efds, efds_ptr, n); + if( rfd_p && copy_to_user_fdset(rfd_p, &rfds, n) ) return -EFAULT; + if( wfd_p && copy_to_user_fdset(wfd_p, &wfds, n) ) return -EFAULT; + if( efd_p && copy_to_user_fdset(efd_p, &efds, n) ) return -EFAULT; if (target_tv) { - host_to_target_timeval(target_tv, &tv); + if( copy_to_user_timeval((struct target_timeval *)target_tv, &tv) ) return -EFAULT; } } - if (target_rfds) - unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0); - if (target_wfds) - unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0); - if (target_efds) - unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0); return ret; } @@ -2709,9 +2701,11 @@ { struct timeval *tvp, tv[2]; if (arg2) { - target_to_host_timeval(&tv[0], arg2); - target_to_host_timeval(&tv[1], - arg2 + sizeof (struct target_timeval)); + if( copy_from_user_timeval(&tv[0], (struct target_timeval *)arg2) ) + return -EFAULT; + if( copy_from_user_timeval(&tv[1], + (struct target_timeval *)(arg2 + sizeof (struct target_timeval))) ) + return -EFAULT; tvp = tv; } else { tvp = NULL; @@ -3174,7 +3168,7 @@ struct rusage rusage; ret = get_errno(getrusage(arg1, &rusage)); if (!is_error(ret)) { - host_to_target_rusage(arg2, &rusage); + if( copy_to_user_rusage((struct target_rusage *)arg2, &rusage) ) return -EFAULT; } } break; @@ -3183,14 +3177,14 @@ struct timeval tv; ret = get_errno(gettimeofday(&tv, NULL)); if (!is_error(ret)) { - host_to_target_timeval(arg1, &tv); + copy_to_user_timeval(arg1, &tv); } } break; case TARGET_NR_settimeofday: { struct timeval tv; - target_to_host_timeval(&tv, arg1); + copy_from_user_timeval(&tv, arg1); ret = get_errno(settimeofday(&tv, NULL)); } break; @@ -3511,19 +3505,23 @@ if (arg2) { pvalue = &value; - target_to_host_timeval(&pvalue->it_interval, - arg2); - target_to_host_timeval(&pvalue->it_value, - arg2 + sizeof(struct target_timeval)); + if( copy_from_user_timeval(&pvalue->it_interval, + (struct target_timeval *)arg2) ) + return -EFAULT; + + if( copy_from_user_timeval(&pvalue->it_value, + (struct target_timeval *)(arg2 + sizeof(struct target_timeval))) ) + return -EFAULT; + } else { pvalue = NULL; } ret = get_errno(setitimer(arg1, pvalue, &ovalue)); if (!is_error(ret) && arg3) { - host_to_target_timeval(arg3, - &ovalue.it_interval); - host_to_target_timeval(arg3 + sizeof(struct target_timeval), - &ovalue.it_value); + if( copy_to_user_timeval((struct target_timeval *)arg3, + &ovalue.it_interval) ) return -EFAULT; + if( copy_to_user_timeval((struct target_timeval *)(arg3 + sizeof(struct target_timeval)), + &ovalue.it_value) ) return -EFAULT; } } break; @@ -3533,10 +3531,10 @@ ret = get_errno(getitimer(arg1, &value)); if (!is_error(ret) && arg2) { - host_to_target_timeval(arg2, - &value.it_interval); - host_to_target_timeval(arg2 + sizeof(struct target_timeval), - &value.it_value); + if( copy_to_user_timeval((struct target_timeval *)arg2, + &value.it_interval) ) return -EFAULT; + if( copy_to_user_timeval((struct target_timeval *)(arg2 + sizeof(struct target_timeval)), + &value.it_value) ) return -EFAULT; } } break; @@ -3633,7 +3631,8 @@ if (status_ptr) tputl(status_ptr, status); if (target_rusage) { - host_to_target_rusage(target_rusage, &rusage); + if( copy_to_user_rusage(target_rusage, &rusage) ) + return -EFAULT; } } }