Message ID | 20240123-arm32-lpae-pan-v1-0-7ea98a20514c@linaro.org (mailing list archive) |
---|---|
Headers | show |
Series | PAN for ARM32 using LPAE | expand |
Second posting within seconds? On Tue, Jan 23, 2024 at 10:16:13PM +0100, Linus Walleij wrote: > This is a patch set from Catalin that ended up on the back burner. > > Since LPAE systems, i.e. ARM32 systems with a lot of physical memory, > will be with us for a while more, this is a pretty straight-forward > hardening measure that we should support. > > The last patch explains the mechanism: since PAN using CPU domains > isn't available when using the LPAE MMU tables, we use the split > between the two translation base tables instead: TTBR0 is for > userspace pages and TTBR1 is for kernelspace tables. When executing > in kernelspace: we protect userspace by simply disabling page > walks in TTBR0. > > This was tested by a simple hack in the ELF loader: > > create_elf_tables() > + unsigned char *test; > (...) > if (copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) > return -EFAULT; > + /* Cause a kernelspace access to userspace memory */ > + test = (char *)u_rand_bytes; > + pr_info("Some byte: %02x\n", *test); > > This tries to read a byte from userspace memory right after the > first unconditional copy_to_user(), a function that carefully > switches access permissions if we're using PAN. > > Without LPAE PAN this will just happily print these bytes from > userspace but with LPAE PAN it will cause a predictable > crash: > > Run /init as init process > Some byte: ac > 8<--- cut here --- > Unable to handle kernel paging request at virtual address 7ec59f6b when read > [7ec59f6b] *pgd=82c3b003, *pmd=82863003, *pte=e00000882f6f5f > Internal error: Oops: 206 [#1] SMP ARM > CPU: 0 PID: 47 Comm: rc.init Not tainted 6.7.0-rc1+ #25 > Hardware name: ARM-Versatile Express > PC is at create_elf_tables+0x13c/0x608 > > Thus we can show that LPAE PAN does its job. > > Changes from Catalins initial patch set: > > - Use IS_ENABLED() to avoid some ifdefs > - Create a uaccess_disabled() for classic CPU domains > and reate a stub uaccess_disabled() for !PAN so we can > always check this. > > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > Catalin Marinas (4): > ARM: Add TTBCR_* definitions to pgtable-3level-hwdef.h > ARM: Move asm statements accessing TTBCR into C functions > ARM: Reduce the number of #ifdef CONFIG_CPU_SW_DOMAIN_PAN > ARM: Implement privileged no-access using TTBR0 page table walks disabling > > arch/arm/Kconfig | 22 ++++++++-- > arch/arm/include/asm/assembler.h | 1 + > arch/arm/include/asm/pgtable-3level-hwdef.h | 26 +++++++++++ > arch/arm/include/asm/proc-fns.h | 12 +++++ > arch/arm/include/asm/uaccess-asm.h | 58 ++++++++++++++++++++++-- > arch/arm/include/asm/uaccess.h | 68 ++++++++++++++++++++++++++--- > arch/arm/kernel/suspend.c | 8 ++++ > arch/arm/lib/csumpartialcopyuser.S | 20 ++++++++- > arch/arm/mm/fault.c | 8 ++++ > arch/arm/mm/mmu.c | 7 ++- > 10 files changed, 212 insertions(+), 18 deletions(-) > --- > base-commit: 8615ebf1370a798c403b4495f39de48270ad48f9 > change-id: 20231216-arm32-lpae-pan-56125ab63d63 > > Best regards, > -- > Linus Walleij <linus.walleij@linaro.org> > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel >
On Tue, Jan 23, 2024 at 10:16:13PM +0100, Linus Walleij wrote: > This is a patch set from Catalin that ended up on the back burner. > > Since LPAE systems, i.e. ARM32 systems with a lot of physical memory, > will be with us for a while more, this is a pretty straight-forward > hardening measure that we should support. > > The last patch explains the mechanism: since PAN using CPU domains > isn't available when using the LPAE MMU tables, we use the split > between the two translation base tables instead: TTBR0 is for > userspace pages and TTBR1 is for kernelspace tables. When executing > in kernelspace: we protect userspace by simply disabling page > walks in TTBR0. > > This was tested by a simple hack in the ELF loader: > > create_elf_tables() > + unsigned char *test; > (...) > if (copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) > return -EFAULT; > + /* Cause a kernelspace access to userspace memory */ > + test = (char *)u_rand_bytes; > + pr_info("Some byte: %02x\n", *test); > > This tries to read a byte from userspace memory right after the > first unconditional copy_to_user(), a function that carefully > switches access permissions if we're using PAN. You can also use CONFIG_LKDTM to test, with: # echo "ACCESS_USERSPACE" | cat >/sys/kernel/debug/provoke-crash/DIRECT ... lkdtm: Performing direct entry ACCESS_USERSPACE lkdtm: attempting bad read at 76fe9000 8<--- cut here --- Unable to handle kernel paging request at virtual address 76fe9000 when read [76fe9000] *pgd=45e47003, *pmd=43fd3003, *pte=a0000048af7f5f Internal error: Oops: 206 [#1] SMP ARM ... # echo "EXEC_USERSPACE" | cat >/sys/kernel/debug/provoke-crash/DIRECT ... lkdtm: Performing direct entry EXEC_USERSPACE lkdtm: attempting ok execution at 8083707c lkdtm: attempting bad execution at 76f38000 8<--- cut here --- Unable to handle kernel paging request at virtual address 76f38000 when execute [76f38000] *pgd=49ed2003, *pmd=49e19003, *pte=a00000494a5f5f Internal error: Oops: 80000206 [#2] SMP ARM ... I can confirm it works as expected. :) Tested-by: Kees Cook <keescook@chromium.org> Thanks! -Kees -- Kees Cook
On Tue, Jan 23, 2024 at 09:28:34PM +0000, Russell King (Oracle) wrote:
> Second posting within seconds?
It looked to me like the first missed the mailing list CC.
On Tue, Jan 23, 2024 at 10:29 PM Kees Cook <keescook@chromium.org> wrote: > On Tue, Jan 23, 2024 at 09:28:34PM +0000, Russell King (Oracle) wrote: > > Second posting within seconds? > > It looked to me like the first missed the mailing list CC. Yeah I screwed up, sorry :( Yours, Linus Walleij
This is a patch set from Catalin that ended up on the back burner. Since LPAE systems, i.e. ARM32 systems with a lot of physical memory, will be with us for a while more, this is a pretty straight-forward hardening measure that we should support. The last patch explains the mechanism: since PAN using CPU domains isn't available when using the LPAE MMU tables, we use the split between the two translation base tables instead: TTBR0 is for userspace pages and TTBR1 is for kernelspace tables. When executing in kernelspace: we protect userspace by simply disabling page walks in TTBR0. This was tested by a simple hack in the ELF loader: create_elf_tables() + unsigned char *test; (...) if (copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) return -EFAULT; + /* Cause a kernelspace access to userspace memory */ + test = (char *)u_rand_bytes; + pr_info("Some byte: %02x\n", *test); This tries to read a byte from userspace memory right after the first unconditional copy_to_user(), a function that carefully switches access permissions if we're using PAN. Without LPAE PAN this will just happily print these bytes from userspace but with LPAE PAN it will cause a predictable crash: Run /init as init process Some byte: ac 8<--- cut here --- Unable to handle kernel paging request at virtual address 7ec59f6b when read [7ec59f6b] *pgd=82c3b003, *pmd=82863003, *pte=e00000882f6f5f Internal error: Oops: 206 [#1] SMP ARM CPU: 0 PID: 47 Comm: rc.init Not tainted 6.7.0-rc1+ #25 Hardware name: ARM-Versatile Express PC is at create_elf_tables+0x13c/0x608 Thus we can show that LPAE PAN does its job. Changes from Catalins initial patch set: - Use IS_ENABLED() to avoid some ifdefs - Create a uaccess_disabled() for classic CPU domains and reate a stub uaccess_disabled() for !PAN so we can always check this. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- Catalin Marinas (4): ARM: Add TTBCR_* definitions to pgtable-3level-hwdef.h ARM: Move asm statements accessing TTBCR into C functions ARM: Reduce the number of #ifdef CONFIG_CPU_SW_DOMAIN_PAN ARM: Implement privileged no-access using TTBR0 page table walks disabling arch/arm/Kconfig | 22 ++++++++-- arch/arm/include/asm/assembler.h | 1 + arch/arm/include/asm/pgtable-3level-hwdef.h | 26 +++++++++++ arch/arm/include/asm/proc-fns.h | 12 +++++ arch/arm/include/asm/uaccess-asm.h | 58 ++++++++++++++++++++++-- arch/arm/include/asm/uaccess.h | 68 ++++++++++++++++++++++++++--- arch/arm/kernel/suspend.c | 8 ++++ arch/arm/lib/csumpartialcopyuser.S | 20 ++++++++- arch/arm/mm/fault.c | 8 ++++ arch/arm/mm/mmu.c | 7 ++- 10 files changed, 212 insertions(+), 18 deletions(-) --- base-commit: 8615ebf1370a798c403b4495f39de48270ad48f9 change-id: 20231216-arm32-lpae-pan-56125ab63d63 Best regards,