2023-06-06 09:32:08

by Nicholas Piggin

[permalink] [raw]
Subject: Re: [PATCH 4/4] powerpc/kuap: Make disabling KUAP at boottime optional

On Mon Jun 5, 2023 at 9:04 PM AEST, Christophe Leroy wrote:
> 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.
>
> So add a CONFIG item to make it optionnal.

I love counting cycles, but a CONFIG option for one nop... I think
you have me beat.

Is that sustainable? What if instead of the static branch you patched in
nops to the lock/unlock asm? AFAIKS there does not look like much (any?)
C code in the kuap enabled branches.

Thanks,
Nick

>
> Signed-off-by: Christophe Leroy <[email protected]>
> ---
> arch/powerpc/include/asm/kup.h | 2 +-
> arch/powerpc/mm/init-common.c | 3 +++
> arch/powerpc/platforms/Kconfig.cputype | 10 ++++++++++
> 3 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
> index 74b7f4cee2ed..f3280169aeec 100644
> --- a/arch/powerpc/include/asm/kup.h
> +++ b/arch/powerpc/include/asm/kup.h
> @@ -53,7 +53,7 @@ extern struct static_key_false disable_kuap_key;
>
> static __always_inline bool kuap_is_disabled(void)
> {
> - return static_branch_unlikely(&disable_kuap_key);
> + return IS_ENABLED(CONFIG_PPC_KUAP_BOOTTIME) && static_branch_unlikely(&disable_kuap_key);
> }
> #endif
> #else
> diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c
> index 74e140b1efef..994ee58f0092 100644
> --- a/arch/powerpc/mm/init-common.c
> +++ b/arch/powerpc/mm/init-common.c
> @@ -48,6 +48,9 @@ early_param("nosmep", parse_nosmep);
>
> static int __init parse_nosmap(char *p)
> {
> + if (!IS_ENABLED(CONFIG_PPC_KUAP_BOOTTIME))
> + return 0;
> +
> disable_kuap = true;
> pr_warn("Disabling Kernel Userspace Access Protection\n");
> return 0;
> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
> index 45fd975ef521..f75c2d5cd182 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -502,6 +502,16 @@ config PPC_KUAP
>
> If you're unsure, say Y.
>
> +config PPC_KUAP_BOOTTIME
> + bool "Allow disabling Kernel Userspace Access Protection at boottime"
> + depends on PPC_KUAP
> + default y
> + help
> + Allow the user to disable Kernel Userspace Access Protection (KUAP)
> + at boot time using 'nosmap' kernel parameter.
> +
> + If you're unsure, say Y.
> +
> config PPC_KUAP_DEBUG
> bool "Extra debugging for Kernel Userspace Access Protection"
> depends on PPC_KUAP
> --
> 2.40.1



2023-06-22 06:50:25

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH 4/4] powerpc/kuap: Make disabling KUAP at boottime optional



Le 06/06/2023 à 11:27, Nicholas Piggin a écrit :
> On Mon Jun 5, 2023 at 9:04 PM AEST, Christophe Leroy wrote:
>> 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.
>>
>> So add a CONFIG item to make it optionnal.
>
> I love counting cycles, but a CONFIG option for one nop... I think
> you have me beat.

Unlike most other powerpc, a nop on 8xx is one cycle. So if we can avoid
it on hot pathes ....

>
> Is that sustainable? What if instead of the static branch you patched in
> nops to the lock/unlock asm? AFAIKS there does not look like much (any?)
> C code in the kuap enabled branches.

Yes that's probably the solution at the end.

At the moment I'm struggling with UACCESS objtool validation and I think
I will temporarily disable boottime 'nosmap' parameter for PPC32.

The problem is that with the static branch, objtool visits both branches
but it does it independently for each branch, it is not able to match
two static branches using the same key. So the result is that it detects
UACCESS enable without UACCESS disable and vice-versa.

So the solution at the end will be to patch-out the mtspr, for the time
being I'm just going to disable it completely for PPC32.

Christophe