_SC_OPEN_MAX is quite high on FreeBSD, which makes this close() loop a
quite obvious problem when attempting to do any kind of debugging in a
process that uses StartSubprocess. Switch to using close_range(2)
instead to close them all in a single syscall and dramatically reduce
the runtime and syscall trace noise
Linux has an equivalent syscall, but I do not have the capacity to test
that it works there, so this is limited to SANITIZER_FREEBSD for the
time being.
My earlier patch https://github.com/llvm/llvm-project/pull/98200 caused a regression because it unconditionally unblocked synchronous signals, even if the user program had deliberately blocked them. This patch fixes the issue by checking the current signal mask, as suggested by Vitaly. It also adds tests.
Fixes#113385
---------
Co-authored-by: Vitaly Buka <vitalybuka@gmail.com>
When ASan testing is enabled on SPARC as per PR #107405, the
```
AddressSanitizer-sparc-linux :: TestCases/Posix/print_cmdline.cpp
```
test `FAIL`s. Either `ASAN_OPTIONS=print_cmdline=true` yielded binary
garbage in the `Command:` output or just an empty string.
It turns out one needs to apply an offset to `__libc_stack_end` to get
at the actual `argc`/`argv`, as described in `glibc`'s
`sysdeps/sparc/sparc{32,64}/dl-machine.h` (`DL_STACK_END`).
This patch does this, fixing the test.
Tested on `sparc64-unknown-linux-gnu`.
When ASan testing is enabled on SPARC as per PR #107405, the
```
AddressSanitizer-sparc-sunos :: TestCases/Posix/stack-overflow.cpp
```
test `FAIL`s:
```
compiler-rt/test/asan/TestCases/Posix/stack-overflow.cpp:80:12: error: CHECK: expected string not found in input
// CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}}
^
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
=================================================================
==11358==ERROR: AddressSanitizer: SEGV on unknown address 0xff3fff90 (pc 0x000db0c0 bp 0xfeed59f8 sp 0xfeed5978 T0)
==11358==The signal is caused by a READ memory access.
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.
```
It turns out that `sanitizer_linux.cpp` (`GetPcSpBp`) tries to
dereference the stack pointer to get at the saved frame pointer, which
cannot work since `sp` has been invalidated by the stack overflow in the
test. The access attempt thus leads to a second `SEGV`.
Solaris `walkcontext(3C)` doesn't have that problem: in the original
OpenSolaris sources (`$SRC/lib/libc/port/gen/walkstack.c`) they used
`/proc/self/as` to avoid the fault, which is quite heavy-handed. Solaris
11.4 uses a non-faulting load instead (`load_no_fault_uint32`, which
just uses the `lduwa` insn).
This patch follows this lead, returning a `NULL` `bp` in the failure
case. Unfortunately, this leads to `SEGV`s in the depth of the unwinder,
so this patch avoids printing a stack trace in this case.
Tested on `sparcv9-sun-solaris2.11` and `sparc64-unknown-linux-gnu`.
Due to the slightly non-standard interface that returns a pointer
rather than just an integer, the __syscall() utility cannot be used
on all architectures. This change is required for example to use the
sanitizers on Arm Morello.
Pull Request: https://github.com/llvm/llvm-project/pull/84438
fcd6bd5587 broke the Solaris/sparcv9 buildbot:
```
compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp:39:14: fatal error: 'asm/unistd.h' file not found
39 | # include <asm/unistd.h>
| ^~~~~~~~~~~~~~
```
That section should have been Linux-specific in the first place, which is
what this patch does.
Tested on sparcv9-sun-solaris2.11.
```
SanitizerCommon-Unit :: ./Sanitizer-sparcv9-Test/SanitizerCommon/FileOps
```
`FAIL`s on 64-bit Linux/sparc64:
```
projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparcv9-Test --gtest_filter=SanitizerCommon.FileOps
--
compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:144: Failure
Expected equality of these values:
len1 + len2
Which is: 10
fsize
Which is: 1721875535
```
The issue is similar to the mips64 case: the Linux/sparc64 `*stat`
syscalls take a `struct kernel_stat64 *` arg. Also the syscalls actually
used differ.
This patch handles this, adopting the mips64 code to avoid too much
duplication.
Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`.
…parc64
```
SanitizerCommon-Unit :: ./Sanitizer-sparc-Test/SanitizerCommon/InternalMmapWithOffset
```
`FAIL`s on 32-bit Linux/sparc64:
```
projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparc-Test --gtest_filter=SanitizerCommon.InternalMmapWithOffset
--
compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:335: Failure
Expected equality of these values:
'A'
Which is: 'A' (65, 0x41)
p[0]
Which is: '\0'
```
It turns out the `pgoffset` arg to `mmap2` is passed incorrectly in this
case, unlike the 64-bit test. The caller, `MapWritableFileToMemory`,
passes an `u64` arg, while `mmap2` expects an `off_t`. This patch casts
the arg accordingly.
Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`.
```
SanitizerCommon-Unit :: ./Sanitizer-sparc-Test/SanitizerCommon/StartSubprocessTest
```
and every single test using the `llvm-symbolizer` `FAIL` on
Linux/sparc64 in a very weird way: when using `StartSubprocess`, there's
a call to `internal_fork`, but we never reach `internal_execve`.
`internal_fork` is implemented using `syscall(SYS_clone)`. The calling
convention of that syscall already varies considerably between targets,
but as documented in `clone(2)`, SPARC again is widely different.
Instead of trying to match `glibc` here, this patch just calls `__fork`.
Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`.
On FreeBSD amd64 (aka x86_64), registers are always defined as
`int64_t`, which in turn is equivalent to `long`. This leads to a number
of warnings in `DumpAllRegisters()`:
compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp:2245:31: warning:
format specifies type 'unsigned long long' but the argument has type
'__register_t' (aka 'long') [-Wformat]
2245 | Printf("rax = 0x%016llx ", ucontext->uc_mcontext.mc_rax);
| ~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
| %016lx
compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp:2246:31: warning:
format specifies type 'unsigned long long' but the argument has type
'__register_t' (aka 'long') [-Wformat]
2246 | Printf("rbx = 0x%016llx ", ucontext->uc_mcontext.mc_rbx);
| ~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
| %016lx
... more of these ...
Fix it by using the `lx` format.
While working on safestack on Solaris, I noticed that the `TgKill`
implementation is wrong here: `TgKill` is supposed to return `-1` on
error, while `thr_kill` returns `errno` instead. This patch compensates
for that.
This went unnoticed so far since `TgKill` has been unused.
Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11` together
with a subsequent patch to make safestack actually work on Solaris.
This changes the behavior of `BlockSignals` and `ScopedBlockSignals` to
block only asynchronous signals.
This extension is intended to be used in a future fix for MSan (block
async signals during `MsanThread::Destroy`).
We use REAL() calls in interceptors, but
DEFINE_REAL_PTHREAD_FUNCTIONS has nothing to do
with them and only used for internal maintenance
threads.
This is done to avoid confusion like in #96456.
In the FreeBSD base system, re-executing the main binary when ASLR is
detected was implemented in the following commits:
* freebsd/freebsd-src@7cafe89f9c
* freebsd/freebsd-src@96fe7c8ab0
* freebsd/freebsd-src@930a7c2ac6
* freebsd/freebsd-src@0a736f0a6a
* freebsd/freebsd-src@4c9a0adad1
Squash all these to bring them into upstream compiler-rt.
When ASLR is detected to be enabled, this first force-disables ASLR for
the current process, then calls ReExec(). The ReExec() function gets a
FreeBSD specific implementation for finding the path of the executed
program, via the ELF auxiliary vector. This is done without calling into
the regular elf_aux_info(3) function, as that makes use of several
already-intercepted functions.
This patch enabled tsan for loongarch64 with 47-bit VMA layout. All
tests are passing.
Also adds assembly routines to enable setjmp/longjmp for loongarch64
on linux.
Reviewed By: dvyukov, SixWeining, #sanitizers
Differential Revision: https://reviews.llvm.org/D138489
If `pathname` is an empty string and the AT_EMPTY_PATH flag is specified in `flags`,
statx `pathname` argument is of type `const char *restrict`, so it should be `""`
instead of `0`.
Reviewed By: SixWeining, xen0n, xry111, lixing-star
Differential Revision: https://reviews.llvm.org/D138414
The bit-30 in this `__flags` means the address error is due to memory load, and the
bit-31 means the address error is due to memory store. (see SC_ADDRERR_RD
and SC_ADDRERR_WR in kernel arch/loongarch/include/uapi/asm/sigcontext.h).
`illegal_write_test.cpp` and `illegal_read_test.cpp` have been tested and passed.
Reviewed By: SixWeining, xen0n, XiaodongLoong
Differential Revision: https://reviews.llvm.org/D137231