This is an archive of the discontinued LLVM Phabricator instance.

[asan] Don't double poison secondary allocations
ClosedPublic

Authored by vitalybuka on Jun 21 2023, 11:22 PM.

Details

Summary

Sanitizers allocate shadow and memory as MAP_NORESERVE.

User memory can stay this way and do not increase RSS as long as we
don't store there.

The shadow unpoisoning also can avoid RSS increase for zeroed pages.
However as soon we poison the shadow, we need the page in RSS.

To avoid unnececary RSS increase we should not poison memory just before
unpoisoning them.

Depends on D153497.

Diff Detail

Event Timeline

vitalybuka created this revision.Jun 21 2023, 11:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 21 2023, 11:22 PM
Herald added a subscriber: Enna1. · View Herald Transcript
vitalybuka requested review of this revision.Jun 21 2023, 11:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 21 2023, 11:22 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript
thurston accepted this revision.Jun 22 2023, 9:16 AM
This revision is now accepted and ready to land.Jun 22 2023, 9:16 AM
This revision was landed with ongoing or failed builds.Jun 22 2023, 12:35 PM
This revision was automatically updated to reflect the committed changes.
ro added a subscriber: ro.Jun 27 2023, 12:50 AM

This test causes massive problems on the Solaris/amd64 builder:

load averages:  2.96,  3.29,  4.21;               up 4+11:19:19        09:22:13
65 processes: 63 sleeping, 2 on cpu
CPU states: 87.4% idle,  0.0% user, 12.4% kernel,  0.2% stolen,  0.0% swap
Kernel: 3107 ctxsw, 5994 trap, 2564 intr, 881 syscall, 5990 flt, 1596 pgout
Memory: 256G phys mem, 320M free mem, 64G total swap, 60G free swap

   PID USERNAME NLWP PRI NICE  SIZE   RES STATE     TIME    CPU COMMAND
  7299 llvm-bui    1  40    0  241M  173M cpu/2    13:26  4.79% Sanitizer-x86_6
  8958 llvm-bui    1  60    0  256G   67G sleep     9:01  0.14% huge_malloc.c.t

The system has 256 GB RAM and 64 GB swap. However, unlike Linux, Solaris doesn't do lazy allocation, so the test needs 256 GB of backing store, which causes the host to almost go to a halt, badly impacting another builder on the same system.

ro added a comment.Jun 27 2023, 3:54 AM

I've now temporarily disabled the Solaris/amd64 buildbot: this test caused the other builder on the same host to fail due to lack of memory several times! How should we handle this? Just mark the test as UNSUPPORTED on Solaris, or restrict it to Linux and Android instead? Keeping it as is is unacceptable.

In D153500#4451868, @ro wrote:

I've now temporarily disabled the Solaris/amd64 buildbot: this test caused the other builder on the same host to fail due to lack of memory several times! How should we handle this? Just mark the test as UNSUPPORTED on Solaris, or restrict it to Linux and Android instead? Keeping it as is is unacceptable.

Sorry of that.

Please mark UNSUPPORTED with comment.

Is this a different implementation of MAP_NORESERVE or just Solaris sanitizer implementation does not uses MAP_NORESERVE?
If there is a way to make use of MAP_NORESERVE, it's worse of investigation. Sanitizers heavily rely on that.

In D153500#4451868, @ro wrote:

I've now temporarily disabled the Solaris/amd64 buildbot: this test caused the other builder on the same host to fail due to lack of memory several times! How should we handle this? Just mark the test as UNSUPPORTED on Solaris, or restrict it to Linux and Android instead? Keeping it as is is unacceptable.

Sorry of that.

Please mark UNSUPPORTED with comment.

Is this a different implementation of MAP_NORESERVE or just Solaris sanitizer implementation does not uses MAP_NORESERVE?
If there is a way to make use of MAP_NORESERVE, it's worse of investigation. Sanitizers heavily rely on that.

Also there is hard_rss_limit_mb, why it does not kill the process like on linux.

ro added a comment.Jun 28 2023, 4:12 AM

Also there is hard_rss_limit_mb, why it does not kill the process like on linux.

This is implemented in sanitizer_common_libcdep.cpp, but guarded by (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO

ro added a comment.Jun 28 2023, 4:14 AM

Please mark UNSUPPORTED with comment.

Thanks for taking care of this already.

Is this a different implementation of MAP_NORESERVE or just Solaris sanitizer implementation does not uses MAP_NORESERVE?
If there is a way to make use of MAP_NORESERVE, it's worse of investigation. Sanitizers heavily rely on that.

I've meanwhile run the test under truss (Solaris) resp. strace (Linux), with unexpected results:

  • On Solaris, only brk is used:
5246:	brk(0x8000000000E955C0)				Err#12 ENOMEM
  • while on Linux, mmap is used indeed:
879621 mmap(NULL, 4611686018427523072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

however no MAP_NORESERVE in sight.

ro added a comment.Jun 29 2023, 12:49 AM
In D153500#4455548, @ro wrote:

Please mark UNSUPPORTED with comment.

Thanks for taking care of this already.

Unfortunately, the

UNSUPPORTED: solaris

syntax doesn't work any longer (i.e. it's silently ignored). Judging from other compiler-rt testcases, one now needs to match the target triple explicitly, like

UNSUPPORTED: target={{.*solaris.*}}

At least that's what worked for me locally.