Revert "Reraise signals via rt_tgsigqueueinfo(2) on Linux."

Causes test failures on older versions of Android (e.g. Marshmallow).

Also reverts follow-up CL "Fix dead-code warning in util/posix/signals.cc".

This reverts commits ab9a87fb5463e5d1579e16bacb1f79d0dd71119b and
04431eccfe878570b1c74a5b376d96b4c9c7e0e8.

Bug: 1272877
Change-Id: Id9ef420516c932147b6c8b67d9f4daf9d31d9b03
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3300986
Reviewed-by: Peter Boström <pbos@chromium.org>
Commit-Queue: Peter Collingbourne <pcc@chromium.org>
This commit is contained in:
Peter Collingbourne 2021-11-24 13:45:20 -08:00 committed by Crashpad LUCI CQ
parent bc138fc01c
commit c537245de8
2 changed files with 49 additions and 135 deletions

View File

@ -22,10 +22,6 @@
#include "base/cxx17_backports.h"
#include "base/logging.h"
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
#include <sys/syscall.h>
#endif
namespace crashpad {
namespace {
@ -284,21 +280,6 @@ void Signals::RestoreHandlerAndReraiseSignalOnReturn(
_exit(kFailureExitCode);
}
// If we can raise a signal with siginfo on this platform, do so. This ensures
// that we preserve the siginfo information for asynchronous signals (i.e.
// signals that do not re-raise autonomously), such as signals delivered via
// kill() and asynchronous hardware faults such as SEGV_MTEAERR, which would
// otherwise be lost when re-raising the signal via raise().
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
int retval = syscall(SYS_rt_tgsigqueueinfo,
getpid(),
syscall(SYS_gettid),
siginfo->si_signo,
siginfo);
if (retval != 0) {
_exit(kFailureExitCode);
}
#else
// Explicitly re-raise the signal if it will not re-raise itself. Because
// signal handlers normally execute with their signal blocked, this raise()
// cannot immediately deliver the signal. Delivery is deferred until the
@ -308,7 +289,6 @@ void Signals::RestoreHandlerAndReraiseSignalOnReturn(
if (!WillSignalReraiseAutonomously(siginfo) && raise(sig) != 0) {
_exit(kFailureExitCode);
}
#endif // defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
}
// static

View File

@ -34,48 +34,15 @@
#include "test/scoped_temp_dir.h"
#include "util/posix/scoped_mmap.h"
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
#include <sys/auxv.h>
#include <sys/prctl.h>
#if defined(ARCH_CPU_ARM64)
#ifndef HWCAP2_MTE
#define HWCAP2_MTE (1 << 18)
#endif
#ifndef SEGV_MTEAERR
#define SEGV_MTEAERR 8
#endif
#ifndef PROT_MTE
#define PROT_MTE 0x20
#endif
#ifndef PR_SET_TAGGED_ADDR_CTRL
#define PR_SET_TAGGED_ADDR_CTRL 55
#endif
#ifndef PR_TAGGED_ADDR_ENABLE
#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
#endif
#ifndef PR_MTE_TCF_ASYNC
#define PR_MTE_TCF_ASYNC (1UL << 2)
#endif
#endif // defined(ARCH_CPU_ARM64)
#endif // defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
namespace crashpad {
namespace test {
namespace {
constexpr int kUnexpectedExitStatus = 3;
struct TestableSignal {
int sig, code;
};
// Keep synchronized with CauseSignal().
std::vector<TestableSignal> TestableSignals() {
std::vector<TestableSignal> signals;
signals.push_back({SIGABRT, 0});
signals.push_back({SIGALRM, 0});
signals.push_back({SIGBUS, 0});
bool CanCauseSignal(int sig) {
return sig == SIGABRT || sig == SIGALRM || sig == SIGBUS ||
/* According to DDI0487D (Armv8 Architecture Reference Manual) the expected
* behavior for division by zero (Section 3.4.8) is: "... results in a
* zero being written to the destination register, without any
@ -83,30 +50,24 @@ std::vector<TestableSignal> TestableSignals() {
* This applies to Armv8 (and not earlier) for both 32bit and 64bit app code.
*/
#if defined(ARCH_CPU_X86_FAMILY)
signals.push_back({SIGFPE, 0});
sig == SIGFPE ||
#endif
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL)
signals.push_back({SIGILL, 0});
sig == SIGILL ||
#endif // defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL)
signals.push_back({SIGPIPE, 0});
signals.push_back({SIGSEGV, 0});
#if (defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)) && \
defined(ARCH_CPU_ARM64)
if (getauxval(AT_HWCAP2) & HWCAP2_MTE) {
signals.push_back({SIGSEGV, SEGV_MTEAERR});
}
#endif
sig == SIGPIPE || sig == SIGSEGV ||
#if defined(OS_APPLE)
signals.push_back({SIGSYS, 0});
sig == SIGSYS ||
#endif // OS_APPLE
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM64)
signals.push_back({SIGTRAP, 0});
sig == SIGTRAP ||
#endif // defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM64)
return signals;
false;
}
// Keep synchronized with TestableSignals().
void CauseSignal(int sig, int code) {
// Keep synchronized with CanCauseSignal().
void CauseSignal(int sig) {
switch (sig) {
case SIGABRT: {
abort();
@ -203,37 +164,8 @@ void CauseSignal(int sig, int code) {
}
case SIGSEGV: {
switch (code) {
case 0: {
volatile int* i = nullptr;
*i = 0;
break;
}
#if (defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)) && \
defined(ARCH_CPU_ARM64)
case SEGV_MTEAERR: {
ScopedMmap mapping;
if (!mapping.ResetMmap(nullptr,
getpagesize(),
PROT_READ | PROT_WRITE | PROT_MTE,
MAP_PRIVATE | MAP_ANON,
-1,
0)) {
_exit(kUnexpectedExitStatus);
}
if (prctl(PR_SET_TAGGED_ADDR_CTRL,
PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_ASYNC,
0,
0,
0) != 0) {
_exit(kUnexpectedExitStatus);
}
mapping.addr_as<char*>()[1ULL << 56] = 0;
break;
}
#endif // (defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)) &&
// defined(ARCH_CPU_ARM64)
}
volatile int* i = nullptr;
*i = 0;
break;
}
@ -286,10 +218,9 @@ class SignalsTest : public Multiprocess {
};
static constexpr int kExitingHandlerExitStatus = 2;
SignalsTest(TestType test_type, SignalSource signal_source, int sig, int code)
SignalsTest(TestType test_type, SignalSource signal_source, int sig)
: Multiprocess(),
sig_(sig),
code_(code),
test_type_(test_type),
signal_source_(signal_source) {}
@ -368,7 +299,7 @@ class SignalsTest : public Multiprocess {
switch (signal_source_) {
case SignalSource::kCause:
CauseSignal(sig_, code_);
CauseSignal(sig_);
break;
case SignalSource::kRaise:
raise(sig_);
@ -379,7 +310,6 @@ class SignalsTest : public Multiprocess {
}
int sig_;
int code_;
TestType test_type_;
SignalSource signal_source_;
static Signals::OldActions old_actions_;
@ -422,28 +352,32 @@ TEST(Signals, WillSignalReraiseAutonomously) {
}
TEST(Signals, Cause_DefaultHandler) {
for (TestableSignal s : TestableSignals()) {
SCOPED_TRACE(base::StringPrintf(
"sig %d (%s), code %d", s.sig, strsignal(s.sig), s.code));
for (int sig = 1; sig < NSIG; ++sig) {
SCOPED_TRACE(base::StringPrintf("sig %d (%s)", sig, strsignal(sig)));
if (!CanCauseSignal(sig)) {
continue;
}
SignalsTest test(SignalsTest::TestType::kDefaultHandler,
SignalsTest::SignalSource::kCause,
s.sig,
s.code);
test.SetExpectedChildTermination(Multiprocess::kTerminationSignal, s.sig);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationSignal, sig);
test.Run();
}
}
TEST(Signals, Cause_HandlerExits) {
for (TestableSignal s : TestableSignals()) {
SCOPED_TRACE(base::StringPrintf(
"sig %d (%s), code %d", s.sig, strsignal(s.sig), s.code));
for (int sig = 1; sig < NSIG; ++sig) {
SCOPED_TRACE(base::StringPrintf("sig %d (%s)", sig, strsignal(sig)));
if (!CanCauseSignal(sig)) {
continue;
}
SignalsTest test(SignalsTest::TestType::kHandlerExits,
SignalsTest::SignalSource::kCause,
s.sig,
s.code);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationNormal,
SignalsTest::kExitingHandlerExitStatus);
test.Run();
@ -451,28 +385,32 @@ TEST(Signals, Cause_HandlerExits) {
}
TEST(Signals, Cause_HandlerReraisesToDefault) {
for (TestableSignal s : TestableSignals()) {
SCOPED_TRACE(base::StringPrintf(
"sig %d (%s), code %d", s.sig, strsignal(s.sig), s.code));
for (int sig = 1; sig < NSIG; ++sig) {
SCOPED_TRACE(base::StringPrintf("sig %d (%s)", sig, strsignal(sig)));
if (!CanCauseSignal(sig)) {
continue;
}
SignalsTest test(SignalsTest::TestType::kHandlerReraisesToDefault,
SignalsTest::SignalSource::kCause,
s.sig,
s.code);
test.SetExpectedChildTermination(Multiprocess::kTerminationSignal, s.sig);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationSignal, sig);
test.Run();
}
}
TEST(Signals, Cause_HandlerReraisesToPrevious) {
for (TestableSignal s : TestableSignals()) {
SCOPED_TRACE(base::StringPrintf(
"sig %d (%s), code %d", s.sig, strsignal(s.sig), s.code));
for (int sig = 1; sig < NSIG; ++sig) {
SCOPED_TRACE(base::StringPrintf("sig %d (%s)", sig, strsignal(sig)));
if (!CanCauseSignal(sig)) {
continue;
}
SignalsTest test(SignalsTest::TestType::kHandlerReraisesToPrevious,
SignalsTest::SignalSource::kCause,
s.sig,
s.code);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationNormal,
SignalsTest::kExitingHandlerExitStatus);
test.Run();
@ -489,8 +427,7 @@ TEST(Signals, Raise_DefaultHandler) {
SignalsTest test(SignalsTest::TestType::kDefaultHandler,
SignalsTest::SignalSource::kRaise,
sig,
0);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationSignal, sig);
test.Run();
}
@ -506,8 +443,7 @@ TEST(Signals, Raise_HandlerExits) {
SignalsTest test(SignalsTest::TestType::kHandlerExits,
SignalsTest::SignalSource::kRaise,
sig,
0);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationNormal,
SignalsTest::kExitingHandlerExitStatus);
test.Run();
@ -539,8 +475,7 @@ TEST(Signals, Raise_HandlerReraisesToDefault) {
SignalsTest test(SignalsTest::TestType::kHandlerReraisesToDefault,
SignalsTest::SignalSource::kRaise,
sig,
0);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationSignal, sig);
test.Run();
}
@ -571,8 +506,7 @@ TEST(Signals, Raise_HandlerReraisesToPrevious) {
SignalsTest test(SignalsTest::TestType::kHandlerReraisesToPrevious,
SignalsTest::SignalSource::kRaise,
sig,
0);
sig);
test.SetExpectedChildTermination(Multiprocess::kTerminationNormal,
SignalsTest::kExitingHandlerExitStatus);
test.Run();