diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-03-28 14:48:06 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-03-31 23:01:51 +0200 |
commit | e81aa64280e9835121769085023034e919274745 (patch) | |
tree | ae10b9317f51cc76f2f6c700cbb39721eb195968 | |
parent | 3236b64db8bb26a6c1c2c288cb47ecc08a7d526f (diff) |
macOS: Move application sandbox checking to secondary thread
We use the macOS Security framework to check whether the application is
sandboxed or not, in which case we might have to limit or change some of
the functionality of Qt, such as which shared memory backend to use.
Calls to SecStaticCodeCheckValidityWithErrors should ideally not be done
on the main thread, as the function may not return immediately, and we
get runtime analysis warnings about this in Xcode:
This method should not be called on the main thread as it may lead to
UI unresponsiveness.
To improve the situation we spin up a short lived thread at library
load that resolves the sandboxing state, ready to be queried when
needed from Qt.
Pick-to: 6.5
Change-Id: I52cdc1bf6aef05c3b93b43f67b3fb46035996b3a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
-rw-r--r-- | src/corelib/kernel/qcore_mac.mm | 74 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 5 |
2 files changed, 57 insertions, 22 deletions
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm index 17cd03d975..989e7d03a6 100644 --- a/src/corelib/kernel/qcore_mac.mm +++ b/src/corelib/kernel/qcore_mac.mm @@ -30,6 +30,10 @@ #include "qvarlengtharray.h" #include "private/qlocking_p.h" +#if !defined(QT_BOOTSTRAPPED) +#include <thread> +#endif + #if !defined(QT_APPLE_NO_PRIVATE_APIS) extern "C" { typedef uint32_t csr_config_t; @@ -456,34 +460,62 @@ AppleApplication *qt_apple_sharedApplication() } #endif +#if !defined(QT_BOOTSTRAPPED) + +#if defined(Q_OS_MACOS) +namespace { +struct SandboxChecker +{ + SandboxChecker() : m_thread([this]{ + m_isSandboxed = []{ + QCFType<SecStaticCodeRef> staticCode = nullptr; + NSURL *executableUrl = NSBundle.mainBundle.executableURL; + if (SecStaticCodeCreateWithPath((__bridge CFURLRef)executableUrl, + kSecCSDefaultFlags, &staticCode) != errSecSuccess) + return false; + + QCFType<SecRequirementRef> sandboxRequirement; + if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"), + kSecCSDefaultFlags, &sandboxRequirement) != errSecSuccess) + return false; + + if (SecStaticCodeCheckValidityWithErrors(staticCode, + kSecCSBasicValidateOnly, sandboxRequirement, nullptr) != errSecSuccess) + return false; + + return true; + }(); + }) + {} + ~SandboxChecker() { + std::scoped_lock lock(m_mutex); + if (m_thread.joinable()) + m_thread.detach(); + } + bool isSandboxed() const { + std::scoped_lock lock(m_mutex); + if (m_thread.joinable()) + m_thread.join(); + return m_isSandboxed; + } +private: + bool m_isSandboxed; + mutable std::thread m_thread; + mutable std::mutex m_mutex; +}; +} // namespace +static SandboxChecker sandboxChecker; +#endif // Q_OS_MACOS + bool qt_apple_isSandboxed() { #if defined(Q_OS_MACOS) - static bool isSandboxed = []() { - QCFType<SecStaticCodeRef> staticCode = nullptr; - NSURL *executableUrl = NSBundle.mainBundle.executableURL; - if (SecStaticCodeCreateWithPath((__bridge CFURLRef)executableUrl, - kSecCSDefaultFlags, &staticCode) != errSecSuccess) - return false; - - QCFType<SecRequirementRef> sandboxRequirement; - if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"), - kSecCSDefaultFlags, &sandboxRequirement) != errSecSuccess) - return false; - - if (SecStaticCodeCheckValidityWithErrors(staticCode, - kSecCSBasicValidateOnly, sandboxRequirement, nullptr) != errSecSuccess) - return false; - - return true; - }(); - return isSandboxed; + return sandboxChecker.isSandboxed(); #else return true; // All other Apple platforms #endif } -#if !defined(QT_BOOTSTRAPPED) QT_END_NAMESPACE @implementation NSObject (QtSandboxHelpers) - (id)qt_valueForPrivateKey:(NSString *)key @@ -495,7 +527,7 @@ QT_END_NAMESPACE } @end QT_BEGIN_NAMESPACE -#endif +#endif // !QT_BOOTSTRAPPED #ifdef Q_OS_MACOS /* diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index aee5fcb604..39ffe831bb 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -195,15 +195,18 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string); #endif Q_CORE_EXPORT bool qt_apple_isApplicationExtension(); + +#if !defined(QT_BOOTSTRAPPED) Q_CORE_EXPORT bool qt_apple_isSandboxed(); -#if !defined(QT_BOOTSTRAPPED) && defined(__OBJC__) +#if defined(__OBJC__) QT_END_NAMESPACE @interface NSObject (QtSandboxHelpers) - (id)qt_valueForPrivateKey:(NSString *)key; @end QT_BEGIN_NAMESPACE #endif +#endif // !QT_BOOTSTRAPPED #if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS) QT_END_NAMESPACE |