diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-03-15 01:43:08 -0700 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2022-03-22 13:06:21 +0100 |
commit | db36aa7daab77a0780be6c044ad7144ac741043e (patch) | |
tree | 4527886481cd10d4180365e8f48ac87b8e2a8872 /linux-user/syscall.c | |
parent | cd0e31a49a1af452b8abf1efa38d035b500c9d0a (diff) |
linux-user: Properly handle sigset arg to ppoll
Unblocked signals are never delivered, because we
didn't record the new mask for process_pending_signals.
Handle this with the same mechanism as sigsuspend.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220315084308.433109-6-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 24 |
1 files changed, 7 insertions, 17 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 67af40deac..f65045efe6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1519,8 +1519,7 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, } if (ppoll) { struct timespec _timeout_ts, *timeout_ts = &_timeout_ts; - target_sigset_t *target_set; - sigset_t _set, *set = &_set; + sigset_t *set = NULL; if (arg3) { if (time64) { @@ -1539,25 +1538,19 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, } if (arg4) { - if (arg5 != sizeof(target_sigset_t)) { - unlock_user(target_pfd, arg1, 0); - return -TARGET_EINVAL; - } - - target_set = lock_user(VERIFY_READ, arg4, - sizeof(target_sigset_t), 1); - if (!target_set) { + ret = process_sigsuspend_mask(&set, arg4, arg5); + if (ret != 0) { unlock_user(target_pfd, arg1, 0); - return -TARGET_EFAULT; + return ret; } - target_to_host_sigset(set, target_set); - } else { - set = NULL; } ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts, set, SIGSET_T_SIZE)); + if (set) { + finish_sigsuspend_mask(ret); + } if (!is_error(ret) && arg3) { if (time64) { if (host_to_target_timespec64(arg3, timeout_ts)) { @@ -1569,9 +1562,6 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, } } } - if (arg4) { - unlock_user(target_set, arg4, 0); - } } else { struct timespec ts, *pts; |