[iOS] Block the accessibility server when accessibility is not enabled.
authorpvollan@apple.com <pvollan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Mar 2019 05:44:22 +0000 (05:44 +0000)
committerpvollan@apple.com <pvollan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Mar 2019 05:44:22 +0000 (05:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195342

Reviewed by Brent Fulgham.

Source/WebKit:

By default, block the iOS accessibility server in the sandbox. If accessibility is enabled,
let the UI process issue a mach extension to the WebContent process. The UI process will
issue the mach extension the the WebContent process by its process identifier. The sandbox
extension handle is sent to the WebContent process to be consumed. The message will be sent
when the WebProcess has finished launching, and also when accessibility is turned on.

* Platform/spi/ios/AccessibilitySupportSPI.h:
* Resources/SandboxProfiles/ios/com.apple.WebKit.WebContent.sb:
* Shared/SandboxExtension.h:
* Shared/mac/SandboxExtensionMac.mm:
(WebKit::SandboxExtensionImpl::create):
(WebKit::SandboxExtensionImpl::sandboxExtensionForType):
(WebKit::SandboxExtensionImpl::SandboxExtensionImpl):
(WebKit::SandboxExtension::createHandleForMachLookupByPid):
* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::WebProcessPool::registerNotificationObservers):
(WebKit::WebProcessPool::unregisterNotificationObservers):
* UIProcess/WebProcessPool.h:
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::didFinishLaunching):
* UIProcess/WebProcessProxy.h:
* UIProcess/ios/WebProcessProxyIOS.mm:
(WebKit::WebProcessProxy::unblockAccessibilityServerIfNeeded):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::unblockAccessibilityServer):
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:

Source/WTF:

Add SPI to issue a mach extension to a process by pid. Also, add a macro for
the availability of this SPI.

* wtf/Platform.h:
* wtf/spi/darwin/SandboxSPI.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243034 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/Platform.h
Source/WTF/wtf/spi/darwin/SandboxSPI.h
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/AccessibilitySupportSPI.h
Source/WebKit/Resources/SandboxProfiles/ios/com.apple.WebKit.WebContent.sb
Source/WebKit/Shared/SandboxExtension.h
Source/WebKit/Shared/mac/SandboxExtensionMac.mm
Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
Source/WebKit/UIProcess/WebProcessPool.h
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/ios/WebProcessProxyIOS.mm
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/WebProcess.h
Source/WebKit/WebProcess/WebProcess.messages.in

index b1eafa2..924b532 100644 (file)
@@ -1,3 +1,16 @@
+2019-03-15  Per Arne Vollan  <pvollan@apple.com>
+
+        [iOS] Block the accessibility server when accessibility is not enabled.
+        https://bugs.webkit.org/show_bug.cgi?id=195342
+
+        Reviewed by Brent Fulgham.
+
+        Add SPI to issue a mach extension to a process by pid. Also, add a macro for
+        the availability of this SPI.
+
+        * wtf/Platform.h:
+        * wtf/spi/darwin/SandboxSPI.h:
+
 2019-03-15  Eric Carlson  <eric.carlson@apple.com>
 
         Add media stream release logging
index 94037ce..25e2a3b 100644 (file)
 #define HAVE_CSCHECKFIXDISABLE 1
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
+#define HAVE_SANDBOX_ISSUE_MACH_EXTENSION_TO_PROCESS_BY_PID 1
+#endif
+
 #if PLATFORM(MAC)
 #define ENABLE_MONOSPACE_FONT_EXCEPTION (__MAC_OS_X_VERSION_MIN_REQUIRED < 101500)
 #elif PLATFORM(IOS_FAMILY)
index b2681b4..38c390f 100644 (file)
@@ -63,6 +63,7 @@ extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT;
 
 char *sandbox_extension_issue_file(const char *extension_class, const char *path, uint32_t flags);
 char *sandbox_extension_issue_generic(const char *extension_class, uint32_t flags);
+char *sandbox_extension_issue_mach_to_process_by_pid(const char *extension_class, const char *name, uint32_t flags, pid_t);
 int sandbox_check(pid_t, const char *operation, enum sandbox_filter_type, ...);
 int sandbox_check_by_audit_token(audit_token_t, const char *operation, enum sandbox_filter_type, ...);
 int sandbox_container_path_for_pid(pid_t, char *buffer, size_t bufsize);
index a53fd40..e9bb648 100644 (file)
@@ -1,3 +1,38 @@
+2019-03-15  Per Arne Vollan  <pvollan@apple.com>
+
+        [iOS] Block the accessibility server when accessibility is not enabled.
+        https://bugs.webkit.org/show_bug.cgi?id=195342
+
+        Reviewed by Brent Fulgham.
+
+        By default, block the iOS accessibility server in the sandbox. If accessibility is enabled,
+        let the UI process issue a mach extension to the WebContent process. The UI process will
+        issue the mach extension the the WebContent process by its process identifier. The sandbox
+        extension handle is sent to the WebContent process to be consumed. The message will be sent
+        when the WebProcess has finished launching, and also when accessibility is turned on.
+
+        * Platform/spi/ios/AccessibilitySupportSPI.h:
+        * Resources/SandboxProfiles/ios/com.apple.WebKit.WebContent.sb:
+        * Shared/SandboxExtension.h:
+        * Shared/mac/SandboxExtensionMac.mm:
+        (WebKit::SandboxExtensionImpl::create):
+        (WebKit::SandboxExtensionImpl::sandboxExtensionForType):
+        (WebKit::SandboxExtensionImpl::SandboxExtensionImpl):
+        (WebKit::SandboxExtension::createHandleForMachLookupByPid):
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (WebKit::WebProcessPool::registerNotificationObservers):
+        (WebKit::WebProcessPool::unregisterNotificationObservers):
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::didFinishLaunching):
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/ios/WebProcessProxyIOS.mm:
+        (WebKit::WebProcessProxy::unblockAccessibilityServerIfNeeded):
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::unblockAccessibilityServer):
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+
 2019-03-15  Timothy Hatcher  <timothy@apple.com>
 
         Unreviewed speculative build fix for non-Cocoa ports after r243012.
index 50ca2db..d360f79 100644 (file)
@@ -41,6 +41,8 @@ WTF_EXTERN_C_BEGIN
 #if PLATFORM(IOS_FAMILY)
 extern Boolean _AXSKeyRepeatEnabled();
 extern CFTimeInterval _AXSKeyRepeatDelay();
+extern Boolean _AXSApplicationAccessibilityEnabled();
+extern CFStringRef kAXSApplicationAccessibilityEnabledNotification;
 #endif
 
 #if ENABLE(ACCESSIBILITY_EVENTS)
index db087e6..c84e59f 100644 (file)
     (global-name "com.apple.backboard.hid.focus")
     (global-name "com.apple.backboard.hid.services")
     (global-name "com.apple.iohideventsystem")
-    (global-name "com.apple.iphone.axserver-systemwide")
     (global-name "com.apple.frontboard.workspace")
     (global-name "com.apple.frontboard.systemappservices"))
 
 (deny mach-lookup (with send-signal SIGKILL)
     (global-name "com.apple.backboard.hid.services"))
 
+(allow mach-lookup (extension "com.apple.webkit.extension.mach"))
+
 ;; These services have been identified as unused during living-on.
 ;; This list overrides some definitions above and in common.sb.
 ;; FIXME: remove overridden rules once the final list has been
index ddfacb2..7c93d3b 100644 (file)
@@ -46,6 +46,7 @@ public:
     enum class Type {
         ReadOnly,
         ReadWrite,
+        Mach,
         Generic,
     };
 
@@ -101,6 +102,7 @@ public:
     static bool createHandleForReadWriteDirectory(const String& path, Handle&); // Will attempt to create the directory.
     static String createHandleForTemporaryFile(const String& prefix, Type, Handle&);
     static bool createHandleForGenericExtension(const String& extensionClass, Handle&);
+    static bool createHandleForMachLookupByPid(const String& service, pid_t, Handle&);
     ~SandboxExtension();
 
     bool consume();
index 1f7b961..3bd9571 100644 (file)
@@ -40,9 +40,9 @@ namespace WebKit {
 
 class SandboxExtensionImpl {
 public:
-    static std::unique_ptr<SandboxExtensionImpl> create(const char* path, SandboxExtension::Type type)
+    static std::unique_ptr<SandboxExtensionImpl> create(const char* path, SandboxExtension::Type type, Optional<pid_t> pid = WTF::nullopt)
     {
-        std::unique_ptr<SandboxExtensionImpl> impl { new SandboxExtensionImpl(path, type) };
+        std::unique_ptr<SandboxExtensionImpl> impl { new SandboxExtensionImpl(path, type, pid) };
         if (!impl->m_token)
             return nullptr;
         return impl;
@@ -64,6 +64,10 @@ public:
 #if PLATFORM(IOS_FAMILY_SIMULATOR)
         return !sandbox_check(getpid(), 0, SANDBOX_FILTER_NONE);
 #else
+        if (m_handle == -1) {
+            LOG_ERROR("Could not create a sandbox extension for '%s', errno = %d", m_token, errno);
+            return false;
+        }
         return m_handle;
 #endif
     }
@@ -80,20 +84,28 @@ public:
     }
 
 private:
-    char* sandboxExtensionForType(const char* path, SandboxExtension::Type type)
+    char* sandboxExtensionForType(const char* path, SandboxExtension::Type type, Optional<pid_t> pid = WTF::nullopt)
     {
         switch (type) {
         case SandboxExtension::Type::ReadOnly:
             return sandbox_extension_issue_file(APP_SANDBOX_READ, path, 0);
         case SandboxExtension::Type::ReadWrite:
             return sandbox_extension_issue_file(APP_SANDBOX_READ_WRITE, path, 0);
+        case SandboxExtension::Type::Mach:
+#if HAVE(SANDBOX_ISSUE_MACH_EXTENSION_TO_PROCESS_BY_PID)
+            return sandbox_extension_issue_mach_to_process_by_pid("com.apple.webkit.extension.mach"_s, path, 0, pid.value());
+#else
+            UNUSED_PARAM(pid);
+            ASSERT_NOT_REACHED();
+            return nullptr;
+#endif
         case SandboxExtension::Type::Generic:
             return sandbox_extension_issue_generic(path, 0);
         }
     }
 
-    SandboxExtensionImpl(const char* path, SandboxExtension::Type type)
-        : m_token { sandboxExtensionForType(path, type) }
+    SandboxExtensionImpl(const char* path, SandboxExtension::Type type, Optional<pid_t> pid = WTF::nullopt)
+        : m_token { sandboxExtensionForType(path, type, pid) }
     {
     }
 
@@ -357,6 +369,19 @@ bool SandboxExtension::createHandleForGenericExtension(const String& extensionCl
     return true;
 }
 
+bool SandboxExtension::createHandleForMachLookupByPid(const String& service, pid_t pid, Handle& handle)
+{
+    ASSERT(!handle.m_sandboxExtension);
+    
+    handle.m_sandboxExtension = SandboxExtensionImpl::create(service.utf8().data(), Type::Mach, pid);
+    if (!handle.m_sandboxExtension) {
+        WTFLogAlways("Could not create a '%s' sandbox extension", service.utf8().data());
+        return false;
+    }
+    
+    return true;
+}
+
 SandboxExtension::SandboxExtension(const Handle& handle)
     : m_sandboxExtension(WTFMove(handle.m_sandboxExtension))
 {
index 4514349..cba1448 100644 (file)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "WebProcessPool.h"
 
+#import "AccessibilitySupportSPI.h"
 #import "CookieStorageUtilsCF.h"
 #import "LegacyCustomProtocolManagerClient.h"
 #import "NetworkProcessCreationParameters.h"
@@ -447,6 +448,10 @@ void WebProcessPool::registerNotificationObservers()
     }];
 #elif PLATFORM(IOS)
     CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, backlightLevelDidChangeCallback, static_cast<CFStringRef>(UIBacklightLevelChangedNotification), nullptr, CFNotificationSuspensionBehaviorCoalesce);
+    m_accessibilityEnabledObserver = [[NSNotificationCenter defaultCenter] addObserverForName:(__bridge id)kAXSApplicationAccessibilityEnabledNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *) {
+        for (size_t i = 0; i < m_processes.size(); ++i)
+            m_processes[i]->unblockAccessibilityServerIfNeeded();
+    }];
 #endif // !PLATFORM(IOS_FAMILY)
 }
 
@@ -466,6 +471,7 @@ void WebProcessPool::unregisterNotificationObservers()
     [[NSNotificationCenter defaultCenter] removeObserver:m_deactivationObserver.get()];
 #elif PLATFORM(IOS)
     CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, static_cast<CFStringRef>(UIBacklightLevelChangedNotification) , nullptr);
