linux-user/aarch64: Implement map_shadow_stack syscall
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20251008215613.300150-67-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
1c94480377
commit
ad1afe433f
1 changed files with 59 additions and 0 deletions
|
|
@ -6358,6 +6358,12 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
|
|||
# define PR_SET_SHADOW_STACK_STATUS 75
|
||||
# define PR_LOCK_SHADOW_STACK_STATUS 76
|
||||
#endif
|
||||
#ifndef SHADOW_STACK_SET_TOKEN
|
||||
# define SHADOW_STACK_SET_TOKEN (1u << 0)
|
||||
#endif
|
||||
#ifndef SHADOW_STACK_SET_MARKER
|
||||
# define SHADOW_STACK_SET_MARKER (1u << 1)
|
||||
#endif
|
||||
|
||||
#include "target_prctl.h"
|
||||
|
||||
|
|
@ -6605,6 +6611,54 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
static abi_long do_map_shadow_stack(CPUArchState *env, abi_ulong addr,
|
||||
abi_ulong size, abi_int flags)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
abi_ulong alloc_size;
|
||||
|
||||
if (!cpu_isar_feature(aa64_gcs, cpu)) {
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
if (flags & ~(SHADOW_STACK_SET_TOKEN | SHADOW_STACK_SET_MARKER)) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (addr & ~TARGET_PAGE_MASK) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (size == 8 || !QEMU_IS_ALIGNED(size, 8)) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
alloc_size = TARGET_PAGE_ALIGN(size);
|
||||
if (alloc_size < size) {
|
||||
return -TARGET_EOVERFLOW;
|
||||
}
|
||||
|
||||
mmap_lock();
|
||||
addr = gcs_alloc(addr, alloc_size);
|
||||
if (addr != -1) {
|
||||
if (flags & SHADOW_STACK_SET_TOKEN) {
|
||||
abi_ptr cap_ptr = addr + size - 8;
|
||||
uint64_t cap_val;
|
||||
|
||||
if (flags & SHADOW_STACK_SET_MARKER) {
|
||||
/* Leave an extra empty frame at top-of-stack. */
|
||||
cap_ptr -= 8;
|
||||
}
|
||||
cap_val = (cap_ptr & TARGET_PAGE_MASK) | 1;
|
||||
if (put_user_u64(cap_val, cap_ptr)) {
|
||||
/* Allocation succeeded above. */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
mmap_unlock();
|
||||
return get_errno(addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NEW_STACK_SIZE 0x40000
|
||||
|
||||
|
||||
|
|
@ -14065,6 +14119,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
return do_riscv_hwprobe(cpu_env, arg1, arg2, arg3, arg4, arg5);
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
case TARGET_NR_map_shadow_stack:
|
||||
return do_map_shadow_stack(cpu_env, arg1, arg2, arg3);
|
||||
#endif
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
|
||||
return -TARGET_ENOSYS;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue