This is an archive of the discontinued LLVM Phabricator instance.

[ASan][libcxx] A way to turn off annotations for containers with a specific allocator
ClosedPublic

Authored by AdvenamTacet on Mar 8 2023, 4:19 PM.

Details

Summary

This revision is part of our efforts to support container annotations with (almost) every allocator.
That patch is necessary to enable support for most annotations (D136765). Without a way to turn off annotations, it's hard to use ASan with area allocators (no calls to destructors).

This is an answer to a request about it. This patch provides a solution to the aforementioned issue by introducing a new template structure __asan_annotate_container_with_allocator, which allows the disabling of container annotations for a specific allocator.

This patch also introduces _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS FTM.

To turn off annotations, it is sufficient to create a template specialization with a false value using a Unary Type Trait.

The proposed structure is being used in the code enabling annotations for all allocators in std::vector, std::basic_string, and std::deque. (D136765 D146214 D146815)

Possibility to do it was added to ASan API in rGdd1b7b797a116eed588fd752fbe61d34deeb24e4 commit.

For context on not calling a destructor, look at https://eel.is/c++draft/basic.life#5 and notes there, you may also read a discussion in D136765.

Diff Detail

Event Timeline

AdvenamTacet created this revision.Mar 8 2023, 4:19 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 8 2023, 4:19 PM
AdvenamTacet requested review of this revision.Mar 8 2023, 4:19 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 8 2023, 4:19 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript
AdvenamTacet retitled this revision from A way to turn off annotations for containers with a specific allocator to [ASan][libcxx] A way to turn off annotations for containers with a specific allocator.Mar 8 2023, 4:26 PM
AdvenamTacet added a project: Restricted Project.
AdvenamTacet added a subscriber: Restricted Project.
hans added a comment.Mar 9 2023, 2:43 AM

Thanks for adding this!

I think for https://crbug.com/1420967 we will need this. Unpoisoning is not an option there (I think?) since other code will access the memory buffer while the vector is still "active".

libcxx/docs/UsingLibcxx.rst
527

Could you please include a code example which shows how to do the specialization?

Also, will it be possible to write this in a way that works both with libc++ versions that have and don't have this change?

AdvenamTacet marked an inline comment as done.

This update adds examples how to turn off annotations in a simple way.

I was also thinking about creating a macro _LIBCPP_ASAN_ANNOTATE_CONTAINER_WITH_ALLOCATOR, but I don't fully like that idea.
Let me know if you think it's a good change.

#define _LIBCPP_ASAN_ANNOTATE_CONTAINER_WITH_ALLOCATOR(ALLOC, VALUE) template <class T> \
    struct __asan_annotate_container_with_allocator< ALLOC<T> > { \
        static bool const value = VALUE; \
    };

Then description would be:

For simple allocators with only one template parameter, it's possible to use
``_LIBCPP_ASAN_ANNOTATE_CONTAINER_WITH_ALLOCATOR`` macro.

.. code-block:: cpp

  _LIBCPP_ASAN_ANNOTATE_CONTAINER_WITH_ALLOCATOR(user_allocator, false);
AdvenamTacet added inline comments.Mar 16 2023, 1:47 AM
libcxx/docs/UsingLibcxx.rst
527

I added examples. I hope those are helpful. If you believe that another example is necessary as well, let me know.

Also, will it be possible to write this in a way that works both with libc++ versions that have and don't have this change?

Possibly a macro would be answer to that, I suggested one in an update comment. But it should be possible to solve easily with libc++ version number as well. I don't really like the idea of creating a macro here.

hans added inline comments.Mar 16 2023, 4:06 AM
libcxx/docs/UsingLibcxx.rst
521

When this lands, it should probably have a link from the release notes.

524

Perhaps the "ASan annotations for containers" could be a link to https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow for those who are not familiar with the feature.

527

This is great, thanks!

I'd suggest writing the example in a way that's portable, i.e. that will work both with libc++ versions which do and do not have this feature, as well as other standard libraries.

In order to do that, I guess we'll need some kind of feature test macro. I don't think checking the libc++ version number is a good solution as it's not fine grained enough. I'm guessing libc++ has some kind of mechanism for this already similar to the standard feature test macros.

530

It would be good to have an example (not necessarily in code) of why an allocator would not work with this, and either code or a link to how to unpoison the memory.

AdvenamTacet marked 2 inline comments as done.

This update extends description with:

  • Why one may want to turn off annotations,
  • and what else one may do (unpoisoning, turning off instrumentation).
AdvenamTacet added inline comments.Mar 20 2023, 11:01 AM
libcxx/docs/UsingLibcxx.rst
527

I don't really see a good way to do it and believe that relaying on libc++ version seems the best option. If @philnik or @ldionne think that some macro should be created, I will do it. Just I have to know what macro exactly.

Rebase to apply to the newest commit from main.

hans added inline comments.Mar 21 2023, 8:15 AM
libcxx/docs/UsingLibcxx.rst
527

A version check won't work for consumers of libc++ trunk, since there are versions both with and without this template that have the same _LIBCPP_VERSION.

I think we need a macro or other feature flag, or some mechanism that works both before and after this change (instead of a class template, could we do something based on function overload resolution with the allocator type work?)

AdvenamTacet added a subscriber: EricWF.

