Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/syscall-defs.h | 1 + linux-user/syscall-file.inc.c | 96 +++++++++++++++++++++++++++++++ linux-user/syscall.c | 103 ---------------------------------- linux-user/strace.list | 3 - 4 files changed, 97 insertions(+), 106 deletions(-)
diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h index 01143414c7..c179f69d9f 100644 --- a/linux-user/syscall-defs.h +++ b/linux-user/syscall-defs.h @@ -180,6 +180,7 @@ SYSCALL_DEF_FULL(preadv, .impl = impl_preadv, SYSCALL_DEF_FULL(pwritev, .impl = impl_pwritev, .args = args_preadv_pwritev, .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }); +SYSCALL_DEF(pselect6, ARG_DEC, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR); SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC); #ifdef TARGET_NR_readlink SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC); diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c index 1d66dc3323..0a25d39d28 100644 --- a/linux-user/syscall-file.inc.c +++ b/linux-user/syscall-file.inc.c @@ -934,6 +934,102 @@ SYSCALL_IMPL(pwritev) return ret; } +SYSCALL_IMPL(pselect6) +{ + abi_long n = arg1; + abi_ulong rfd_addr = arg2; + abi_ulong wfd_addr = arg3; + abi_ulong efd_addr = arg4; + abi_ulong ts_addr = arg5; + fd_set rfds, wfds, efds; + fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; + struct timespec ts, *ts_ptr = NULL; + abi_long ret; + + /* + * The 6th arg is actually two args smashed together, and since + * we are using safe_syscall, we must handle this ourselves. + */ + sigset_t set; + struct { + sigset_t *set; + size_t size; + } sig, *sig_ptr = NULL; + + abi_ulong arg_sigset, arg_sigsize, *arg7; + target_sigset_t *target_sigset; + + ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); + if (ret) { + return ret; + } + ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); + if (ret) { + return ret; + } + ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); + if (ret) { + return ret; + } + + if (ts_addr) { + if (target_to_host_timespec(&ts, ts_addr)) { + return -TARGET_EFAULT; + } + ts_ptr = &ts; + } + + /* Extract the two packed args for the sigset */ + if (arg6) { + sig_ptr = &sig; + sig.size = SIGSET_T_SIZE; + + arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1); + if (!arg7) { + return -TARGET_EFAULT; + } + arg_sigset = tswapal(arg7[0]); + arg_sigsize = tswapal(arg7[1]); + unlock_user(arg7, arg6, 0); + + if (arg_sigset) { + sig.set = &set; + if (arg_sigsize != sizeof(*target_sigset)) { + /* Like the kernel, we enforce correct size sigsets */ + return -TARGET_EINVAL; + } + target_sigset = lock_user(VERIFY_READ, arg_sigset, + sizeof(*target_sigset), 1); + if (!target_sigset) { + return -TARGET_EFAULT; + } + target_to_host_sigset(&set, target_sigset); + unlock_user(target_sigset, arg_sigset, 0); + } else { + sig.set = NULL; + } + } + + ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr, + ts_ptr, sig_ptr)); + + if (!is_error(ret)) { + if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) { + return -TARGET_EFAULT; + } + if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) { + return -TARGET_EFAULT; + } + if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) { + return -TARGET_EFAULT; + } + if (ts_addr && host_to_target_timespec(ts_addr, &ts)) { + return -TARGET_EFAULT; + } + } + return ret; +} + SYSCALL_IMPL(read) { int fd = arg1; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 2c8d74a450..6355fd62d8 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4158,109 +4158,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, void *p; switch(num) { -#ifdef TARGET_NR_pselect6 - case TARGET_NR_pselect6: - { - abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; - fd_set rfds, wfds, efds; - fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; - struct timespec ts, *ts_ptr; - - /* - * The 6th arg is actually two args smashed together, - * so we cannot use the C library. - */ - sigset_t set; - struct { - sigset_t *set; - size_t size; - } sig, *sig_ptr; - - abi_ulong arg_sigset, arg_sigsize, *arg7; - target_sigset_t *target_sigset; - - n = arg1; - rfd_addr = arg2; - wfd_addr = arg3; - efd_addr = arg4; - ts_addr = arg5; - - ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); - if (ret) { - return ret; - } - ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); - if (ret) { - return ret; - } - ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); - if (ret) { - return ret; - } - - /* - * This takes a timespec, and not a timeval, so we cannot - * use the do_select() helper ... - */ - if (ts_addr) { - if (target_to_host_timespec(&ts, ts_addr)) { - return -TARGET_EFAULT; - } - ts_ptr = &ts; - } else { - ts_ptr = NULL; - } - - /* Extract the two packed args for the sigset */ - if (arg6) { - sig_ptr = &sig; - sig.size = SIGSET_T_SIZE; - - arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1); - if (!arg7) { - return -TARGET_EFAULT; - } - arg_sigset = tswapal(arg7[0]); - arg_sigsize = tswapal(arg7[1]); - unlock_user(arg7, arg6, 0); - - if (arg_sigset) { - sig.set = &set; - if (arg_sigsize != sizeof(*target_sigset)) { - /* Like the kernel, we enforce correct size sigsets */ - return -TARGET_EINVAL; - } - target_sigset = lock_user(VERIFY_READ, arg_sigset, - sizeof(*target_sigset), 1); - if (!target_sigset) { - return -TARGET_EFAULT; - } - target_to_host_sigset(&set, target_sigset); - unlock_user(target_sigset, arg_sigset, 0); - } else { - sig.set = NULL; - } - } else { - sig_ptr = NULL; - } - - ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr, - ts_ptr, sig_ptr)); - - if (!is_error(ret)) { - if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) - return -TARGET_EFAULT; - if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) - return -TARGET_EFAULT; - if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) - return -TARGET_EFAULT; - - if (ts_addr && host_to_target_timespec(ts_addr, &ts)) - return -TARGET_EFAULT; - } - } - return ret; -#endif #ifdef TARGET_NR_symlink case TARGET_NR_symlink: { diff --git a/linux-user/strace.list b/linux-user/strace.list index 297180d94f..1bb9224b5e 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -848,9 +848,6 @@ #ifdef TARGET_NR_profil { TARGET_NR_profil, "profil" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_pselect6 -{ TARGET_NR_pselect6, "pselect6" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_ptrace { TARGET_NR_ptrace, "ptrace" , NULL, NULL, NULL }, #endif -- 2.17.1