Leonard Chan via llvm-dev
2021-Apr-15 00:32 UTC
[llvm-dev] HWASan and [Un]Interesting Allocas
Hi all, I'm having trouble wrapping my head around hwasan instrumentation for specific alloca instructions. For the given (minimized reproducer) C code: ``` void func(const char *); void trace(const char *str, ...) { func(str); } ``` I can generate the following IR: ``` ; Compiled (from a near ToT clang) with: ; clang /tmp/test.c -fsanitize=hwaddress --target=aarch64-unknown-fuchsia -S -o - -mllvm --hwasan-instrument-with-calls=1 -mllvm --hwasan-generate-tags-with-calls=1 -emit-llvm ; Function Attrs: noinline nounwind optnone sanitize_hwaddress shadowcallstack sspstrong uwtable define dso_local void @trace(i8* %0, ...) #0 { %2 = call i8* asm "", "=r,0"(i8* null) %3 = alloca i8*, align 8 %4 = ptrtoint i8** %3 to i64 call void @__hwasan_store8(i64 %4) store i8* %0, i8** %3, align 8 %5 = ptrtoint i8** %3 to i64 call void @__hwasan_load8(i64 %5) %6 = load i8*, i8** %3, align 8 call void @func(i8* %6) #2 ret void } ``` This IR contains one load and store check on the `%3 = alloca i8*, align 8`. The thing that confuses me is* the alloca in this instance isn't tagged, nor is shadow memory setup for it, but we still check a load/store on it.* My understanding is that if shadow isn't set up with a tag, then hwasan will likely throw an error on the first __hwasan_store8 from comparing an untagged pointer against a value at an arbitrary shadow address which could be non-zero from some previous allocation. The above C code is a minimal reproducer for the case I ran into which I think might be a false-negative. In the pass, it looks like hwasan will only instrument an alloca based on `isInterestingAlloca()`, which is dependent on `isAllocaPromotable()` returning false. All other requirements for `isInterestingAlloca()` seem to be fulfilled except for this. Based on comments, it looks like we only want to instrument an alloca that is not promotable to a register. This looks to be the case since the `alloca` seems to be lowered to space on the stack: ``` trace: sub sp, sp, #256 str x30, [x18], #8 stp x29, x30, [sp, #240] * add x29, sp, #240 str x0, [sp, #8]*... * sub x0, x29, #16* bl __hwasan_store8 // x29 is offset into stack * ldr x8, [sp, #8] stur x8, [x29, #-16] // Load original arg onto stack* ... ``` At a glance, it looks like the store into the alloca isn't an actual bug, so we shouldn't need to instrument it. I'm thinking perhaps this is an issue regarding where to add load/store checks. HWASan has a similar function `getInterestingMemoryOperands()` for determining interesting places to add checks before loads/stores, but it doesn't seem to specifically if a load/store operand accepts one of these ignored allocas. Should there be extra checks to ensure that these allocas aren't checked? Thanks, Leonard -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210414/6b20d296/attachment.html>