[llvm-dev] HWASan and [Un]Interesting Allocas

Leonard Chan via llvm-dev llvm-dev at lists.llvm.org
Wed Apr 14 17:32:04 PDT 2021


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>


More information about the llvm-dev mailing list