This is an archive of the discontinued LLVM Phabricator instance.

[clang][Codegen] Introduce the disable_sanitizer_instrumentation attribute
ClosedPublic

Authored by glider on Aug 13 2021, 5:34 AM.

Details

Summary

The purpose of attribute((disable_sanitizer_instrumentation)) is to
prevent all kinds of sanitizer instrumentation applied to a certain
function, Objective-C method, or global variable.

The no_sanitize(...) attribute drops instrumentation checks, but may
still insert code preventing false positive reports. In some cases
though (e.g. when building Linux kernel with -fsanitize=kernel-memory
or -fsanitize=thread) the users may want to avoid any kind of
instrumentation.

Diff Detail

Event Timeline

glider created this revision.Aug 13 2021, 5:34 AM
glider requested review of this revision.Aug 13 2021, 5:34 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptAug 13 2021, 5:34 AM
glider updated this revision to Diff 366256.Aug 13 2021, 5:37 AM

Added a comment to clang/lib/CodeGen/CodeGenFunction.h

melver accepted this revision.Aug 13 2021, 5:52 AM
melver added inline comments.
llvm/include/llvm/AsmParser/LLToken.h
223

LLVM seems to just call them nofoo i.e. here it'd be nosanitizer_instrumentation.
I think Clang and LLVM are a bit inconsistent in their naming (no_foo vs nofoo) . See e.g. nosanitize_coverage which is similarly inconsistent yet consistent with other LLVM attrs.

This revision is now accepted and ready to land.Aug 13 2021, 5:52 AM
dvyukov accepted this revision.Aug 13 2021, 6:55 AM
dvyukov added inline comments.
clang/lib/CodeGen/CodeGenFunction.cpp
526

When is CurFuncDecl nullptr? Maybe we should look at definition in this case?

aaron.ballman requested changes to this revision.Aug 13 2021, 7:20 AM
aaron.ballman added inline comments.
clang/include/clang/Basic/AttrDocs.td
2611–2612

Has there been agreement that this isn't actually a bug? My understanding of no_sanitize is that it disables sanitizer support for a function or global. The documentation for that attribute says:

Use the ``no_sanitize`` attribute on a function or a global variable
declaration to specify that a particular instrumentation or set of
instrumentations should not be applied.

That sure reads like "do not instrument this at all" to me, and makes me think we don't need a second attribute that says "no, really, I mean it this time."

This revision now requires changes to proceed.Aug 13 2021, 7:20 AM
glider added a project: Restricted Project.Aug 13 2021, 8:53 AM
glider added inline comments.Aug 13 2021, 9:01 AM
clang/include/clang/Basic/AttrDocs.td
2611–2612

No, this isn't a bug, but might need to be better clarified in the docs.
ThreadSanitizer and MemorySanitizer do insert some instrumentation into ignore functions to prevent false positives:

ThreadSanitizer still instruments such functions to avoid false positives and provide meaningful stack traces.

