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 <timur.pocheptsov@qt.io>
bb10
Tor Arne Vestbø 2022-05-09 19:03:47 +02:00
parent c46ee7df57
commit 057cce5e85
2 changed files with 54 additions and 0 deletions

View File

@ -19,6 +19,7 @@
#include <objc/runtime.h>
#include <mach-o/dyld.h>
#include <sys/sysctl.h>
#include <spawn.h>
#include <qdebug.h>
@ -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<uint32_t> 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()

View File

@ -175,6 +175,7 @@ private:
Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
Q_CORE_EXPORT bool qt_mac_runningUnderRosetta();
Q_CORE_EXPORT std::optional<uint32_t> qt_mac_sipConfiguration();
Q_CORE_EXPORT void qt_mac_ensureResponsible();
#endif
#ifndef QT_NO_DEBUG_STREAM