From 1c7bd7da9f40b307d8ba5111e15a153cfa5c891a Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Tue, 7 Apr 2026 02:23:09 -0400 Subject: [PATCH] pidfdhack: Simplify and just override os.checkPidfdOnce Ignoring SIGSYS entirely was masking other legitimate upstream golang regressions. Signed-off-by: Andrew Gunnerson --- stbridge/pidfdhack/pidfdhack.go | 65 +++++++-------------------------- 1 file changed, 14 insertions(+), 51 deletions(-) diff --git a/stbridge/pidfdhack/pidfdhack.go b/stbridge/pidfdhack/pidfdhack.go index ed3396e..66a2f19 100644 --- a/stbridge/pidfdhack/pidfdhack.go +++ b/stbridge/pidfdhack/pidfdhack.go @@ -1,72 +1,35 @@ -// SPDX-FileCopyrightText: 2025 Andrew Gunnerson +// SPDX-FileCopyrightText: 2025-2026 Andrew Gunnerson // SPDX-License-Identifier: GPL-3.0-only // We get killed on Android 11 and older due to seccomp blocking the pidfd_open // syscall. Upstream golang works around this by ignoring the SIGSYS signal for // that invocation (https://github.com/golang/go/pull/69543), but this does not // work when loaded as a shared library because go's normal signal handler is -// not registered. To work around this, we just handle SIGSYS and log the error. -// -// Some alternatives that were considered: -// -// * Overriding os.checkPidfdOnce with go:linkname. For unknown reasons, this -// only sometimes works. If it is set to a function that just returns an -// error, then pidfd_open is still called. If a fmt.Printf() call is added, -// then it works. This is despite the function only being called once (no -// races between threads). -// -// * Replacing os.ignoreSIGSYS() and os.restoreSIGSYS() with functions that -// temporarily block receiving SIGSYS with sigprocmask(). Unfortunately, the -// builtin runtime package already provides implementations via go:linkname, -// so we would get a duplicate symbol error when linking. +// not registered. To work around this, we just override checkPidfdOnce. package pidfdhack /* -#include -#include - #include -#include - -#define LOG(level, ...) __android_log_print(ANDROID_LOG_ ## level, "pidfdhack", __VA_ARGS__) - -void sigsys_handler(int signum, siginfo_t *info, void *context) { - if (info->si_code == SYS_SECCOMP) { - LOG( - WARN, - "Received seccomp SIGSYS (call=%p, arch=%u, syscall=%d): %s", - info->si_call_addr, - info->si_arch, - info->si_syscall, - strerror(info->si_errno) - ); - } else { - LOG(WARN, "Received non-seccomp SIGSYS: %s", strerror(info->si_errno)); - } -} - -void block_sigsys() { - struct sigaction sa = { 0 }; - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = &sigsys_handler; - - if (sigaction(SIGSYS, &sa, NULL) == -1) { - LOG(WARN, "Failed to set SIGSYS handler"); - } - - LOG(INFO, "Successfully set SIGSYS handler"); -} */ import "C" import ( + "errors" + _ "os" _ "unsafe" ) -var shouldIgnoreSigsys = int(C.android_get_device_api_level()) <= 30 +//go:linkname checkPidfdOnce os.checkPidfdOnce +var checkPidfdOnce func() error + +var pidFdError = errors.New("Would be blocked by seccomp") + +func pidFdErrorFunc() error { + return pidFdError +} func init() { - if shouldIgnoreSigsys { - C.block_sigsys() + if int(C.android_get_device_api_level()) <= 30 { + checkPidfdOnce = pidFdErrorFunc } }