From 057cce5e85d4f933bb64aa7824e01219f6b03160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 9 May 2022 19:03:47 +0200 Subject: [PATCH] macOS: Add private API to ensure that a process is responsible/disclaimed Useful for tests that request permissions and need to ensure these are requested on behalf of the app itself, and not its parent process, regardless of how it's invoked. Change-Id: Iac493e95440a3a04df4fa466c1d700ba1233e393 Reviewed-by: Timur Pocheptsov --- src/corelib/kernel/qcore_mac.mm | 53 ++++++++++++++++++++++++++++++++ src/corelib/kernel/qcore_mac_p.h | 1 + 2 files changed, 54 insertions(+) diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm index c2c1f1ac42..b18a7d56ef 100644 --- a/src/corelib/kernel/qcore_mac.mm +++ b/src/corelib/kernel/qcore_mac.mm @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -33,6 +34,12 @@ extern "C" { typedef uint32_t csr_config_t; extern int csr_get_active_config(csr_config_t *) __attribute__((weak_import)); + +int responsibility_spawnattrs_setdisclaim(posix_spawnattr_t attrs, int disclaim) +__attribute__((availability(macos,introduced=10.14),weak_import)); +pid_t responsibility_get_pid_responsible_for_pid(pid_t) __attribute__((weak_import)); +char *** _NSGetArgv(); +extern char **environ; } #endif @@ -382,6 +389,52 @@ std::optional qt_mac_sipConfiguration() }(); return configuration; } + +#define CHECK_SPAWN(expr) \ + if (int err = (expr)) { \ + posix_spawnattr_destroy(&attr); \ + return; \ + } + +void qt_mac_ensureResponsible() +{ +#if !defined(QT_APPLE_NO_PRIVATE_APIS) + if (!responsibility_get_pid_responsible_for_pid || !responsibility_spawnattrs_setdisclaim) + return; + + auto pid = getpid(); + if (responsibility_get_pid_responsible_for_pid(pid) == pid) + return; // Already responsible + + posix_spawnattr_t attr = {}; + CHECK_SPAWN(posix_spawnattr_init(&attr)); + + // Behave as exec + short flags = POSIX_SPAWN_SETEXEC; + + // Reset signal mask + sigset_t no_signals; + sigemptyset(&no_signals); + CHECK_SPAWN(posix_spawnattr_setsigmask(&attr, &no_signals)); + flags |= POSIX_SPAWN_SETSIGMASK; + + // Reset all signals to their default handlers + sigset_t all_signals; + sigfillset(&all_signals); + CHECK_SPAWN(posix_spawnattr_setsigdefault(&attr, &all_signals)); + flags |= POSIX_SPAWN_SETSIGDEF; + + CHECK_SPAWN(posix_spawnattr_setflags(&attr, flags)); + + if (@available(macOS 10.14, *)) + CHECK_SPAWN(responsibility_spawnattrs_setdisclaim(&attr, 1)); + + char **argv = *_NSGetArgv(); + posix_spawnp(&pid, argv[0], nullptr, &attr, argv, environ); + posix_spawnattr_destroy(&attr); +#endif +} + #endif bool qt_apple_isApplicationExtension() diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index e6252ad98f..54bbbc1e39 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -175,6 +175,7 @@ private: Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); Q_CORE_EXPORT bool qt_mac_runningUnderRosetta(); Q_CORE_EXPORT std::optional qt_mac_sipConfiguration(); +Q_CORE_EXPORT void qt_mac_ensureResponsible(); #endif #ifndef QT_NO_DEBUG_STREAM