Skip to content
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

[Backtracing] Bail out earlier for privileged binaries on macOS. #77181

Open
wants to merge 1 commit into
base: release/6.0
Choose a base branch
from
Open
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions stdlib/public/Backtracing/modules/OS/Darwin.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ extern void _dyld_process_info_for_each_segment(dyld_process_info info, uint64_t
// .. Code Signing SPI .........................................................

#define CS_OPS_STATUS 0
#define CS_GET_TASK_ALLOW 0x00000004
#define CS_RUNTIME 0x00010000
#define CS_PLATFORM_BINARY 0x04000000
#define CS_PLATFORM_PATH 0x08000000
extern int csops(int, unsigned int, void *, size_t);
Expand Down
21 changes: 14 additions & 7 deletions stdlib/public/libexec/swift-backtrace/TargetMacOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,28 @@ class Target {
}
}

static func isPlatformBinary(pid: pid_t) -> Bool {
static func isPrivileged(pid: pid_t) -> Bool {
var flags = UInt32(0)

return csops(pid,
UInt32(CS_OPS_STATUS),
&flags,
MemoryLayout<UInt32>.size) != 0 ||
(flags & UInt32(CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != 0
guard csops(pid,
UInt32(CS_OPS_STATUS),
&flags,
MemoryLayout<UInt32>.size) == 0 else {
return true
}

if (flags & UInt32(CS_PLATFORM_BINARY | CS_PLATFORM_PATH | CS_RUNTIME)) != 0 {
return true
}

return (flags & UInt32(CS_GET_TASK_ALLOW)) == 0
}

init(crashInfoAddr: UInt64, limit: Int?, top: Int, cache: Bool,
symbolicate: SwiftBacktrace.Symbolication) {
pid = getppid()

if Self.isPlatformBinary(pid: pid) {
if Self.isPrivileged(pid: pid) {
/* Exit silently in this case; either

1. We can't call csops(), because we're sandboxed, or
Expand Down
8 changes: 8 additions & 0 deletions stdlib/public/libexec/swift-backtrace/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,15 @@ Generate a backtrace for the parent process.
}
}

static func unblockSignals() {
var mask = sigset_t()

sigfillset(&mask)
sigprocmask(SIG_UNBLOCK, &mask, nil)
}

static func main() {
unblockSignals()
parseArguments()

guard let crashInfoAddr = args.crashInfo else {
Expand Down
46 changes: 29 additions & 17 deletions stdlib/public/runtime/Backtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@
#endif

#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
#if __has_include(<sys/codesign.h>)
#include <sys/codesign.h>
#else
// SPI
#define CS_OPS_STATUS 0
#define CS_GET_TASK_ALLOW 0x00000004
#define CS_RUNTIME 0x00010000
#define CS_PLATFORM_BINARY 0x04000000
#define CS_PLATFORM_PATH 0x08000000
extern "C" int csops(int, unsigned int, void *, size_t);
#endif
#include <spawn.h>
#endif
#include <unistd.h>
Expand Down Expand Up @@ -145,11 +156,6 @@ BacktraceInitializer backtraceInitializer;

SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END

#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
posix_spawnattr_t backtraceSpawnAttrs;
posix_spawn_file_actions_t backtraceFileActions;
#endif

#if SWIFT_BACKTRACE_ON_CRASH_SUPPORTED

// We need swiftBacktracePath to be aligned on a page boundary, and it also
Expand Down Expand Up @@ -254,6 +260,23 @@ const char *presetToString(Preset preset) {
bool isPrivileged() {
return getauxval(AT_SECURE);
}
#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST
bool isPrivileged() {
if (issetugid())
return true;

uint32_t flags = 0;
if (csops(getpid(),
CS_OPS_STATUS,
&flags,
sizeof(flags)) != 0)
return true;

if (flags & (CS_PLATFORM_BINARY | CS_PLATFORM_PATH | CS_RUNTIME))
return true;

return !(flags & CS_GET_TASK_ALLOW);
}
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
bool isPrivileged() {
return issetugid();
Expand Down Expand Up @@ -451,17 +474,6 @@ BacktraceInitializer::BacktraceInitializer() {
}

if (_swift_backtraceSettings.enabled == OnOffTty::On) {
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
// Make sure that all fds are closed except for stdin/stdout/stderr.
posix_spawnattr_init(&backtraceSpawnAttrs);
posix_spawnattr_setflags(&backtraceSpawnAttrs, POSIX_SPAWN_CLOEXEC_DEFAULT);

posix_spawn_file_actions_init(&backtraceFileActions);
posix_spawn_file_actions_addinherit_np(&backtraceFileActions, STDIN_FILENO);
posix_spawn_file_actions_addinherit_np(&backtraceFileActions, STDOUT_FILENO);
posix_spawn_file_actions_addinherit_np(&backtraceFileActions, STDERR_FILENO);
#endif

ErrorCode err = _swift_installCrashHandler();
if (err != 0) {
swift::warning(0,
Expand Down Expand Up @@ -993,7 +1005,7 @@ _swift_spawnBacktracer(const ArgChar * const *argv)
const_cast<char * const *>(env));
#else
int ret = posix_spawn(&child, swiftBacktracePath,
&backtraceFileActions, &backtraceSpawnAttrs,
nullptr, nullptr,
const_cast<char * const *>(argv),
const_cast<char * const *>(env));
#endif
Expand Down