-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
powerpc/64s: Implement KUAP for Radix MMU
Kernel Userspace Access Prevention utilises a feature of the Radix MMU which disallows read and write access to userspace addresses. By utilising this, the kernel is prevented from accessing user data from outside of trusted paths that perform proper safety checks, such as copy_{to/from}_user() and friends. Userspace access is disabled from early boot and is only enabled when performing an operation like copy_{to/from}_user(). The register that controls this (AMR) does not prevent userspace from accessing itself, so there is no need to save and restore when entering and exiting userspace. When entering the kernel from the kernel we save AMR and if it is not blocking user access (because eg. we faulted doing a user access) we reblock user access for the duration of the exception (ie. the page fault) and then restore the AMR when returning back to the kernel. This feature can be tested by using the lkdtm driver (CONFIG_LKDTM=y) and performing the following: # (echo ACCESS_USERSPACE) > [debugfs]/provoke-crash/DIRECT If enabled, this should send SIGSEGV to the thread. We also add paranoid checking of AMR in switch and syscall return under CONFIG_PPC_KUAP_DEBUG. Co-authored-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Russell Currey <ruscur@russell.cc> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
- Loading branch information
Showing
10 changed files
with
176 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H | ||
#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H | ||
|
||
#include <linux/const.h> | ||
|
||
#define AMR_KUAP_BLOCK_READ UL(0x4000000000000000) | ||
#define AMR_KUAP_BLOCK_WRITE UL(0x8000000000000000) | ||
#define AMR_KUAP_BLOCKED (AMR_KUAP_BLOCK_READ | AMR_KUAP_BLOCK_WRITE) | ||
#define AMR_KUAP_SHIFT 62 | ||
|
||
#ifdef __ASSEMBLY__ | ||
|
||
.macro kuap_restore_amr gpr | ||
#ifdef CONFIG_PPC_KUAP | ||
BEGIN_MMU_FTR_SECTION_NESTED(67) | ||
ld \gpr, STACK_REGS_KUAP(r1) | ||
mtspr SPRN_AMR, \gpr | ||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67) | ||
#endif | ||
.endm | ||
|
||
.macro kuap_check_amr gpr1, gpr2 | ||
#ifdef CONFIG_PPC_KUAP_DEBUG | ||
BEGIN_MMU_FTR_SECTION_NESTED(67) | ||
mfspr \gpr1, SPRN_AMR | ||
li \gpr2, (AMR_KUAP_BLOCKED >> AMR_KUAP_SHIFT) | ||
sldi \gpr2, \gpr2, AMR_KUAP_SHIFT | ||
999: tdne \gpr1, \gpr2 | ||
EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE) | ||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67) | ||
#endif | ||
.endm | ||
|
||
.macro kuap_save_amr_and_lock gpr1, gpr2, use_cr, msr_pr_cr | ||
#ifdef CONFIG_PPC_KUAP | ||
BEGIN_MMU_FTR_SECTION_NESTED(67) | ||
.ifnb \msr_pr_cr | ||
bne \msr_pr_cr, 99f | ||
.endif | ||
mfspr \gpr1, SPRN_AMR | ||
std \gpr1, STACK_REGS_KUAP(r1) | ||
li \gpr2, (AMR_KUAP_BLOCKED >> AMR_KUAP_SHIFT) | ||
sldi \gpr2, \gpr2, AMR_KUAP_SHIFT | ||
cmpd \use_cr, \gpr1, \gpr2 | ||
beq \use_cr, 99f | ||
// We don't isync here because we very recently entered via rfid | ||
mtspr SPRN_AMR, \gpr2 | ||
isync | ||
99: | ||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67) | ||
#endif | ||
.endm | ||
|
||
#else /* !__ASSEMBLY__ */ | ||
|
||
#ifdef CONFIG_PPC_KUAP | ||
|
||
#include <asm/reg.h> | ||
|
||
/* | ||
* We support individually allowing read or write, but we don't support nesting | ||
* because that would require an expensive read/modify write of the AMR. | ||
*/ | ||
|
||
static inline void set_kuap(unsigned long value) | ||
{ | ||
if (!mmu_has_feature(MMU_FTR_RADIX_KUAP)) | ||
return; | ||
|
||
/* | ||
* ISA v3.0B says we need a CSI (Context Synchronising Instruction) both | ||
* before and after the move to AMR. See table 6 on page 1134. | ||
*/ | ||
isync(); | ||
mtspr(SPRN_AMR, value); | ||
isync(); | ||
} | ||
|
||
static inline void allow_user_access(void __user *to, const void __user *from, | ||
unsigned long size) | ||
{ | ||
// This is written so we can resolve to a single case at build time | ||
if (__builtin_constant_p(to) && to == NULL) | ||
set_kuap(AMR_KUAP_BLOCK_WRITE); | ||
else if (__builtin_constant_p(from) && from == NULL) | ||
set_kuap(AMR_KUAP_BLOCK_READ); | ||
else | ||
set_kuap(0); | ||
} | ||
|
||
static inline void prevent_user_access(void __user *to, const void __user *from, | ||
unsigned long size) | ||
{ | ||
set_kuap(AMR_KUAP_BLOCKED); | ||
} | ||
|
||
#endif /* CONFIG_PPC_KUAP */ | ||
|
||
#endif /* __ASSEMBLY__ */ | ||
|
||
#endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters