Skip to content

Commit 83ef4a3

Browse files
committed
Merge branch 'for-next/pkey-signal' into for-next/core
* for-next/pkey-signal: : Bring arm64 pkey signal delivery in line with the x86 behaviour selftests/mm: Fix unused function warning for aarch64_write_signal_pkey() selftests/mm: Define PKEY_UNRESTRICTED for pkey_sighandler_tests selftests/mm: Enable pkey_sighandler_tests on arm64 selftests/mm: Use generic pkey register manipulation arm64: signal: Remove unused macro arm64: signal: Remove unnecessary check when saving POE state arm64: signal: Improve POR_EL0 handling to avoid uaccess failures firmware: arm_sdei: Fix the input parameter of cpuhp_remove_state() Revert "kasan: Disable Software Tag-Based KASAN with GCC" kasan: Fix Software Tag-Based KASAN with GCC kasan: Disable Software Tag-Based KASAN with GCC Documentation/protection-keys: add AArch64 to documentation arm64: set POR_EL0 for kernel threads # Conflicts: # arch/arm64/kernel/signal.c
2 parents 437330d + 929bbc1 commit 83ef4a3

File tree

10 files changed

+222
-55
lines changed

10 files changed

+222
-55
lines changed

Documentation/core-api/protection-keys.rst

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ Pkeys Userspace (PKU) is a feature which can be found on:
1212
* Intel server CPUs, Skylake and later
1313
* Intel client CPUs, Tiger Lake (11th Gen Core) and later
1414
* Future AMD CPUs
15+
* arm64 CPUs implementing the Permission Overlay Extension (FEAT_S1POE)
1516

17+
x86_64
18+
======
1619
Pkeys work by dedicating 4 previously Reserved bits in each page table entry to
1720
a "protection key", giving 16 possible keys.
1821

@@ -28,6 +31,22 @@ register. The feature is only available in 64-bit mode, even though there is
2831
theoretically space in the PAE PTEs. These permissions are enforced on data
2932
access only and have no effect on instruction fetches.
3033

34+
arm64
35+
=====
36+
37+
Pkeys use 3 bits in each page table entry, to encode a "protection key index",
38+
giving 8 possible keys.
39+
40+
Protections for each key are defined with a per-CPU user-writable system
41+
register (POR_EL0). This is a 64-bit register encoding read, write and execute
42+
overlay permissions for each protection key index.
43+
44+
Being a CPU register, POR_EL0 is inherently thread-local, potentially giving
45+
each thread a different set of protections from every other thread.
46+
47+
Unlike x86_64, the protection key permissions also apply to instruction
48+
fetches.
49+
3150
Syscalls
3251
========
3352

@@ -38,11 +57,10 @@ There are 3 system calls which directly interact with pkeys::
3857
int pkey_mprotect(unsigned long start, size_t len,
3958
unsigned long prot, int pkey);
4059

41-
Before a pkey can be used, it must first be allocated with
42-
pkey_alloc(). An application calls the WRPKRU instruction
43-
directly in order to change access permissions to memory covered
44-
with a key. In this example WRPKRU is wrapped by a C function
45-
called pkey_set().
60+
Before a pkey can be used, it must first be allocated with pkey_alloc(). An
61+
application writes to the architecture specific CPU register directly in order
62+
to change access permissions to memory covered with a key. In this example
63+
this is wrapped by a C function called pkey_set().
4664
::
4765

4866
int real_prot = PROT_READ|PROT_WRITE;
@@ -64,9 +82,9 @@ is no longer in use::
6482
munmap(ptr, PAGE_SIZE);
6583
pkey_free(pkey);
6684

67-
.. note:: pkey_set() is a wrapper for the RDPKRU and WRPKRU instructions.
68-
An example implementation can be found in
69-
tools/testing/selftests/x86/protection_keys.c.
85+
.. note:: pkey_set() is a wrapper around writing to the CPU register.
86+
Example implementations can be found in
87+
tools/testing/selftests/mm/pkey-{arm64,powerpc,x86}.h
7088