(https://clang.llvm.org/docs/ThreadSanitizer.html#attribute-no-sanitize-thread)

and

MemorySanitizer may still instrument such functions to avoid false positives.

(https://clang.llvm.org/docs/MemorySanitizer.html#attribute-no-sanitize-memory)

This is the behavior people rely onto, although at this point I don't think no_sanitize(...) is the best name for attribute not disabling instrumentation completely.

aaron.ballman added inline comments.Aug 13 2021, 11:29 AM
clang/include/clang/Basic/AttrDocs.td
2611–2612

Thank you for the information!

Having two attributes with basically the same name to perform this functionality is confusing because users (understandably) will reach for the succinctly named one and make assumptions about what it does from the name.

One possibility would be to change no_sanitize to take an additional argument, as in: __attribute__((no_sanitize(fully_disable, "thread"))). Perhaps another solution would be to give the proposed attribute a more distinct name, like disable_sanitizer_instrumentation, sanitizer_instrumentation_disabled, or something else.

melver added inline comments.Aug 13 2021, 11:42 AM
clang/include/clang/Basic/AttrDocs.td
2611–2612

Last I looked at no_sanitize, it's quite awkward that it is an attribute that accepts arguments, because it makes it very hard to query for existence of attribute additions/changes with __has_attribute(). Given this new attribute is meant to be semantically quite different, the cleaner and less intrusive way with that in mind is to create a new attribute. Unless of course there's a nice way to make __has_attribute() work.

Here's another suggestion for name, which actually makes the difference between no_sanitize and the new one obvious: no_sanitize_any_permit_false_positives

At least it would semantically tell a user what might happen, which in turn would hopefully make them avoid this attribute (also because it's hard enough to type) unless they are absolutely sure.

aaron.ballman added inline comments.Aug 13 2021, 11:52 AM
clang/include/clang/Basic/AttrDocs.td
2611–2612

Given this new attribute is meant to be semantically quite different, the cleaner and less intrusive way with that in mind is to create a new attribute. Unless of course there's a nice way to make __has_attribute() work.

That sounds like good rationale for a separate attribute.

Here's another suggestion for name, which actually makes the difference between no_sanitize and the new one obvious: no_sanitize_any_permit_false_positives

At least it would semantically tell a user what might happen, which in turn would hopefully make them avoid this attribute (also because it's hard enough to type) unless they are absolutely sure.

That would certainly solve my concerns! Do you envision this being used far less often than no_sanitize? (That's my intuition, so I'm just double-checking that this isn't expected to be a popular replacement or something where the long name may be really undesirable.)

The new attribute should be very rare, and not something that a typical end user should even know about.
That's why I'd prefer if the name reflected how the attribute affects code generation rather than user-visible behavior: disable_sanitizer_instrumentation sounds perfect to me.

glider updated this revision to Diff 366570.Aug 16 2021, 2:12 AM

Renamed no_sanitizer_instrumentation to disable_sanitizer_instrumentation
Added bitcode attribute declaration and missing handling of the new attribute in switches.

glider marked 2 inline comments as done.Aug 16 2021, 2:19 AM
glider added inline comments.
clang/include/clang/Basic/AttrDocs.td
2611–2612

Yes, right now we only want to apply this attribute to a couple of critical places in the Linux kernel.
Other users may pop up in e.g. other kernels (NetBSD is using KMSAN) and maybe userspace programs, but we don't expect it to be popular, so having a lengthy attribute name is fine.

clang/lib/CodeGen/CodeGenFunction.cpp
526

I borrowed this check from ShouldInstrumentFunction(), it fires e.g. in the following case (borrowed from an existing regtest):

namespace rdar9445102 {
  class Rdar9445102 {
    public:
      Rdar9445102();
  };
}

static rdar9445102::Rdar9445102 s_rdar9445102Initializer;

We don't need to distinguish between the declaration and the definition, it happens automatically.
E.g. if we apply the attribute to either of them, the resulting function will have the disable_sanitizer_instrumentation LLVM attribute.

llvm/include/llvm/AsmParser/LLToken.h
223

Renamed the attribute to disable_sanitizer_instrumentation per Evgenii's comment.

glider marked 2 inline comments as done.Aug 16 2021, 2:28 AM
glider added a subscriber: krytarowski.

+krytarowski FYI

glider updated this revision to Diff 366591.Aug 16 2021, 4:47 AM

Updated patch description

glider retitled this revision from [clang][Codegen] Introduce the no_sanitizer_instrumentation attribute to [clang][Codegen] Introduce the disable_sanitizer_instrumentation attribute.Aug 16 2021, 4:49 AM
glider edited the summary of this revision. (Show Details)
aaron.ballman added inline comments.Aug 16 2021, 6:02 AM
clang/include/clang/Basic/Attr.td
2953

Do we want this to also appertain to GlobalVar and ObjCMethod so it's got the same subjects as no_sanitize?

clang/include/clang/Basic/AttrDocs.td
2611–2612

Fantastic, thank you for the confirmation!

clang/lib/CodeGen/CodeGenFunction.cpp
528–530
glider updated this revision to Diff 366845.Aug 17 2021, 2:54 AM

Address Aaron's comments

clang/include/clang/Basic/Attr.td
2953

Good catch, thank you. When adding the new attribute to ASan, we probably want it to mimic the behavior of no_sanitize("address")

clang/lib/CodeGen/CodeGenFunction.cpp
528–530

Right :)

aaron.ballman accepted this revision.Aug 17 2021, 6:41 AM

Clang bits LGTM with a few minor documentation nits.

clang/include/clang/Basic/AttrDocs.td
2608–2609

function, Objective-C method, or global variable.

2611–2612
This revision is now accepted and ready to land.Aug 17 2021, 6:41 AM
melver added inline comments.Aug 17 2021, 6:51 AM
llvm/include/llvm/IR/Attributes.td
90

There's this long-tail of changes required for adding new keywords to the IR. Have a look at https://reviews.llvm.org/D102772 -- things that I see currently missing are various tests etc.

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
629

There's also BitcodeReader, which needs something similar.

glider updated this revision to Diff 366887.Aug 17 2021, 6:51 AM

Fix the docs

glider edited the summary of this revision. (Show Details)Aug 17 2021, 6:52 AM
glider added inline comments.Aug 17 2021, 7:04 AM
llvm/include/llvm/IR/Attributes.td
90

It's ridiculous that we have so many handwritten files that list all the attributes (all those llvm.vim etc)
But I'll definitely need to update BitcodeReader and the tests. Thanks!

melver added inline comments.Aug 17 2021, 1:50 PM
clang/test/CodeGen/attr-no-sanitize-coverage.c
1 ↗(On Diff #366887)

This file says it's called attr-no-sanitize-coverage.c, I think that's the wrong name.

glider added inline comments.Aug 19 2021, 5:34 AM
llvm/include/llvm/Bitcode/LLVMBitCodes.h
674

Missing "_KIND_"

glider updated this revision to Diff 367480.Aug 19 2021, 6:20 AM

Updated BitcodeReader.cpp and several tests per Marco's suggestion
Renamed ATTR_DISABLE_SANITIZER_INSTRUMENTATION to ATTR_KIND_DISABLE_SANITIZER_INSTRUMENTATION

melver added inline comments.Aug 19 2021, 6:30 AM
llvm/lib/AsmParser/LLLexer.cpp
646

Do the tests pass?

There should also be the code that actually turns the token into the attribute in llvm/lib/AsmParser/LLParser.cpp

llvm/docs/LangRef.rst also needs a corresponding change.

llvm/docs/LangRef.rst also needs a corresponding change.

Right, will do. I thought LangRef was missing the sanitizer bits as well, and was planning to add them together, but apparently I was just looking for the wrong attributes.

llvm/lib/AsmParser/LLLexer.cpp
646

check-llvm and check-clang pass for me, check-all seems to choke on some unrelated bugs.

LLParser is using Tablegen now, no need to change it: https://github.com/llvm/llvm-project/blob/main/llvm/lib/AsmParser/LLParser.cpp#L1247

melver accepted this revision.Aug 19 2021, 7:11 AM

LGTM
with the LangRef change.

Thanks!

llvm/lib/AsmParser/LLLexer.cpp
646

Ah, nice, I missed that.

glider updated this revision to Diff 367759.Aug 20 2021, 4:04 AM

Updated LangRef.rst

melver accepted this revision.Aug 20 2021, 4:06 AM

llvm/docs/LangRef.rst also needs a corresponding change.

Right, will do. I thought LangRef was missing the sanitizer bits as well, and was planning to add them together, but apparently I was just looking for the wrong attributes.

I've added the function attribute description to LangRef. Looks like global attributes aren't listed explicitly.

This revision was landed with ongoing or failed builds.Aug 20 2021, 5:06 AM
This revision was automatically updated to reflect the committed changes.