mirror of
https://github.com/torvalds/linux.git
synced 2026-06-06 21:45:45 +02:00
selftests: mm: make protection_keys test work on arm64
The encoding of the pkey register differs on arm64, than on x86/ppc. On those platforms, a bit in the register is used to disable permissions, for arm64, a bit enabled in the register indicates that the permission is allowed. This drops two asserts of the form: assert(read_pkey_reg() <= orig_pkey_reg); Because on arm64 this doesn't hold, due to the encoding. The pkey must be reset to both access allow and write allow in the signal handler. pkey_access_allow() works currently for PowerPC as the PKEY_DISABLE_ACCESS and PKEY_DISABLE_WRITE have overlapping bits set. Access to the uc_mcontext is abstracted, as arm64 has a different structure. Signed-off-by: Joey Gouly <joey.gouly@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> Link: https://lore.kernel.org/r/20240822151113.1479789-27-joey.gouly@arm.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
41bbcf7b4b
commit
f5b5ea51f7
|
|
@ -26,6 +26,9 @@
|
||||||
#define HDR_SZ \
|
#define HDR_SZ \
|
||||||
sizeof(struct _aarch64_ctx)
|
sizeof(struct _aarch64_ctx)
|
||||||
|
|
||||||
|
#define GET_UC_RESV_HEAD(uc) \
|
||||||
|
(struct _aarch64_ctx *)(&(uc->uc_mcontext.__reserved))
|
||||||
|
|
||||||
#define GET_SF_RESV_HEAD(sf) \
|
#define GET_SF_RESV_HEAD(sf) \
|
||||||
(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)
|
(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ TEST_GEN_FILES += $(BINARIES_64)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
|
|
||||||
ifneq (,$(findstring $(ARCH),powerpc))
|
ifneq (,$(filter $(ARCH),arm64 powerpc))
|
||||||
TEST_GEN_FILES += protection_keys
|
TEST_GEN_FILES += protection_keys
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
139
tools/testing/selftests/mm/pkey-arm64.h
Normal file
139
tools/testing/selftests/mm/pkey-arm64.h
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Arm Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PKEYS_ARM64_H
|
||||||
|
#define _PKEYS_ARM64_H
|
||||||
|
|
||||||
|
#include "vm_util.h"
|
||||||
|
/* for signal frame parsing */
|
||||||
|
#include "../arm64/signal/testcases/testcases.h"
|
||||||
|
|
||||||
|
#ifndef SYS_mprotect_key
|
||||||
|
# define SYS_mprotect_key 288
|
||||||
|
#endif
|
||||||
|
#ifndef SYS_pkey_alloc
|
||||||
|
# define SYS_pkey_alloc 289
|
||||||
|
# define SYS_pkey_free 290
|
||||||
|
#endif
|
||||||
|
#define MCONTEXT_IP(mc) mc.pc
|
||||||
|
#define MCONTEXT_TRAPNO(mc) -1
|
||||||
|
|
||||||
|
#define PKEY_MASK 0xf
|
||||||
|
|
||||||
|
#define POE_NONE 0x0
|
||||||
|
#define POE_X 0x2
|
||||||
|
#define POE_RX 0x3
|
||||||
|
#define POE_RWX 0x7
|
||||||
|
|
||||||
|
#define NR_PKEYS 8
|
||||||
|
#define NR_RESERVED_PKEYS 1 /* pkey-0 */
|
||||||
|
|
||||||
|
#define PKEY_ALLOW_ALL 0x77777777
|
||||||
|
|
||||||
|
#define PKEY_BITS_PER_PKEY 4
|
||||||
|
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
|
||||||
|
#undef HPAGE_SIZE
|
||||||
|
#define HPAGE_SIZE default_huge_page_size()
|
||||||
|
|
||||||
|
/* 4-byte instructions * 16384 = 64K page */
|
||||||
|
#define __page_o_noops() asm(".rept 16384 ; nop; .endr")
|
||||||
|
|
||||||
|
static inline u64 __read_pkey_reg(void)
|
||||||
|
{
|
||||||
|
u64 pkey_reg = 0;
|
||||||
|
|
||||||
|
// POR_EL0
|
||||||
|
asm volatile("mrs %0, S3_3_c10_c2_4" : "=r" (pkey_reg));
|
||||||
|
|
||||||
|
return pkey_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __write_pkey_reg(u64 pkey_reg)
|
||||||
|
{
|
||||||
|
u64 por = pkey_reg;
|
||||||
|
|
||||||
|
dprintf4("%s() changing %016llx to %016llx\n",
|
||||||
|
__func__, __read_pkey_reg(), pkey_reg);
|
||||||
|
|
||||||
|
// POR_EL0
|
||||||
|
asm volatile("msr S3_3_c10_c2_4, %0\nisb" :: "r" (por) :);
|
||||||
|
|
||||||
|
dprintf4("%s() pkey register after changing %016llx to %016llx\n",
|
||||||
|
__func__, __read_pkey_reg(), pkey_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cpu_has_pkeys(void)
|
||||||
|
{
|
||||||
|
/* No simple way to determine this */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 pkey_bit_position(int pkey)
|
||||||
|
{
|
||||||
|
return pkey * PKEY_BITS_PER_PKEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_arch_reserved_keys(void)
|
||||||
|
{
|
||||||
|
return NR_RESERVED_PKEYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void expect_fault_on_read_execonly_key(void *p1, int pkey)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey)
|
||||||
|
{
|
||||||
|
return PTR_ERR_ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define set_pkey_bits set_pkey_bits
|
||||||
|
static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
|
||||||
|
{
|
||||||
|
u32 shift = pkey_bit_position(pkey);
|
||||||
|
u64 new_val = POE_RWX;
|
||||||
|
|
||||||
|
/* mask out bits from pkey in old value */
|
||||||
|
reg &= ~((u64)PKEY_MASK << shift);
|
||||||
|
|
||||||
|
if (flags & PKEY_DISABLE_ACCESS)
|
||||||
|
new_val = POE_X;
|
||||||
|
else if (flags & PKEY_DISABLE_WRITE)
|
||||||
|
new_val = POE_RX;
|
||||||
|
|
||||||
|
/* OR in new bits for pkey */
|
||||||
|
reg |= new_val << shift;
|
||||||
|
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define get_pkey_bits get_pkey_bits
|
||||||
|
static inline u64 get_pkey_bits(u64 reg, int pkey)
|
||||||
|
{
|
||||||
|
u32 shift = pkey_bit_position(pkey);
|
||||||
|
/*
|
||||||
|
* shift down the relevant bits to the lowest four, then
|
||||||
|
* mask off all the other higher bits
|
||||||
|
*/
|
||||||
|
u32 perm = (reg >> shift) & PKEY_MASK;
|
||||||
|
|
||||||
|
if (perm == POE_X)
|
||||||
|
return PKEY_DISABLE_ACCESS;
|
||||||
|
if (perm == POE_RX)
|
||||||
|
return PKEY_DISABLE_WRITE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)
|
||||||
|
{
|
||||||
|
struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt);
|
||||||
|
struct poe_context *poe_ctx =
|
||||||
|
(struct poe_context *) get_header(ctx, POE_MAGIC,
|
||||||
|
sizeof(uctxt->uc_mcontext), NULL);
|
||||||
|
if (poe_ctx)
|
||||||
|
poe_ctx->por_el0 = pkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _PKEYS_ARM64_H */
|
||||||
|
|
@ -91,12 +91,17 @@ void record_pkey_malloc(void *ptr, long size, int prot);
|
||||||
#include "pkey-x86.h"
|
#include "pkey-x86.h"
|
||||||
#elif defined(__powerpc64__) /* arch */
|
#elif defined(__powerpc64__) /* arch */
|
||||||
#include "pkey-powerpc.h"
|
#include "pkey-powerpc.h"
|
||||||
|
#elif defined(__aarch64__) /* arch */
|
||||||
|
#include "pkey-arm64.h"
|
||||||
#else /* arch */
|
#else /* arch */
|
||||||
#error Architecture not supported
|
#error Architecture not supported
|
||||||
#endif /* arch */
|
#endif /* arch */
|
||||||
|
|
||||||
|
#ifndef PKEY_MASK
|
||||||
#define PKEY_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
|
#define PKEY_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef set_pkey_bits
|
||||||
static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
|
static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
|
||||||
{
|
{
|
||||||
u32 shift = pkey_bit_position(pkey);
|
u32 shift = pkey_bit_position(pkey);
|
||||||
|
|
@ -106,7 +111,9 @@ static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
|
||||||
reg |= (flags & PKEY_MASK) << shift;
|
reg |= (flags & PKEY_MASK) << shift;
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef get_pkey_bits
|
||||||
static inline u64 get_pkey_bits(u64 reg, int pkey)
|
static inline u64 get_pkey_bits(u64 reg, int pkey)
|
||||||
{
|
{
|
||||||
u32 shift = pkey_bit_position(pkey);
|
u32 shift = pkey_bit_position(pkey);
|
||||||
|
|
@ -116,6 +123,7 @@ static inline u64 get_pkey_bits(u64 reg, int pkey)
|
||||||
*/
|
*/
|
||||||
return ((reg >> shift) & PKEY_MASK);
|
return ((reg >> shift) & PKEY_MASK);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern u64 shadow_pkey_reg;
|
extern u64 shadow_pkey_reg;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
# define SYS_pkey_free 385
|
# define SYS_pkey_free 385
|
||||||
#endif
|
#endif
|
||||||
#define REG_IP_IDX PT_NIP
|
#define REG_IP_IDX PT_NIP
|
||||||
|
#define MCONTEXT_IP(mc) mc.gp_regs[REG_IP_IDX]
|
||||||
|
#define MCONTEXT_TRAPNO(mc) mc.gp_regs[REG_TRAPNO]
|
||||||
#define REG_TRAPNO PT_TRAP
|
#define REG_TRAPNO PT_TRAP
|
||||||
#define MCONTEXT_FPREGS
|
#define MCONTEXT_FPREGS
|
||||||
#define gregs gp_regs
|
#define gregs gp_regs
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MCONTEXT_IP(mc) mc.gregs[REG_IP_IDX]
|
||||||
|
#define MCONTEXT_TRAPNO(mc) mc.gregs[REG_TRAPNO]
|
||||||
#define MCONTEXT_FPREGS
|
#define MCONTEXT_FPREGS
|
||||||
|
|
||||||
#ifndef PKEY_DISABLE_ACCESS
|
#ifndef PKEY_DISABLE_ACCESS
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ void abort_hooks(void)
|
||||||
* will then fault, which makes sure that the fault code handles
|
* will then fault, which makes sure that the fault code handles
|
||||||
* execute-only memory properly.
|
* execute-only memory properly.
|
||||||
*/
|
*/
|
||||||
#ifdef __powerpc64__
|
#if defined(__powerpc64__) || defined(__aarch64__)
|
||||||
/* This way, both 4K and 64K alignment are maintained */
|
/* This way, both 4K and 64K alignment are maintained */
|
||||||
__attribute__((__aligned__(65536)))
|
__attribute__((__aligned__(65536)))
|
||||||
#else
|
#else
|
||||||
|
|
@ -212,7 +212,6 @@ void pkey_disable_set(int pkey, int flags)
|
||||||
unsigned long syscall_flags = 0;
|
unsigned long syscall_flags = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int pkey_rights;
|
int pkey_rights;
|
||||||
u64 orig_pkey_reg = read_pkey_reg();
|
|
||||||
|
|
||||||
dprintf1("START->%s(%d, 0x%x)\n", __func__,
|
dprintf1("START->%s(%d, 0x%x)\n", __func__,
|
||||||
pkey, flags);
|
pkey, flags);
|
||||||
|
|
@ -242,8 +241,6 @@ void pkey_disable_set(int pkey, int flags)
|
||||||
|
|
||||||
dprintf1("%s(%d) pkey_reg: 0x%016llx\n",
|
dprintf1("%s(%d) pkey_reg: 0x%016llx\n",
|
||||||
__func__, pkey, read_pkey_reg());
|
__func__, pkey, read_pkey_reg());
|
||||||
if (flags)
|
|
||||||
pkey_assert(read_pkey_reg() >= orig_pkey_reg);
|
|
||||||
dprintf1("END<---%s(%d, 0x%x)\n", __func__,
|
dprintf1("END<---%s(%d, 0x%x)\n", __func__,
|
||||||
pkey, flags);
|
pkey, flags);
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +250,6 @@ void pkey_disable_clear(int pkey, int flags)
|
||||||
unsigned long syscall_flags = 0;
|
unsigned long syscall_flags = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int pkey_rights = hw_pkey_get(pkey, syscall_flags);
|
int pkey_rights = hw_pkey_get(pkey, syscall_flags);
|
||||||
u64 orig_pkey_reg = read_pkey_reg();
|
|
||||||
|
|
||||||
pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
|
pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
|
||||||
|
|
||||||
|
|
@ -273,8 +269,6 @@ void pkey_disable_clear(int pkey, int flags)
|
||||||
|
|
||||||
dprintf1("%s(%d) pkey_reg: 0x%016llx\n", __func__,
|
dprintf1("%s(%d) pkey_reg: 0x%016llx\n", __func__,
|
||||||
pkey, read_pkey_reg());
|
pkey, read_pkey_reg());
|
||||||
if (flags)
|
|
||||||
assert(read_pkey_reg() <= orig_pkey_reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkey_write_allow(int pkey)
|
void pkey_write_allow(int pkey)
|
||||||
|
|
@ -330,8 +324,8 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
|
||||||
__func__, __LINE__,
|
__func__, __LINE__,
|
||||||
__read_pkey_reg(), shadow_pkey_reg);
|
__read_pkey_reg(), shadow_pkey_reg);
|
||||||
|
|
||||||
trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
|
trapno = MCONTEXT_TRAPNO(uctxt->uc_mcontext);
|
||||||
ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
|
ip = MCONTEXT_IP(uctxt->uc_mcontext);
|
||||||
#ifdef MCONTEXT_FPREGS
|
#ifdef MCONTEXT_FPREGS
|
||||||
fpregs = (char *) uctxt->uc_mcontext.fpregs;
|
fpregs = (char *) uctxt->uc_mcontext.fpregs;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -395,6 +389,8 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
|
||||||
#elif defined(__powerpc64__) /* arch */
|
#elif defined(__powerpc64__) /* arch */
|
||||||
/* restore access and let the faulting instruction continue */
|
/* restore access and let the faulting instruction continue */
|
||||||
pkey_access_allow(siginfo_pkey);
|
pkey_access_allow(siginfo_pkey);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
aarch64_write_signal_pkey(uctxt, PKEY_ALLOW_ALL);
|
||||||
#endif /* arch */
|
#endif /* arch */
|
||||||
pkey_faults++;
|
pkey_faults++;
|
||||||
dprintf1("<<<<==================================================\n");
|
dprintf1("<<<<==================================================\n");
|
||||||
|
|
@ -908,7 +904,9 @@ void expected_pkey_fault(int pkey)
|
||||||
* test program continue. We now have to restore it.
|
* test program continue. We now have to restore it.
|
||||||
*/
|
*/
|
||||||
if (__read_pkey_reg() != 0)
|
if (__read_pkey_reg() != 0)
|
||||||
#else /* arch */
|
#elif defined(__aarch64__)
|
||||||
|
if (__read_pkey_reg() != PKEY_ALLOW_ALL)
|
||||||
|
#else
|
||||||
if (__read_pkey_reg() != shadow_pkey_reg)
|
if (__read_pkey_reg() != shadow_pkey_reg)
|
||||||
#endif /* arch */
|
#endif /* arch */
|
||||||
pkey_assert(0);
|
pkey_assert(0);
|
||||||
|
|
@ -1498,6 +1496,11 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
|
||||||
lots_o_noops_around_write(&scratch);
|
lots_o_noops_around_write(&scratch);
|
||||||
do_not_expect_pkey_fault("executing on PROT_EXEC memory");
|
do_not_expect_pkey_fault("executing on PROT_EXEC memory");
|
||||||
expect_fault_on_read_execonly_key(p1, pkey);
|
expect_fault_on_read_execonly_key(p1, pkey);
|
||||||
|
|
||||||
|
// Reset back to PROT_EXEC | PROT_READ for architectures that support
|
||||||
|
// non-PKEY execute-only permissions.
|
||||||
|
ret = mprotect_pkey(p1, PAGE_SIZE, PROT_EXEC | PROT_READ, (u64)pkey);
|
||||||
|
pkey_assert(!ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
|
void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
|
||||||
|
|
@ -1671,6 +1674,84 @@ void test_ptrace_modifies_pkru(int *ptr, u16 pkey)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
void test_ptrace_modifies_pkru(int *ptr, u16 pkey)
|
||||||
|
{
|
||||||
|
pid_t child;
|
||||||
|
int status, ret;
|
||||||
|
struct iovec iov;
|
||||||
|
u64 trace_pkey;
|
||||||
|
/* Just a random pkey value.. */
|
||||||
|
u64 new_pkey = (POE_X << PKEY_BITS_PER_PKEY * 2) |
|
||||||
|
(POE_NONE << PKEY_BITS_PER_PKEY) |
|
||||||
|
POE_RWX;
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
pkey_assert(child >= 0);
|
||||||
|
dprintf3("[%d] fork() ret: %d\n", getpid(), child);
|
||||||
|
if (!child) {
|
||||||
|
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
||||||
|
|
||||||
|
/* Stop and allow the tracer to modify PKRU directly */
|
||||||
|
raise(SIGSTOP);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* need __read_pkey_reg() version so we do not do shadow_pkey_reg
|
||||||
|
* checking
|
||||||
|
*/
|
||||||
|
if (__read_pkey_reg() != new_pkey)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
raise(SIGSTOP);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pkey_assert(child == waitpid(child, &status, 0));
|
||||||
|
dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status);
|
||||||
|
pkey_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);
|
||||||
|
|
||||||
|
iov.iov_base = &trace_pkey;
|
||||||
|
iov.iov_len = 8;
|
||||||
|
ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_ARM_POE, &iov);
|
||||||
|
pkey_assert(ret == 0);
|
||||||
|
pkey_assert(trace_pkey == read_pkey_reg());
|
||||||
|
|
||||||
|
trace_pkey = new_pkey;
|
||||||
|
|
||||||
|
ret = ptrace(PTRACE_SETREGSET, child, (void *)NT_ARM_POE, &iov);
|
||||||
|
pkey_assert(ret == 0);
|
||||||
|
|
||||||
|
/* Test that the modification is visible in ptrace before any execution */
|
||||||
|
memset(&trace_pkey, 0, sizeof(trace_pkey));
|
||||||
|
ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_ARM_POE, &iov);
|
||||||
|
pkey_assert(ret == 0);
|
||||||
|
pkey_assert(trace_pkey == new_pkey);
|
||||||
|
|
||||||
|
/* Execute the tracee */
|
||||||
|
ret = ptrace(PTRACE_CONT, child, 0, 0);
|
||||||
|
pkey_assert(ret == 0);
|
||||||
|
|
||||||
|
/* Test that the tracee saw the PKRU value change */
|
||||||
|
pkey_assert(child == waitpid(child, &status, 0));
|
||||||
|
dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status);
|
||||||
|
pkey_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);
|
||||||
|
|
||||||
|
/* Test that the modification is visible in ptrace after execution */
|
||||||
|
memset(&trace_pkey, 0, sizeof(trace_pkey));
|
||||||
|
ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_ARM_POE, &iov);
|
||||||
|
pkey_assert(ret == 0);
|
||||||
|
pkey_assert(trace_pkey == new_pkey);
|
||||||
|
|
||||||
|
ret = ptrace(PTRACE_CONT, child, 0, 0);
|
||||||
|
pkey_assert(ret == 0);
|
||||||
|
pkey_assert(child == waitpid(child, &status, 0));
|
||||||
|
dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status);
|
||||||
|
pkey_assert(WIFEXITED(status));
|
||||||
|
pkey_assert(WEXITSTATUS(status) == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)
|
void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)
|
||||||
{
|
{
|
||||||
int size = PAGE_SIZE;
|
int size = PAGE_SIZE;
|
||||||
|
|
@ -1706,7 +1787,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = {
|
||||||
test_pkey_syscalls_bad_args,
|
test_pkey_syscalls_bad_args,
|
||||||
test_pkey_alloc_exhaust,
|
test_pkey_alloc_exhaust,
|
||||||
test_pkey_alloc_free_attach_pkey0,
|
test_pkey_alloc_free_attach_pkey0,
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
||||||
test_ptrace_modifies_pkru,
|
test_ptrace_modifies_pkru,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user