7189
Behavior
7290
========
@@ -96,3 +114,7 @@ with a read()::
96114
The kernel will send a SIGSEGV in both cases, but si_code will be set
97115
to SEGV_PKERR when violating protection keys versus SEGV_ACCERR when
98116
the plain mprotect() permissions are violated.
117+
118+
Note that kernel accesses from a kthread (such as io_uring) will use a default
119+
value for the protection key register and so will not be consistent with
120+
userspace's value of the register or mprotect().

arch/arm64/kernel/process.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
466466

467467
p->thread.cpu_context.x19 = (unsigned long)args->fn;
468468
p->thread.cpu_context.x20 = (unsigned long)args->fn_arg;
469+
470+
if (system_supports_poe())
471+
p->thread.por_el0 = POR_EL0_INIT;
469472
}
470473
p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
471474
p->thread.cpu_context.sp = (unsigned long)childregs;

arch/arm64/kernel/signal.c

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/ratelimit.h>
2020
#include <linux/rseq.h>
2121
#include <linux/syscalls.h>
22+
#include <linux/pkeys.h>
2223

2324
#include <asm/daifflags.h>
2425
#include <asm/debug-monitors.h>
@@ -72,10 +73,62 @@ struct rt_sigframe_user_layout {
7273
unsigned long end_offset;
7374
};
7475

75-
#define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16)
76+
/*
77+
* Holds any EL0-controlled state that influences unprivileged memory accesses.
78+
* This includes both accesses done in userspace and uaccess done in the kernel.
79+
*
80+
* This state needs to be carefully managed to ensure that it doesn't cause
81+
* uaccess to fail when setting up the signal frame, and the signal handler
82+
* itself also expects a well-defined state when entered.
83+
*/
84+
struct user_access_state {
85+
u64 por_el0;
86+
};
87+
7688
#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
7789
#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
7890

91+
/*
92+
* Save the user access state into ua_state and reset it to disable any
93+
* restrictions.
94+
*/
95+
static void save_reset_user_access_state(struct user_access_state *ua_state)
96+
{
97+
if (system_supports_poe()) {
98+
u64 por_enable_all = 0;
99+
100+
for (int pkey = 0; pkey < arch_max_pkey(); pkey++)
101+
por_enable_all |= POE_RXW << (pkey * POR_BITS_PER_PKEY);
102+
103+
ua_state->por_el0 = read_sysreg_s(SYS_POR_EL0);
104+
write_sysreg_s(por_enable_all, SYS_POR_EL0);
105+
/* Ensure that any subsequent uaccess observes the updated value */
106+
isb();
107+
}
108+
}
109+
110+
/*
111+
* Set the user access state for invoking the signal handler.
112+
*
113+
* No uaccess should be done after that function is called.
114+
*/
115+
static void set_handler_user_access_state(void)
116+
{
117+
if (system_supports_poe())
118+
write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0);
119+
}
120+
121+
/*
122+
* Restore the user access state to the values saved in ua_state.
123+
*
124+
* No uaccess should be done after that function is called.
125+
*/
126+
static void restore_user_access_state(const struct user_access_state *ua_state)
127+
{
128+
if (system_supports_poe())
129+
write_sysreg_s(ua_state->por_el0, SYS_POR_EL0);
130+
}
131+
79132
static void init_user_layout(struct rt_sigframe_user_layout *user)
80133
{
81134
const size_t reserved_size =
@@ -269,18 +322,20 @@ static int restore_fpmr_context(struct user_ctxs *user)
269322
return err;
270323
}
271324

272-
static int preserve_poe_context(struct poe_context __user *ctx)
325+
static int preserve_poe_context(struct poe_context __user *ctx,
326+
const struct user_access_state *ua_state)
273327
{
274328
int err = 0;
275329

276330
__put_user_error(POE_MAGIC, &ctx->head.magic, err);
277331
__put_user_error(sizeof(*ctx), &ctx->head.size, err);
278-
__put_user_error(read_sysreg_s(SYS_POR_EL0), &ctx->por_el0, err);
332+
__put_user_error(ua_state->por_el0, &ctx->por_el0, err);
279333

280334
return err;
281335
}
282336

