This is an archive of the discontinued LLVM Phabricator instance.

hwasan: Support for outlined checks in the Linux kernel.
ClosedPublic

Authored by pcc on Oct 29 2020, 1:58 PM.

Details

Summary

Add support for match-all tags and GOT-free runtime calls, which
are both required for the kernel to be able to support outlined
checks. This requires extending the access info to let the backend
know when to enable these features. To make the code easier to maintain
introduce an enum with the bit field positions for the access info.

Allow outlined checks to be enabled with -mllvm
-hwasan-inline-all-checks=0. Kernels that contain runtime support for
outlined checks may pass this flag. Kernels lacking runtime support
will continue to link because they do not pass the flag. Old versions
of LLVM will ignore the flag and continue to use inline checks.

With a separate kernel patch [1] I measured the code size of defconfig
+ tag-based KASAN, as well as boot time (i.e. time to init launch)
on a DragonBoard 845c with an Android arm64 GKI kernel. The results
are below:

code size    boot time

before 92824064 6.18s
after 38822400 6.65s

[1] https://linux-review.googlesource.com/id/I1a30036c70ab3c3ee78d75ed9b87ef7cdc3fdb76

Depends on D90425

Diff Detail

Event Timeline

pcc created this revision.Oct 29 2020, 1:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 29 2020, 1:58 PM
pcc requested review of this revision.Oct 29 2020, 1:58 PM
pcc added inline comments.Oct 29 2020, 2:45 PM
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
361

This was meant to stay where it was (I had originally moved it here because I had the match-all check first, but benchmarking revealed that moving the match-all check after the shadow check was faster). I'll move it back in the next upload.

pcc updated this revision to Diff 301775.Oct 29 2020, 3:38 PM

Revert unnecessary change, fix tests

eugenis added inline comments.Oct 29 2020, 5:18 PM
llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
505

I don't understand the impact of this diff.
Now, Recover==true no longer overrides an explicit -hwasan-inline-all-checks=1.
Why?
Is that what prevented outlining in the kernel before?

510

ClMatchTag & 0xF
either here or when constructing AccessInfo

hctim added inline comments.Oct 29 2020, 5:36 PM
llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h
40

why not enum HWASanAccessInfo { ...?

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
397

IIUC, this is being optimised to

lsr x16, x1, #56
cmp x16, MatchAllTag
b.eq .ret

and this seems clearer to me. Is it possible to update the codegen here to be the same?

514

B instead of BR implies that the kernel will never return from __hwasan_tag_mismatch (which is still reachable as it looks like it's still possible for the kernel to compile without short granules). Does this assumption always hold?

llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
796

can we declare this as a const kAccessInfoRuntimeMask (and elsewhere)?

pcc added inline comments.Oct 29 2020, 6:21 PM
llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h
40

Because we don't want these to go straight into the llvm namespace. enum class avoids this but then the enumerators would be more awkward to work with in this context (e.g. need to be static_casted into integers).

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
397

There is no AArch64::LSR or AArch64::CMP. When the assembler sees one of these it rewrites the instruction into the more general form (i.e. UBFM, SUBS). So we can't make it the same.

514

B instead of BR implies that the kernel will never return from __hwasan_tag_mismatch

No it doesn't. With either B or BR x30 is not overwritten so a RET in __hwasan_tag_mismatch would go straight back to the caller of __hwasan_check_*. This is how tail calls work for example.

llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
505

Yes, outlining was being prevented in the kernel because it always had Recover enabled (see addKernelHWAddressSanitizerPasses in clang). What this diff lets you do is say -hwasan-inline-all-checks=0 and as a result you are promising that your runtime supports recovery from outlined checks.

510

You mean ClMatchAllTag & 0xFF, right? This isn't MTE :)

It is unnecessary because the field is a uint8_t but I suppose we could avoid an implicit truncation that way.

796

Okay, I'll add it to HWAddressSanitizer.h.

eugenis accepted this revision.Oct 30 2020, 12:42 PM

LGTM

llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
510

Right, I missed that. I was concerned about overwriting other fields of AccessInfo if the tag value is too large.

This revision is now accepted and ready to land.Oct 30 2020, 12:42 PM
This revision was landed with ongoing or failed builds.Oct 30 2020, 2:26 PM
This revision was automatically updated to reflect the committed changes.