[RFC PATCH 0/7] kasan: RISC-V support for KASAN_SW_TAGS using pointer masking

Samuel Holland samuel.holland at sifive.com
Wed Aug 14 01:55:28 PDT 2024


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.

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:

      ...
      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/
[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/
[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




More information about the linux-riscv mailing list