This update moves a check for all allocators support to libcxx/include/__memory/allocator_traits.h.
Similar changes has to be made in paches turning annotations for all allocators in vector/string and andded in deque patch.

This idea was suggested by @EricWF in D146214, I think it's a good idea. String/vector/deque code will be simplified.

philnik requested changes to this revision.Mar 25 2023, 4:02 AM
philnik added 1 blocking reviewer(s): ldionne.
philnik added inline comments.
libcxx/docs/UsingLibcxx.rst
524–530
532–552

I don't think it makes sense to disable it for specific types, since I don't see a case where it doesn't purely depend on the allocator whether containers should be annotated, so I don't think we want to advertise that here. We also probably don't want people to poke around in asan annotations if they don't know how to specialize a class.

554–568

This is (mostly) incorporated into my description change above, so nothing should be lost by removing this.

564–566

From what I can tell [[clang::no_sanitize("address")]] is quite fiddly, so I wouldn't recommend it here.

libcxx/include/__memory/allocator_traits.h
26

You shouldn't include this here.

406–413

IMO we should require this to be a Cpp17UnaryTypeTrait.

This revision now requires changes to proceed.Mar 25 2023, 4:02 AM
AdvenamTacet added inline comments.Mar 27 2023, 4:02 AM
libcxx/include/__memory/allocator_traits.h
406–413

@phillnik does it work with C++03? It will be used inside std::vector etc. so it should work with every supported standard.

It's nice to suggest it in libcxx/docs/UsingLibcxx.rst, but I don't think we can use it here.

philnik added inline comments.Mar 27 2023, 4:06 AM
libcxx/include/__memory/allocator_traits.h
406–413

Yes, it works in our C++03. We have lots of extensions there (it's basically anything that can be implemented in C++03 with clang extensions that was added in C++11).

AdvenamTacet marked 7 inline comments as done.

This update introduces changes suggested in code review:

  • use of Cpp17UnaryTypeTrait,
  • description update.
libcxx/docs/UsingLibcxx.rst
564–566

I think it's a nice option, but I am also strongly biased. And that's true that turning off instrumentation may be really tricky.
I removed it, but if someone thinks it would be good to describe every option, I think it may be rediscussed. I'm fine with it and without it.

What else can I do?
-------------------
If you know in which functions poisoned memory is accessed, you can
`turn off instrumentation inside a function with attribute <https://clang.llvm.org/docs/AddressSanitizer.html#disabling-instrumentation-with-attribute-no-sanitize-address>`
``__attribute__((no_sanitize("address")))``. Notice that those functions should not modify the container.
hans added inline comments.Mar 28 2023, 3:15 AM
libcxx/docs/UsingLibcxx.rst
535

Did this lose the template line above, or am I missing something?

I also still think the example needs to be made portable.

This update adds missing template <class T> in the example.

*Adds missing space.

AdvenamTacet marked an inline comment as done and an inline comment as not done.Mar 29 2023, 1:52 AM
AdvenamTacet added inline comments.
libcxx/docs/UsingLibcxx.rst
535

Yes, thank you! I fixed it.

I also still think the example needs to be made portable.

As there is a separate thread about it, I marked this comment as done.

AdvenamTacet marked an inline comment as done.

This update:

  • resolves a problem with C++03,
  • tries to sole a problem with g++ compilation.
ldionne accepted this revision as: ldionne.Mar 30 2023, 2:07 PM

I'm not super happy with this patch, I wish it weren't necessary. But it seems like the arena case where destructors aren't actually called indeed requires it and I can't think of an easy way to support this otherwise, so LGTM. I will let @philnik give the final approval, but don't consider it blocked on me.

AdvenamTacet edited the summary of this revision. (Show Details)Mar 30 2023, 2:44 PM
hans requested changes to this revision.Mar 31 2023, 12:25 PM

I still think we need to address how code which builds against different c++ standard libraries are going to realistically use this. As written, the instructions only work with libc++ versions containing this patch -- how is a developer going to detect that?

This revision now requires changes to proceed.Mar 31 2023, 12:25 PM

This update:

  • adds _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS FTM,
  • updates the description,
  • updates the example.

As discussed on Discord, #libcxx.

@hans I hope this also answers your concerns.

AdvenamTacet edited the summary of this revision. (Show Details)Apr 1 2023, 5:51 AM
AdvenamTacet edited the summary of this revision. (Show Details)Apr 1 2023, 6:00 AM
hans accepted this revision.Apr 3 2023, 1:30 AM

This update:

  • adds _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS FTM,
  • updates the description,
  • updates the example.

As discussed on Discord, #libcxx.

@hans I hope this also answers your concerns.

Yes it does. Thanks!

libcxx/docs/UsingLibcxx.rst
538

Should it be std::false_type?

philnik accepted this revision.Apr 3 2023, 4:03 AM

LGTM with nits addressed.

libcxx/docs/UsingLibcxx.rst
538

yes

libcxx/include/__memory/allocator_traits.h
420
This revision is now accepted and ready to land.Apr 3 2023, 4:03 AM
AdvenamTacet marked 6 inline comments as done.

This update addresses nits.

This update solves the merge conflict with the newest commit.

This revision was landed with ongoing or failed builds.May 4 2023, 2:17 PM
This revision was automatically updated to reflect the committed changes.