This is an archive of the discontinued LLVM Phabricator instance.

[sanitizer_common][test] Fix CompactRingBuffer.int64 munmap error
Needs ReviewPublic

Authored by XiaodongLoong on Jan 18 2022, 7:32 PM.

Details

Summary

The munmap syscall expects a page size aligned address, but hard
coded 4k page size is used in CompactRingBuffer.int64 test, then
the munmap syscall get a address (alignment-16k-addr+4k) that is
not page size aligned on 16k page size system.

Co-authored-by: Weining Lu <luweining@loongson.cn>

Depends on D123910

Diff Detail

Event Timeline

XiaodongLoong requested review of this revision.Jan 18 2022, 7:32 PM
XiaodongLoong created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptJan 18 2022, 7:32 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript

update for sanitizer_ring_buffer_test.cpp:82 EXPECT_EQ check and delete redundant variable page_size

delete Change-Id

benshi001 added inline comments.Jan 25 2022, 4:39 AM
compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h
91

GetPageSizeCached() is called multiple times, can we

  1. keep the orginal class level variable static constexpr int kPageSizeBits,
  2. initialize it with Log2(GetPageSizeCached())
  3. replace other calls of GetPageSizeCached() with (1 << kPageSizeBits) ?

I expect others can take a look.

See https://github.com/google/sanitizers/issues/1446 - I'd rather remove the requirement that buffer size is a multiple of page size.

XiaodongLoong added a comment.EditedFeb 7 2022, 6:35 PM

See https://github.com/google/sanitizers/issues/1446 - I'd rather remove the requirement that buffer size is a multiple of page size.

Hi, thank you for your attention to this issue.
This patch is a bugfix for the current implementation since version 8.0. I think what you mentioned is another implementation that can save memory, but there are technical problems as you said:

There is also an efficiency issue in HwasanThreadList::DontNeedThread - if
the buffer is smaller than a page, it will never be able to release
anything. That's a bit harder to fix, and I'm not sure how significant it
actually is.
compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h
91

Thanks for your comments. Your idea is very good to reduce duplicate code. I try to change the code as you said, but I met a compilation error as following:

compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h:88:24: error: constexpr variable 'kPageSizeBits' must be
      initialized by a constant expression
  static constexpr int kPageSizeBits = Log2(GetPageSizeCached());

I also attempt to implement your idea in other way, but all failed with compilation or test error.
(1) static const unsigned kPageSizeBits = Log2(GetPageSizeCached());

compilation error logs:
sanitizer_ring_buffer.h:88:41: error: in-class initializer for static data member is
      not a constant expression
  static const unsigned kPageSizeBits = Log2(GetPageSizeCached());

(2) static unsigned kPageSizeBits = Log2(GetPageSizeCached());

compilation error logs:
 error: non-const static data member must be initialized
      out of line
  static unsigned kPageSizeBits = Log2(GetPageSizeCached());

(3) unsigned kPageSizeBits = Log2(GetPageSizeCached());

test error logs:
==30453==Sanitizer CHECK failed: compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h:99 ((sizeof(CompactRingBuffer<T>))) == ((sizeof(void *))) (16, 8)

This patch is a bugfix for the current implementation since version 8.0. I think what you mentioned is another implementation that can save memory, but there are technical problems as you said:

The problem is that kPageSizeBits is part of a contract between the runtime library and the compiler instrumentation. See HWAddressSanitizer::emitPrologue. There is no way to read the runtime page size in compiler instrumentation. This has to be a compile-time constant.

(sorry for not catching this earlier, and thank you for trying to fix this!)

XiaodongLoong added a comment.EditedFeb 8 2022, 10:56 PM

The problem is that kPageSizeBits is part of a contract between the runtime library and the compiler instrumentation. See HWAddressSanitizer::emitPrologue. There is no way to read the runtime page size in compiler instrumentation. This has to be a compile-time constant.

If I'm not mistaken, HWAddressSanitizer is only for the AArch64. Could we keep 4K page size on AArch64 and use variable page size for other CPU architectures?

The problem is that kPageSizeBits is part of a contract between the runtime library and the compiler instrumentation. See HWAddressSanitizer::emitPrologue. There is no way to read the runtime page size in compiler instrumentation. This has to be a compile-time constant.

If I'm not mistaken, HWAddressSanitizer is only for the AArch64. Could we keep 4K page size on AArch64 and use variable page size for other CPU architectures?

It's not, hwasan supports x86_64, too, and potentially any future arch with some kind of top-N-bit-ignore feature.

Also, CompactRingBuffer is only used in hwasan, unless you have an out-of-tree user.

XiaodongLoong abandoned this revision.Mar 22 2022, 11:08 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 22 2022, 11:08 PM
XiaodongLoong reclaimed this revision.Apr 17 2022, 5:57 AM

I have found a new solution. Please take a look. Thanks!

XiaodongLoong edited the summary of this revision. (Show Details)Apr 17 2022, 5:58 AM