linux-user: Split out helpers for sigsuspend
Two new functions: process_sigsuspend_mask and finish_sigsuspend_mask. Move the size check and copy-from-user code. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20220315084308.433109-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
7fb5ef350b
commit
0a99f09383
|
@ -92,4 +92,30 @@ abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
|
||||||
*/
|
*/
|
||||||
int block_signals(void); /* Returns non zero if signal pending */
|
int block_signals(void); /* Returns non zero if signal pending */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* process_sigsuspend_mask: read and apply syscall-local signal mask
|
||||||
|
*
|
||||||
|
* Read the guest signal mask from @sigset, length @sigsize.
|
||||||
|
* Convert that to a host signal mask and save it to sigpending_mask.
|
||||||
|
*
|
||||||
|
* Return value: negative target errno, or zero;
|
||||||
|
* store &sigpending_mask into *pset on success.
|
||||||
|
*/
|
||||||
|
int process_sigsuspend_mask(sigset_t **pset, target_ulong sigset,
|
||||||
|
target_ulong sigsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finish_sigsuspend_mask: finish a sigsuspend-like syscall
|
||||||
|
*
|
||||||
|
* Set in_sigsuspend if we need to use the modified sigset
|
||||||
|
* during process_pending_signals.
|
||||||
|
*/
|
||||||
|
static inline void finish_sigsuspend_mask(int ret)
|
||||||
|
{
|
||||||
|
if (ret != -QEMU_ERESTARTSYS) {
|
||||||
|
TaskState *ts = (TaskState *)thread_cpu->opaque;
|
||||||
|
ts->in_sigsuspend = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1199,3 +1199,26 @@ void process_pending_signals(CPUArchState *cpu_env)
|
||||||
}
|
}
|
||||||
ts->in_sigsuspend = 0;
|
ts->in_sigsuspend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int process_sigsuspend_mask(sigset_t **pset, target_ulong sigset,
|
||||||
|
target_ulong sigsize)
|
||||||
|
{
|
||||||
|
TaskState *ts = (TaskState *)thread_cpu->opaque;
|
||||||
|
sigset_t *host_set = &ts->sigsuspend_mask;
|
||||||
|
target_sigset_t *target_sigset;
|
||||||
|
|
||||||
|
if (sigsize != sizeof(*target_sigset)) {
|
||||||
|
/* Like the kernel, we enforce correct size sigsets */
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_sigset = lock_user(VERIFY_READ, sigset, sigsize, 1);
|
||||||
|
if (!target_sigset) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
target_to_host_sigset(host_set, target_sigset);
|
||||||
|
unlock_user(target_sigset, sigset, 0);
|
||||||
|
|
||||||
|
*pset = host_set;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -9557,41 +9557,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||||
#ifdef TARGET_NR_sigsuspend
|
#ifdef TARGET_NR_sigsuspend
|
||||||
case TARGET_NR_sigsuspend:
|
case TARGET_NR_sigsuspend:
|
||||||
{
|
{
|
||||||
TaskState *ts = cpu->opaque;
|
sigset_t *set;
|
||||||
|
|
||||||
#if defined(TARGET_ALPHA)
|
#if defined(TARGET_ALPHA)
|
||||||
|
TaskState *ts = cpu->opaque;
|
||||||
/* target_to_host_old_sigset will bswap back */
|
/* target_to_host_old_sigset will bswap back */
|
||||||
abi_ulong mask = tswapal(arg1);
|
abi_ulong mask = tswapal(arg1);
|
||||||
target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
|
set = &ts->sigsuspend_mask;
|
||||||
|
target_to_host_old_sigset(set, &mask);
|
||||||
#else
|
#else
|
||||||
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
|
ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
|
||||||
return -TARGET_EFAULT;
|
if (ret != 0) {
|
||||||
target_to_host_old_sigset(&ts->sigsuspend_mask, p);
|
return ret;
|
||||||
unlock_user(p, arg1, 0);
|
|
||||||
#endif
|
|
||||||
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
|
|
||||||
SIGSET_T_SIZE));
|
|
||||||
if (ret != -QEMU_ERESTARTSYS) {
|
|
||||||
ts->in_sigsuspend = 1;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
|
||||||
|
finish_sigsuspend_mask(ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
case TARGET_NR_rt_sigsuspend:
|
case TARGET_NR_rt_sigsuspend:
|
||||||
{
|
{
|
||||||
TaskState *ts = cpu->opaque;
|
sigset_t *set;
|
||||||
|
|
||||||
if (arg2 != sizeof(target_sigset_t)) {
|
ret = process_sigsuspend_mask(&set, arg1, arg2);
|
||||||
return -TARGET_EINVAL;
|
if (ret != 0) {
|
||||||
}
|
return ret;
|
||||||
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
|
|
||||||
return -TARGET_EFAULT;
|
|
||||||
target_to_host_sigset(&ts->sigsuspend_mask, p);
|
|
||||||
unlock_user(p, arg1, 0);
|
|
||||||
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
|
|
||||||
SIGSET_T_SIZE));
|
|
||||||
if (ret != -QEMU_ERESTARTSYS) {
|
|
||||||
ts->in_sigsuspend = 1;
|
|
||||||
}
|
}
|
||||||
|
ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
|
||||||
|
finish_sigsuspend_mask(ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
#ifdef TARGET_NR_rt_sigtimedwait
|
#ifdef TARGET_NR_rt_sigtimedwait
|
||||||
|
|
Loading…
Reference in New Issue