Skip to content

[sanitizer] Don't TestPTrace() if SPARC; don't give up if internal_fork() fails #152072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 5, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,21 @@ struct ScopedSetTracerPID {

// This detects whether ptrace is blocked (e.g., by seccomp), by forking and
// then attempting ptrace.
// This separate check is necessary because StopTheWorld() creates a child
// process with a shared virtual address space and shared TLS, and therefore
// This separate check is necessary because StopTheWorld() creates a thread
// with a shared virtual address space and shared TLS, and therefore
// cannot use waitpid() due to the shared errno.
static void TestPTrace() {
# if SANITIZER_SPARC
// internal_fork() on SPARC actually calls __fork(). We can't safely fork,
// because it's possible seccomp has been configured to disallow fork() but
// allow clone().
Report("WARNING: skipping TestPTrace() because this is SPARC\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are people supposed to do with this warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added details in 5a630c5

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to e VPrint

spamming stderr just in case is not helpful

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VReport

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Report(
"If seccomp blocks ptrace, LeakSanitizer may hang without further "
"notice\n");
Report(
"If seccomp does not block ptrace, you can safely ignore this warning\n");
# else
// Heuristic: only check the first time this is called. This is not always
// correct (e.g., user manually triggers leak detection, then updates
// seccomp, then leak detection is triggered again).
Expand All @@ -417,35 +428,46 @@ static void TestPTrace() {
return;
checked = true;

// We hope that fork() is not too expensive, because of copy-on-write.
// Hopefully internal_fork() is not too expensive, thanks to copy-on-write.
// Besides, this is only called the first time.
// Note that internal_fork() on non-SPARC Linux actually calls
// SYSCALL(clone); thus, it is reasonable to use it because if seccomp kills
// TestPTrace(), it would have killed StopTheWorld() anyway.
int pid = internal_fork();

if (pid < 0) {
int rverrno;
if (internal_iserror(pid, &rverrno)) {
if (internal_iserror(pid, &rverrno))
Report("WARNING: TestPTrace() failed to fork (errno %d)\n", rverrno);
}
internal__exit(-1);

// We don't abort the sanitizer - it's still worth letting the sanitizer
// try.
return;
}

if (pid == 0) {
// Child subprocess

// TODO: consider checking return value of internal_ptrace, to handle
// SCMP_ACT_ERRNO. However, be careful not to consume too many
// resources performing a proper ptrace.
internal_ptrace(PTRACE_ATTACH, 0, nullptr, nullptr);
internal__exit(0);
} else {
int wstatus;
internal_waitpid(pid, &wstatus, 0);

// Handle SCMP_ACT_KILL
if (WIFSIGNALED(wstatus)) {
VReport(0,
"Warning: ptrace appears to be blocked (is seccomp enabled?). "
"WARNING: ptrace appears to be blocked (is seccomp enabled?). "
"LeakSanitizer may hang.\n");
VReport(0, "Child exited with signal %d.\n", WTERMSIG(wstatus));
// We don't abort the sanitizer - it's still worth letting the sanitizer
// try.
}
}
# endif
}

void StopTheWorld(StopTheWorldCallback callback, void *argument) {
Expand Down
Loading