Re: [RFC PATCH 0/7] kasan: RISC-V support for KASAN_SW_TAGS using pointer masking
From: Andrey Konovalov <andreyknvl@gmail.com>
Date: 2024-08-14 16:03:25
Also in:
linux-riscv, lkml, llvm
On Wed, Aug 14, 2024 at 10:56 AM Samuel Holland [off-list ref] wrote:
This series implements support for software tag-based KASAN using the RISC-V pointer masking extension[1], which supports 7 and/or 16-bit tags. This implementation uses 7-bit tags, so it is compatible with either hardware mode. Patch 3 adds supports for KASAN_SW_TAGS with tag widths other than 8 bits.
This is awesome!
Pointer masking is an optional ISA extension, and it must be enabled using an SBI call to firmware on each CPU. If the SBI call fails on the boot CPU, KASAN is globally disabled. Patch 2 adds support for boot-time disabling of KASAN_SW_TAGS. The SBI call is part of the upcoming SBI Firmware Features (FWFT) extension[2][3]. Since generic FWFT support is not yet merged to Linux, I open-coded the sbi_ecall() in this RFC to keep this series focused. With my RISC-V KASAN fixes series[4] applied, this implementation passes all but one of the KASAN KUnit tests. It fails vmalloc_percpu(), which also fails on arm64:
Hm, this test passes on arm64 for me. Could you share the kernel config that you used?
...
ok 65 vmalloc_oob
ok 66 vmap_tags
ok 67 vm_map_ram_tags
# vmalloc_percpu: EXPECTATION FAILED at mm/kasan/kasan_test.c:1785
Expected (u8)((u8)((u64)(c_ptr) >> 57)) < (u8)0x7f, but
(u8)((u8)((u64)(c_ptr) >> 57)) == 127 (0x7f)
(u8)0x7f == 127 (0x7f)
# vmalloc_percpu: EXPECTATION FAILED at mm/kasan/kasan_test.c:1785
Expected (u8)((u8)((u64)(c_ptr) >> 57)) < (u8)0x7f, but
(u8)((u8)((u64)(c_ptr) >> 57)) == 127 (0x7f)
(u8)0x7f == 127 (0x7f)
# vmalloc_percpu: EXPECTATION FAILED at mm/kasan/kasan_test.c:1785
Expected (u8)((u8)((u64)(c_ptr) >> 57)) < (u8)0x7f, but
(u8)((u8)((u64)(c_ptr) >> 57)) == 127 (0x7f)
(u8)0x7f == 127 (0x7f)
# vmalloc_percpu: EXPECTATION FAILED at mm/kasan/kasan_test.c:1785
Expected (u8)((u8)((u64)(c_ptr) >> 57)) < (u8)0x7f, but
(u8)((u8)((u64)(c_ptr) >> 57)) == 127 (0x7f)
(u8)0x7f == 127 (0x7f)
not ok 68 vmalloc_percpu
ok 69 match_all_not_assigned
ok 70 match_all_ptr_tag
...
# kasan: pass:62 fail:1 skip:8 total:71
# Totals: pass:62 fail:1 skip:8 total:71
I'm not sure how I'm supposed to hook in to the percpu allocator.
When running with hardware or firmware that doesn't support pointer
masking, the kernel still boots successfully:
kasan: test: Can't run KASAN tests with KASAN disabled
# kasan: # failed to initialize (-1)
not ok 1 kasan
If stack tagging is enabled but pointer masking is unsupported, an extra
change (patch 7) is required so all pointers to stack variables are
tagged with KASAN_TAG_KERENL and can be dereferenced. I'm not sure if
this change should be RISC-V specific or made more generic.
This series can be tested by applying patch series to LLVM[5], QEMU[6],
and OpenSBI[7].
[1]: https://github.com/riscv/riscv-j-extension/releases/download/pointer-masking-v1.0.0-rc2/pointer-masking-v1.0.0-rc2.pdf
[2]: https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/src/ext-firmware-features.adoc
[3]: https://github.com/riscv-non-isa/riscv-sbi-doc/pull/161
[4]: https://lore.kernel.org/linux-riscv/20240801033725.28816-1-samuel.holland@sifive.com/ (local)
[5]: https://github.com/SiFiveHolland/llvm-project/commits/up/riscv64-kernel-hwasan
[6]: https://lore.kernel.org/qemu-devel/20240511101053.1875596-1-me@deliversmonkey.space/ (local)
[7]: https://lists.infradead.org/pipermail/opensbi/2024-August/007244.html
Samuel Holland (7):
kasan: sw_tags: Use arithmetic shift for shadow computation
kasan: sw_tags: Check kasan_flag_enabled at runtime
kasan: sw_tags: Support tag widths less than 8 bits
riscv: Do not rely on KASAN to define the memory layout
riscv: Align the sv39 linear map to 16 GiB
riscv: Implement KASAN_SW_TAGS
kasan: sw_tags: Support runtime stack tagging control for RISC-V
Documentation/arch/riscv/vm-layout.rst | 10 ++---
Documentation/dev-tools/kasan.rst | 14 +++---
arch/arm64/Kconfig | 10 ++---
arch/arm64/include/asm/kasan.h | 6 ++-
arch/arm64/include/asm/memory.h | 8 ++++
arch/arm64/include/asm/uaccess.h | 1 +
arch/arm64/mm/kasan_init.c | 7 ++-
arch/riscv/Kconfig | 4 +-
arch/riscv/include/asm/cache.h | 4 ++
arch/riscv/include/asm/kasan.h | 29 +++++++++++-
arch/riscv/include/asm/page.h | 21 +++++++--
arch/riscv/include/asm/pgtable.h | 6 +++
arch/riscv/include/asm/tlbflush.h | 4 +-
arch/riscv/kernel/setup.c | 6 +++
arch/riscv/kernel/smpboot.c | 8 +++-
arch/riscv/lib/Makefile | 2 +
arch/riscv/lib/kasan_sw_tags.S | 61 ++++++++++++++++++++++++++
arch/riscv/mm/init.c | 2 +-
arch/riscv/mm/kasan_init.c | 30 ++++++++++++-
arch/riscv/mm/physaddr.c | 4 ++
include/linux/kasan-enabled.h | 15 +++----
include/linux/kasan-tags.h | 13 +++---
include/linux/kasan.h | 10 ++++-
mm/kasan/hw_tags.c | 10 -----
mm/kasan/kasan.h | 2 +
mm/kasan/sw_tags.c | 9 ++++
mm/kasan/tags.c | 10 +++++
scripts/Makefile.kasan | 5 +++
scripts/gdb/linux/mm.py | 5 ++-
29 files changed, 255 insertions(+), 61 deletions(-)
create mode 100644 arch/riscv/lib/kasan_sw_tags.S
--
2.45.1