[PATCH v3 04/15] powerpc/kuap: Make disabling KUAP at boottime impossible except on book3s/64
From: Christophe Leroy <hidden>
Date: 2023-06-23 17:06:29
Also in:
lkml
Subsystem:
linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Michael Ellerman, Linus Torvalds
It is possible to disable KUAP at boottime with 'nosmap' parameter. That is implemented with jump_label hence adds a 'nop' in front of each open/close of userspace access. From a security point of view it makes sence to disallow disabling KUAP. And on processors like the 8xx where 'nop' is not seamless, it saves a few cycles. In addition, objtool UACCESS validation cannot cope with that feature because it visits every static branches independentely and is not able to see that when a UACCESS enable is skipped, the matching UACCESS disable is skipped as well. So make KUAP always active when selected in kernel config. In the future it may be re-implemented by noping the instructions instead of using static branches. Signed-off-by: Christophe Leroy <redacted> --- arch/powerpc/include/asm/kup.h | 4 +--- arch/powerpc/mm/book3s32/kuap.c | 15 ++++++--------- arch/powerpc/mm/init-common.c | 6 +++--- arch/powerpc/mm/nohash/kup.c | 8 +------- 4 files changed, 11 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
index 74b7f4cee2ed..a02340535efa 100644
--- a/arch/powerpc/include/asm/kup.h
+++ b/arch/powerpc/include/asm/kup.h@@ -49,11 +49,9 @@ void setup_kuep(bool disabled); void setup_kuap(bool disabled); #ifndef kuap_is_disabled -extern struct static_key_false disable_kuap_key; - static __always_inline bool kuap_is_disabled(void) { - return static_branch_unlikely(&disable_kuap_key); + return false; } #endif #else
diff --git a/arch/powerpc/mm/book3s32/kuap.c b/arch/powerpc/mm/book3s32/kuap.c
index c5484729b595..639219d0a821 100644
--- a/arch/powerpc/mm/book3s32/kuap.c
+++ b/arch/powerpc/mm/book3s32/kuap.c@@ -17,17 +17,14 @@ EXPORT_SYMBOL(kuap_unlock_all_ool); void setup_kuap(bool disabled) { - if (!disabled) { - kuap_lock_all_ool(); - init_mm.context.sr0 |= SR_KS; - current->thread.sr0 |= SR_KS; - } + WARN_ON(disabled); + + kuap_lock_all_ool(); + init_mm.context.sr0 |= SR_KS; + current->thread.sr0 |= SR_KS; if (smp_processor_id() != boot_cpuid) return; - if (disabled) - static_branch_enable(&disable_kuap_key); - else - pr_info("Activating Kernel Userspace Access Protection\n"); + pr_info("Activating Kernel Userspace Access Protection\n"); }
diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c
index 74e140b1efef..237086742ec7 100644
--- a/arch/powerpc/mm/init-common.c
+++ b/arch/powerpc/mm/init-common.c@@ -32,9 +32,6 @@ EXPORT_SYMBOL_GPL(kernstart_virt_addr); bool disable_kuep = !IS_ENABLED(CONFIG_PPC_KUEP); bool disable_kuap = !IS_ENABLED(CONFIG_PPC_KUAP); -struct static_key_false disable_kuap_key; -EXPORT_SYMBOL(disable_kuap_key); - static int __init parse_nosmep(char *p) { if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64))
@@ -48,6 +45,9 @@ early_param("nosmep", parse_nosmep); static int __init parse_nosmap(char *p) { + if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64)) + return 0; + disable_kuap = true; pr_warn("Disabling Kernel Userspace Access Protection\n"); return 0;
diff --git a/arch/powerpc/mm/nohash/kup.c b/arch/powerpc/mm/nohash/kup.c
index 4e22adfa2aa8..3bb79f89de06 100644
--- a/arch/powerpc/mm/nohash/kup.c
+++ b/arch/powerpc/mm/nohash/kup.c@@ -15,13 +15,7 @@ #ifdef CONFIG_PPC_KUAP void setup_kuap(bool disabled) { - if (disabled) { - if (IS_ENABLED(CONFIG_40x)) - disable_kuep = true; - if (smp_processor_id() == boot_cpuid) - static_branch_enable(&disable_kuap_key); - return; - } + WARN_ON(disabled); pr_info("Activating Kernel Userspace Access Protection\n");
--
2.40.1