[adding KASAN folk]
There appears to be a GCC bug here, analysis below.
The issues with clang are unrelated, and I will follow up with a
separate mail for those.
On Sat, Aug 31, 2024 at 06:52:52PM +0100, Marc Zyngier wrote:
It looks like what's happening here is:
(1) With CONFIG_KASAN_SW_TAGS=y we pass the compiler
`-fsanitize=kernel-hwaddress`.
(2) When GCC is passed `-fsanitize=hwaddress` or
`-fsanitize=kernel-hwaddress` it ignores
`__attribute__((no_sanitize_address))`, and instruments functions we
require are not instrumented.
I believe this is a compiler bug, as there doesn't seem to be a
separate attribute to prevent instrumentation in this mode.
(3) In this config, smp_build_mpidr_hash() gets inlined into
setup_arch(), and as setup_arch() is instrumented, all of the stack
variables for smp_build_mpidr_hash() are initialized at the start of
setup_arch(), with calls to __hwasan_tag_memory().
At this point, we are using the early shadow (where a single page of
shadow is used for all memory).
(4) In setup_arch(), we call kasan_init() to transition from the early
shadow to the runtime shadow. This replaces the early shadow memory
with new shadow memory initialized to KASAN_SHADOW_INIT (0xFE AKA
KASAN_TAG_INVALID), including the shadow for the stack.
(5) Once the CPU returns back into setup_arch(), it's using the new
shadow initialized to 0xFE. Subsequent stack accesses which check
the shadow see 0xFE in the shadow, and fault. Note that in the dump
of the shadow above, the shadow around ffff800086867d80 and above is
all 0xFE, while below that functions have managed to clear the
shadow.
Compiler test case below. Note that this demonstrates the compiler
ignores `__attribute__((no_sanitize_address))` regardless of
KASAN_STACK, so KASAN_SW_TAGS is generally broken with GCC. All versions
I tried were broken, from 11.3.0 to 14.2.0 inclusive.
I think we have to disable KASAN_SW_TAGS with GCC until this is fixed.
| [mark@lakrids:/mnt/data/tests/kasan-tags]% cat test.c
| #define __nsa __attribute__((no_sanitize_address))
|
| long __nsa load_long(long *ptr)
| {
| return *ptr;
| }
|
| void __nsa store_long(long *ptr, long val)
| {
| *ptr = val;
| }
|
| void extern_func(void);
|
| long __nsa stack_func(void)
| {
| volatile long val = 0;
| extern_func();
| return val;
| }
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 12.1.0 aarch64-linux-gcc -c test.c -O2 -fsanitize=kernel-hwaddress
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 14.2.0 aarch64-linux-objdump -d test.o
|
| test.o: file format elf64-littleaarch64
|
|
| Disassembly of section .text:
|
| 0000000000000000 <load_long>:
| 0: a9be7bfd stp x29, x30, [sp, #-32]!
| 4: 910003fd mov x29, sp
| 8: f9000bf3 str x19, [sp, #16]
| c: aa0003f3 mov x19, x0
| 10: 94000000 bl 0 <__hwasan_load8_noabort>
| 14: f9400260 ldr x0, [x19]
| 18: f9400bf3 ldr x19, [sp, #16]
| 1c: a8c27bfd ldp x29, x30, [sp], #32
| 20: d65f03c0 ret
|
| 0000000000000024 <store_long>:
| 24: a9be7bfd stp x29, x30, [sp, #-32]!
| 28: 910003fd mov x29, sp
| 2c: a90153f3 stp x19, x20, [sp, #16]
| 30: aa0003f3 mov x19, x0
| 34: aa0103f4 mov x20, x1
| 38: 94000000 bl 0 <__hwasan_store8_noabort>
| 3c: f9000274 str x20, [x19]
| 40: a94153f3 ldp x19, x20, [sp, #16]
| 44: a8c27bfd ldp x29, x30, [sp], #32
| 48: d65f03c0 ret
| 4c: d503201f nop
|
| 0000000000000050 <stack_func>:
| 50: a9be7bfd stp x29, x30, [sp, #-32]!
| 54: 910003fd mov x29, sp
| 58: f9000fff str xzr, [sp, #24]
| 5c: 94000000 bl 0 <extern_func>
| 60: f9400fe0 ldr x0, [sp, #24]
| 64: a8c27bfd ldp x29, x30, [sp], #32
| 68: d65f03c0 ret
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 12.1.0 aarch64-linux-gcc -c test.c -O2 -fsanitize=kernel-hwaddress --param hwasan-instrument-stack=1
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 14.2.0 aarch64-linux-objdump -d test.o
|
| test.o: file format elf64-littleaarch64
|
|
| Disassembly of section .text:
|
| 0000000000000000 <load_long>:
| 0: a9be7bfd stp x29, x30, [sp, #-32]!
| 4: 910003fd mov x29, sp
| 8: f9000bf3 str x19, [sp, #16]
| c: aa0003f3 mov x19, x0
| 10: 94000000 bl 0 <__hwasan_load8_noabort>
| 14: f9400260 ldr x0, [x19]
| 18: f9400bf3 ldr x19, [sp, #16]
| 1c: a8c27bfd ldp x29, x30, [sp], #32
| 20: d65f03c0 ret
|
| 0000000000000024 <store_long>:
| 24: a9be7bfd stp x29, x30, [sp, #-32]!
| 28: 910003fd mov x29, sp
| 2c: a90153f3 stp x19, x20, [sp, #16]
| 30: aa0003f3 mov x19, x0
| 34: aa0103f4 mov x20, x1
| 38: 94000000 bl 0 <__hwasan_store8_noabort>
| 3c: f9000274 str x20, [x19]
| 40: a94153f3 ldp x19, x20, [sp, #16]
| 44: a8c27bfd ldp x29, x30, [sp], #32
| 48: d65f03c0 ret
| 4c: d503201f nop
|
| 0000000000000050 <stack_func>:
| 50: a9bd7bfd stp x29, x30, [sp, #-48]!
| 54: d2800202 mov x2, #0x10 // #16
| 58: 9100c3e0 add x0, sp, #0x30
| 5c: 910003fd mov x29, sp
| 60: d378fc01 lsr x1, x0, #56
| 64: 910083e0 add x0, sp, #0x20
| 68: 11000821 add w1, w1, #0x2
| 6c: f9000bf3 str x19, [sp, #16]
| 70: 94000000 bl 0 <__hwasan_tag_memory>
| 74: d2e04000 mov x0, #0x200000000000000 // #144115188075855872
| 78: 8b2063e0 add x0, sp, x0
| 7c: f900101f str xzr, [x0, #32]
| 80: 94000000 bl 0 <extern_func>
| 84: d2e04000 mov x0, #0x200000000000000 // #144115188075855872
| 88: 8b2063e0 add x0, sp, x0
| 8c: d2800202 mov x2, #0x10 // #16
| 90: 52800001 mov w1, #0x0 // #0
| 94: f9401013 ldr x19, [x0, #32]
| 98: 910083e0 add x0, sp, #0x20
| 9c: 94000000 bl 0 <__hwasan_tag_memory>
| a0: aa1303e0 mov x0, x19
| a4: f9400bf3 ldr x19, [sp, #16]
| a8: a8c37bfd ldp x29, x30, [sp], #48
| ac: d65f03c0 ret
| [mark@lakrids:/mnt/data/tests/kasan-tags]%
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 12.1.0 aarch64-linux-gcc -c test.c -O2 -fsanitize=hwaddress
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 14.2.0 aarch64-linux-objdump -d test.o
|
| test.o: file format elf64-littleaarch64
|
|
| Disassembly of section .text:
|
| 0000000000000000 <load_long>:
| 0: a9be7bfd stp x29, x30, [sp, #-32]!
| 4: 910003fd mov x29, sp
| 8: f9000bf3 str x19, [sp, #16]
| c: aa0003f3 mov x19, x0
| 10: 94000000 bl 0 <__hwasan_load8>
| 14: f9400260 ldr x0, [x19]
| 18: f9400bf3 ldr x19, [sp, #16]
| 1c: a8c27bfd ldp x29, x30, [sp], #32
| 20: d65f03c0 ret
|
| 0000000000000024 <store_long>:
| 24: a9be7bfd stp x29, x30, [sp, #-32]!
| 28: 910003fd mov x29, sp
| 2c: a90153f3 stp x19, x20, [sp, #16]
| 30: aa0003f3 mov x19, x0
| 34: aa0103f4 mov x20, x1
| 38: 94000000 bl 0 <__hwasan_store8>
| 3c: f9000274 str x20, [x19]
| 40: a94153f3 ldp x19, x20, [sp, #16]
| 44: a8c27bfd ldp x29, x30, [sp], #32
| 48: d65f03c0 ret
| 4c: d503201f nop
|
| 0000000000000050 <stack_func>:
| 50: a9bd7bfd stp x29, x30, [sp, #-48]!
| 54: 910003fd mov x29, sp
| 58: f9000bf3 str x19, [sp, #16]
| 5c: 94000000 bl 0 <__hwasan_generate_tag>
| 60: 9100c3e1 add x1, sp, #0x30
| 64: d2800202 mov x2, #0x10 // #16
| 68: aa00e033 orr x19, x1, x0, lsl #56
| 6c: 910083e0 add x0, sp, #0x20
| 70: d378fe61 lsr x1, x19, #56
| 74: 94000000 bl 0 <__hwasan_tag_memory>
| 78: f81f027f stur xzr, [x19, #-16]
| 7c: 94000000 bl 0 <extern_func>
| 80: f85f0273 ldur x19, [x19, #-16]
| 84: 910083e0 add x0, sp, #0x20
| 88: d2800202 mov x2, #0x10 // #16
| 8c: 52800001 mov w1, #0x0 // #0
| 90: 94000000 bl 0 <__hwasan_tag_memory>
| 94: aa1303e0 mov x0, x19
| 98: f9400bf3 ldr x19, [sp, #16]
| 9c: a8c37bfd ldp x29, x30, [sp], #48
| a0: d65f03c0 ret
|
| Disassembly of section .text.startup:
|
| 0000000000000000 <_sub_I_00099_0>:
| 0: 14000000 b 0 <__hwasan_init>
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 12.1.0 aarch64-linux-gcc -c test.c -O2 -fsanitize=hwaddress --param hwasan-instrument-stack=1
| [mark@lakrids:/mnt/data/tests/kasan-tags]% usekorg 14.2.0 aarch64-linux-objdump -d test.o
|
| test.o: file format elf64-littleaarch64
|
|
| Disassembly of section .text:
|
| 0000000000000000 <load_long>:
| 0: a9be7bfd stp x29, x30, [sp, #-32]!
| 4: 910003fd mov x29, sp
| 8: f9000bf3 str x19, [sp, #16]
| c: aa0003f3 mov x19, x0
| 10: 94000000 bl 0 <__hwasan_load8>
| 14: f9400260 ldr x0, [x19]
| 18: f9400bf3 ldr x19, [sp, #16]
| 1c: a8c27bfd ldp x29, x30, [sp], #32
| 20: d65f03c0 ret
|
| 0000000000000024 <store_long>:
| 24: a9be7bfd stp x29, x30, [sp, #-32]!
| 28: 910003fd mov x29, sp
| 2c: a90153f3 stp x19, x20, [sp, #16]
| 30: aa0003f3 mov x19, x0
| 34: aa0103f4 mov x20, x1
| 38: 94000000 bl 0 <__hwasan_store8>
| 3c: f9000274 str x20, [x19]
| 40: a94153f3 ldp x19, x20, [sp, #16]
| 44: a8c27bfd ldp x29, x30, [sp], #32
| 48: d65f03c0 ret
| 4c: d503201f nop
|
| 0000000000000050 <stack_func>:
| 50: a9bd7bfd stp x29, x30, [sp, #-48]!
| 54: 910003fd mov x29, sp
| 58: f9000bf3 str x19, [sp, #16]
| 5c: 94000000 bl 0 <__hwasan_generate_tag>
| 60: 9100c3e1 add x1, sp, #0x30
| 64: d2800202 mov x2, #0x10 // #16
| 68: aa00e033 orr x19, x1, x0, lsl #56
| 6c: 910083e0 add x0, sp, #0x20
| 70: d378fe61 lsr x1, x19, #56
| 74: 94000000 bl 0 <__hwasan_tag_memory>
| 78: f81f027f stur xzr, [x19, #-16]
| 7c: 94000000 bl 0 <extern_func>
| 80: f85f0273 ldur x19, [x19, #-16]
| 84: 910083e0 add x0, sp, #0x20
| 88: d2800202 mov x2, #0x10 // #16
| 8c: 52800001 mov w1, #0x0 // #0
| 90: 94000000 bl 0 <__hwasan_tag_memory>
| 94: aa1303e0 mov x0, x19
| 98: f9400bf3 ldr x19, [sp, #16]
| 9c: a8c37bfd ldp x29, x30, [sp], #48
| a0: d65f03c0 ret
|
| Disassembly of section .text.startup:
|
| 0000000000000000 <_sub_I_00099_0>:
| 0: 14000000 b 0 <__hwasan_init>
Mark.