283-
static int restore_poe_context(struct user_ctxs *user)
337+
static int restore_poe_context(struct user_ctxs *user,
338+
struct user_access_state *ua_state)
284339
{
285340
u64 por_el0;
286341
int err = 0;
@@ -290,7 +345,7 @@ static int restore_poe_context(struct user_ctxs *user)
290345

291346
__get_user_error(por_el0, &(user->poe->por_el0), err);
292347
if (!err)
293-
write_sysreg_s(por_el0, SYS_POR_EL0);
348+
ua_state->por_el0 = por_el0;
294349

295350
return err;
296351
}
@@ -946,7 +1001,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
9461001
}
9471002

9481003
static int restore_sigframe(struct pt_regs *regs,
949-
struct rt_sigframe __user *sf)
1004+
struct rt_sigframe __user *sf,
1005+
struct user_access_state *ua_state)
9501006
{
9511007
sigset_t set;
9521008
int i, err;
@@ -998,7 +1054,7 @@ static int restore_sigframe(struct pt_regs *regs,
9981054
err = restore_zt_context(&user);
9991055

10001056
if (err == 0 && system_supports_poe() && user.poe)
1001-
err = restore_poe_context(&user);
1057+
err = restore_poe_context(&user, ua_state);
10021058

10031059
return err;
10041060
}
@@ -1059,6 +1115,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
10591115
{
10601116
struct pt_regs *regs = current_pt_regs();
10611117
struct rt_sigframe __user *frame;
1118+
struct user_access_state ua_state;
10621119

10631120
/* Always make any pending restarted system calls return -EINTR */
10641121
current->restart_block.fn = do_no_restart_syscall;
@@ -1075,7 +1132,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
10751132
if (!access_ok(frame, sizeof (*frame)))
10761133
goto badframe;
10771134

1078-
if (restore_sigframe(regs, frame))
1135+
if (restore_sigframe(regs, frame, &ua_state))
10791136
goto badframe;
10801137

10811138
if (gcs_restore_signal())
@@ -1084,6 +1141,8 @@ SYSCALL_DEFINE0(rt_sigreturn)
10841141
if (restore_altstack(&frame->uc.uc_stack))
10851142
goto badframe;
10861143

1144+
restore_user_access_state(&ua_state);
1145+
10871146
return regs->regs[0];
10881147

10891148
badframe:
@@ -1198,7 +1257,8 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
11981257
}
11991258

12001259
static int setup_sigframe(struct rt_sigframe_user_layout *user,
1201-
struct pt_regs *regs, sigset_t *set)
1260+
struct pt_regs *regs, sigset_t *set,
1261+
const struct user_access_state *ua_state)
12021262
{
12031263
int i, err = 0;
12041264
struct rt_sigframe __user *sf = user->sigframe;
@@ -1262,14 +1322,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
12621322
err |= preserve_fpmr_context(fpmr_ctx);
12631323
}
12641324

1265-
if (system_supports_poe() && err == 0 && user->poe_offset) {
1325+
if (system_supports_poe() && err == 0) {
12661326
struct poe_context __user *poe_ctx =
12671327
apply_user_offset(user, user->poe_offset);
12681328

1269-
err |= preserve_poe_context(poe_ctx);
1329+
err |= preserve_poe_context(poe_ctx, ua_state);
12701330
}
12711331

1272-
12731332
/* ZA state if present */
12741333
if (system_supports_sme() && err == 0 && user->za_offset) {
12751334
struct za_context __user *za_ctx =
@@ -1447,9 +1506,6 @@ static int setup_return(struct pt_regs *regs, struct ksignal *ksig,
14471506
sme_smstop();
14481507
}
14491508

1450-
if (system_supports_poe())
1451-
write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0);
1452-
14531509
if (ksig->ka.sa.sa_flags & SA_RESTORER)
14541510
sigtramp = ksig->ka.sa.sa_restorer;
14551511
else
@@ -1465,20 +1521,22 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
14651521
{
14661522
struct rt_sigframe_user_layout user;
14671523
struct rt_sigframe __user *frame;
1524+
struct user_access_state ua_state;
14681525
int err = 0;
14691526

14701527
fpsimd_signal_preserve_current_state();
14711528

14721529
if (get_sigframe(&user, ksig, regs))
14731530
return 1;
14741531

1532+
save_reset_user_access_state(&ua_state);
14751533
frame = user.sigframe;
14761534

14771535
__put_user_error(0, &frame->uc.uc_flags, err);
14781536
__put_user_error(NULL, &frame->uc.uc_link, err);
14791537

14801538
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
1481-
err |= setup_sigframe(&user, regs, set);
1539+
err |= setup_sigframe(&user, regs, set, &ua_state);
14821540
if (err == 0) {
14831541
err = setup_return(regs, ksig, &user, usig);
14841542
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
@@ -1488,6 +1546,11 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
14881546
}
14891547
}
14901548

1549+
if (err == 0)
1550+
set_handler_user_access_state();
1551+
else
1552+
restore_user_access_state(&ua_state);
1553+
14911554
return err;
14921555
}
14931556

