This patch adds nosantize metadata to memory access instructions inserted by gcov emitProfileNotes(), making sanitizers skip these instructions when gcov and sanitizer are used together.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Thanks for the patch! Why do we want to skip sanitizing these loads and stores?
Also, gocv is misspelled in the commit description, please fix that up.
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | ||
---|---|---|
150–152 | This looks the same as SanitizerMetadata::disableSanitizerForInstruction and ModuleSanitizerCoverage::SetNoSanitizeMetadata. Rather than define a third copy, why not declare it as a new method on Instruction and define it in llvm/lib/IR/Metadata.cpp, then use it in all three places? | |
926–936 | Please use Instruction * rather than auto. |
Thanks for you review!
Why do we want to skip sanitizing these loads and stores?
When use asan and gcov together, asan will instrument the loads and stores inserted by gcov which increases the code size a lot.
As the loads and stores inserted by gcov are unlikey to have bugs, so I add nosanitize metadata to these loads and stores like we do in SanitizerCoverage.
Also, gocv is misspelled in the commit description, please fix that up.
Thanks for pointing this.
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | ||
---|---|---|
150–152 | Send https://reviews.llvm.org/D150632 which adds Instruction::setNoSanitizeMetadata() and use it in SanitizerMetadata and SanitizerCoverage as suggested. |
Hmm...that I'm less comfortable with approving. Personally, I feel that coverage and sanitizers don't mix well (perhaps due to such code size increases). If you want low overhead coverage, disable your sanitizers! Perhaps this makes more sense in the context of HWASAN where you might consider enabling a sanitizer always, even in production builds?
I guess I'm worried about __llvm_gcov_ctr becoming some kind of vector for attack.
Though, I guess you wouldn't ship coverage enabled in production.
llvm/test/Transforms/GCOVProfiling/nosanitize.ll | ||
---|---|---|
2 | Is this run line necessary? | |
4 | please add a comment about the intent of this test; something along the lines of "the intent of this test is to verify that the loads, stores, and atomicrmw adds for gcov are marked nosanitize. |
Though, I guess you wouldn't ship coverage enabled in production.
Sure.
I guess I'm worried about __llvm_gcov_ctr becoming some kind of vector for attack.
__llvm_gcov_ctr global variable is not instrumented by asan, see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp#L1184
Hmm...that I'm less comfortable with approving.
It's ok, if so, I can abandon this patch :)
Or maybe we can add an option gcov-nosanitize?
llvm/test/Transforms/GCOVProfiling/nosanitize.ll | ||
---|---|---|
2 | Yes, it is for don't writing a.gcno in CWD. See other GCOVProfiling testcase (e.g. atomic-counter.ll, kcfi.ll) |
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | ||
---|---|---|
925–926 | Define Instruction *Inst outside before if. Call Inst->setNoSanitizemetadata() just once after if. Add a comment // Disable sanitizers to decrease size bloat. We don't expect sanitizers to catch interesting issues. | |
llvm/test/Transforms/GCOVProfiling/nosanitize.ll | ||
3 | ; RUN: rm -rf %t && mkdir %t && cd %t clean up the directory which may be clobbered. |
I think this patch is fine. __llvm_gcov_ctr is an internal variable and accessing doesn't use indirection, so no risk of hijection.
I don't recommend mixing gcov and sanitizers (e.g. --coverage -fsanitize=hwaddress), but if a user does this, disabling instrumentation for __llvm_gcov_ctr provides some size benefit.
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | ||
---|---|---|
925–926 | It's either 1 or 2 instructions that need the metadata set. The comment SGTM though that this is intentional/deliberate and not a bug. |
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | ||
---|---|---|
925–926 |
There are 2 instructions in else block, so I think can not call Inst->setNoSanitizemetadata() just once after if. |
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | ||
---|---|---|
925–926 | My idea is the factor out one instruction to apply Inst->setNoSanitizemetadata(). The else branch has one more instruction. |
This looks the same as SanitizerMetadata::disableSanitizerForInstruction and ModuleSanitizerCoverage::SetNoSanitizeMetadata. Rather than define a third copy, why not declare it as a new method on Instruction and define it in llvm/lib/IR/Metadata.cpp, then use it in all three places?