+    [[NSNotificationCenter defaultCenter] removeObserver:m_accessibilityEnabledObserver.get()];
 #endif // !PLATFORM(IOS_FAMILY)
 }
 
index 6671412..83eb0e6 100644 (file)
@@ -673,6 +673,10 @@ private:
     std::unique_ptr<PerActivityStateCPUUsageSampler> m_perActivityStateCPUUsageSampler;
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+    RetainPtr<NSObject> m_accessibilityEnabledObserver;
+#endif
+
     bool m_shouldUseTestingNetworkSession { false };
 
     bool m_processTerminationEnabled { true };
index 9030df2..55cd873 100644 (file)
@@ -759,6 +759,8 @@ void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connect
         if (xpc_connection_t xpcConnection = connection()->xpcConnection())
             m_throttler.didConnectToProcess(xpc_connection_get_pid(xpcConnection));
     }
+
+    unblockAccessibilityServerIfNeeded();
 #endif
 }
 
index 258102b..bc3d5f1 100644 (file)
@@ -293,6 +293,10 @@ public:
     void revokeAudioCaptureExtension() { m_mediaCaptureSandboxExtensions &= ~Audio; }
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+    void unblockAccessibilityServerIfNeeded();
+#endif
+
 protected:
     static uint64_t generatePageID();
     WebProcessProxy(WebProcessPool&, WebsiteDataStore&, IsPrewarmed);
@@ -431,6 +435,7 @@ private:
 #if PLATFORM(IOS_FAMILY)
     ForegroundWebProcessToken m_foregroundToken;
     BackgroundWebProcessToken m_backgroundToken;
+    bool m_hasSentMessageToUnblockAccessibilityServer { false };
 #endif
 
     HashMap<String, uint64_t> m_pageURLRetainCountMap;
index 4f92c0c..4388087 100644 (file)
@@ -28,6 +28,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#import "AccessibilitySupportSPI.h"
 #import "WKFullKeyboardAccessWatcher.h"
 #import "WebProcessMessages.h"
 
@@ -42,6 +43,25 @@ bool WebProcessProxy::fullKeyboardAccessEnabled()
 #endif
 }
 
+void WebProcessProxy::unblockAccessibilityServerIfNeeded()
+{
+    if (m_hasSentMessageToUnblockAccessibilityServer)
+        return;
+    if (!_AXSApplicationAccessibilityEnabled())
+        return;
+    if (!processIdentifier())
+        return;
+    if (!canSendMessage())
+        return;
+
+    SandboxExtension::Handle handle;
+    if (!SandboxExtension::createHandleForMachLookupByPid("com.apple.iphone.axserver-systemwide", processIdentifier(), handle))
+        return;
+
+    send(Messages::WebProcess::UnblockAccessibilityServer(handle), 0);
+    m_hasSentMessageToUnblockAccessibilityServer = true;
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(IOS_FAMILY)
index d40ea81..9fdbc0b 100644 (file)
@@ -1867,4 +1867,12 @@ void WebProcess::clearCurrentModifierStateForTesting()
     PlatformKeyboardEvent::setCurrentModifierState({ });
 }
 
+#if PLATFORM(IOS_FAMILY)
+void WebProcess::unblockAccessibilityServer(const SandboxExtension::Handle& handle)
+{
+    bool ok = SandboxExtension::consumePermanently(handle);
+    ASSERT_UNUSED(ok, ok);
+}
+#endif
+
 } // namespace WebKit
index f17584a..72fe219 100644 (file)
@@ -245,6 +245,8 @@ public:
 
 #if PLATFORM(IOS_FAMILY)
     void accessibilityProcessSuspendedNotification(bool);
+    
+    void unblockAccessibilityServer(const SandboxExtension::Handle&);
 #endif
 
 #if PLATFORM(IOS)
index f011b82..45fed46 100644 (file)
@@ -157,4 +157,8 @@ messages -> WebProcess LegacyReceiver {
 #endif
 
     ClearCurrentModifierStateForTesting()
+
+#if PLATFORM(IOS_FAMILY)
+    UnblockAccessibilityServer(WebKit::SandboxExtension::Handle handle)
+#endif
 }