drivers/firmware/arm_sdei.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ static int sdei_device_freeze(struct device *dev)
763763
int err;
764764

765765
/* unregister private events */
766-
cpuhp_remove_state(sdei_entry_point);
766+
cpuhp_remove_state(sdei_hp_state);
767767

768768
err = sdei_unregister_shared();
769769
if (err)

include/linux/compiler-gcc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@
8080
#define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
8181
#endif
8282

83+
#ifdef __SANITIZE_HWADDRESS__
84+
#define __no_sanitize_address __attribute__((__no_sanitize__("hwaddress")))
85+
#else
8386
#define __no_sanitize_address __attribute__((__no_sanitize_address__))
87+
#endif
8488

8589
#if defined(__SANITIZE_THREAD__)
8690
#define __no_sanitize_thread __attribute__((__no_sanitize_thread__))

tools/testing/selftests/mm/Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ endif
105105
ifeq ($(CAN_BUILD_X86_64),1)
106106
TEST_GEN_FILES += $(BINARIES_64)
107107
endif
108-
else
109108

110-
ifneq (,$(filter $(ARCH),arm64 powerpc))
109+
else ifeq ($(ARCH),arm64)
110+
TEST_GEN_FILES += protection_keys
111+
TEST_GEN_FILES += pkey_sighandler_tests
112+
else ifeq ($(ARCH),powerpc)
111113
TEST_GEN_FILES += protection_keys
112-
endif
113-
114114
endif
115115

116116
ifneq (,$(filter $(ARCH),arm64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64 s390))

tools/testing/selftests/mm/pkey-arm64.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#define NR_RESERVED_PKEYS 1 /* pkey-0 */
3232

3333
#define PKEY_ALLOW_ALL 0x77777777
34+
#define PKEY_REG_ALLOW_NONE 0x0
3435

3536
#define PKEY_BITS_PER_PKEY 4
3637
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
@@ -126,7 +127,7 @@ static inline u64 get_pkey_bits(u64 reg, int pkey)
126127
return 0;
127128
}
128129

129-
static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)
130+
static inline void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)
130131
{
131132
struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt);
132133
struct poe_context *poe_ctx =

tools/testing/selftests/mm/pkey-helpers.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ void record_pkey_malloc(void *ptr, long size, int prot);
112112
#define PKEY_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
113113
#endif
114114

115+
/*
116+
* FIXME: Remove once the generic PKEY_UNRESTRICTED definition is merged.
117+
*/
118+
#ifndef PKEY_UNRESTRICTED
119+
#define PKEY_UNRESTRICTED 0x0
120+
#endif
121+
115122
#ifndef set_pkey_bits
116123
static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
117124
{

tools/testing/selftests/mm/pkey-x86.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define PAGE_SIZE 4096
3535
#define MB (1<<20)
3636

37+
#define PKEY_REG_ALLOW_NONE 0x55555555
38+
3739
static inline void __page_o_noops(void)
3840
{
3941
/* 8-bytes of instruction * 512 bytes = 1 page */

0 commit comments

Comments
 (0)