Add an entitlement check for service worker on iOS
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 17 Feb 2018 00:46:52 +0000 (00:46 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 17 Feb 2018 00:46:52 +0000 (00:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182865
<rdar://problem/37505903>

Reviewed by Brady Eidson.

Source/WebKit:

Added an entitlement check to enable service workers on iOS.

* Shared/mac/SandboxUtilities.h:
* Shared/mac/SandboxUtilities.mm:
(WebKit::connectedProcessHasEntitlement): Added.
* StorageProcess/StorageProcess.cpp:
(WebKit::StorageProcess::createStorageToWebProcessConnection): Enforce the entitlement check by crashing
when this code is executed without the parent process having the service worker entitlement. This should
never happen unless someone is trying to bypass the entitlement check in UI Process since we ordinarily
disable service worker gracefully in WKWebView _initializeWithConfiguration.
(WebKit::StorageProcess::swServerForSession): Ditto.
(WebKit::StorageProcess::registerSWServerConnection): Ditto.
* StorageProcess/StorageProcess.h:
(WebKit::StorageProcess::parentProcessHasServiceWorkerEntitlement const): Added.
* StorageProcess/ios/StorageProcessIOS.mm:
(WebKit::StorageProcess::parentProcessHasServiceWorkerEntitlement const): Added.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]): Disable the service workers when the entitlement is
missing from the current process. The entitlement is enforced by WebContent and Storage process.
This check avoids crashing WebContent process and gracefully disabling the feature.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::updatePreferences): Enforce the entitlement check.
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::parentProcessHasServiceWorkerEntitlement const): Added.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::parentProcessHasServiceWorkerEntitlement const): Added.

Tools:

Added the service worker entitlements to WebKitTestRunner and TestWebKitAPI on iOS.

* TestWebKitAPI/Configurations/TestWebKitAPI-iOS.entitlements:
* WebKitTestRunner/Configurations/WebKitTestRunnerApp-iOS.entitlements:
* WebKitTestRunner/Configurations/WebKitTestRunnerApp.xcconfig:
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:

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

15 files changed:
Source/WebKit/ChangeLog
Source/WebKit/Shared/mac/SandboxUtilities.h
Source/WebKit/Shared/mac/SandboxUtilities.mm
Source/WebKit/StorageProcess/StorageProcess.cpp
Source/WebKit/StorageProcess/StorageProcess.h
Source/WebKit/StorageProcess/ios/StorageProcessIOS.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Configurations/TestWebKitAPI-iOS.entitlements
Tools/WebKitTestRunner/Configurations/WebKitTestRunnerApp-iOS.entitlements [new file with mode: 0644]
Tools/WebKitTestRunner/Configurations/WebKitTestRunnerApp.xcconfig
Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj

index 37be0fe..0b5d0cd 100644 (file)
@@ -1,3 +1,38 @@
+2018-02-16  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Add an entitlement check for service worker on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=182865
+        <rdar://problem/37505903>
+
+        Reviewed by Brady Eidson.
+
+        Added an entitlement check to enable service workers on iOS.
+
+        * Shared/mac/SandboxUtilities.h:
+        * Shared/mac/SandboxUtilities.mm:
+        (WebKit::connectedProcessHasEntitlement): Added.
+        * StorageProcess/StorageProcess.cpp:
+        (WebKit::StorageProcess::createStorageToWebProcessConnection): Enforce the entitlement check by crashing
+        when this code is executed without the parent process having the service worker entitlement. This should
+        never happen unless someone is trying to bypass the entitlement check in UI Process since we ordinarily
+        disable service worker gracefully in WKWebView _initializeWithConfiguration.
+        (WebKit::StorageProcess::swServerForSession): Ditto.
+        (WebKit::StorageProcess::registerSWServerConnection): Ditto.
+        * StorageProcess/StorageProcess.h:
+        (WebKit::StorageProcess::parentProcessHasServiceWorkerEntitlement const): Added.
+        * StorageProcess/ios/StorageProcessIOS.mm:
+        (WebKit::StorageProcess::parentProcessHasServiceWorkerEntitlement const): Added.
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _initializeWithConfiguration:]): Disable the service workers when the entitlement is
+        missing from the current process. The entitlement is enforced by WebContent and Storage process.
+        This check avoids crashing WebContent process and gracefully disabling the feature.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::updatePreferences): Enforce the entitlement check.
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::parentProcessHasServiceWorkerEntitlement const): Added.
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::parentProcessHasServiceWorkerEntitlement const): Added.
+
 2018-02-16  Youenn Fablet  <youenn@apple.com>
 
         Allow specifying which plug-ins are supported
index 4c8e792..2ccbdb9 100644 (file)
@@ -39,5 +39,6 @@ bool processHasContainer();
 String pathForProcessContainer();
 
 bool processHasEntitlement(NSString *entitlement);
+bool connectedProcessHasEntitlement(xpc_connection_t, NSString *entitlement);
 
 }
index 14cd9b3..adf8a08 100644 (file)
@@ -92,4 +92,20 @@ bool processHasEntitlement(NSString *entitlement)
     return CFBooleanGetValue(static_cast<CFBooleanRef>(value.get()));
 }
 
+bool connectedProcessHasEntitlement(xpc_connection_t connection, NSString *entitlement)
+{
+    audit_token_t token;
+    xpc_connection_get_audit_token(connection, &token);
+    auto task = adoptCF(SecTaskCreateWithAuditToken(NULL, token));
+
+    auto value = adoptCF(SecTaskCopyValueForEntitlement(task.get(), (__bridge CFStringRef)entitlement, nullptr));
+    if (!value)
+        return false;
+
+    if (CFGetTypeID(value.get()) != CFBooleanGetTypeID())
+        return false;
+
+    return CFBooleanGetValue(static_cast<CFBooleanRef>(value.get()));
+}
+
 }
index 024dac3..821a316 100644 (file)
@@ -254,6 +254,7 @@ void StorageProcess::createStorageToWebProcessConnection(bool isServiceWorkerPro
 
 #if ENABLE(SERVICE_WORKER)
     if (isServiceWorkerProcess && !m_storageToWebProcessConnections.isEmpty()) {
+        RELEASE_ASSERT(parentProcessHasServiceWorkerEntitlement());
         ASSERT(m_waitingForServerToContextProcessConnection);
         m_serverToContextConnection = WebSWServerToContextConnection::create(m_storageToWebProcessConnections.last()->connection());
         m_waitingForServerToContextProcessConnection = false;
@@ -404,6 +405,7 @@ void StorageProcess::didGetSandboxExtensionsForBlobFiles(uint64_t requestID, San
 #if ENABLE(SERVICE_WORKER)
 SWServer& StorageProcess::swServerForSession(PAL::SessionID sessionID)
 {
+    RELEASE_ASSERT(parentProcessHasServiceWorkerEntitlement());
     ASSERT(sessionID.isValid());
     auto result = m_swServers.add(sessionID, nullptr);
     if (!result.isNewEntry) {
@@ -492,6 +494,7 @@ void StorageProcess::postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier
 
 void StorageProcess::registerSWServerConnection(WebSWServerConnection& connection)
 {
+    RELEASE_ASSERT(parentProcessHasServiceWorkerEntitlement());
     ASSERT(!m_swServerConnections.contains(connection.identifier()));
     m_swServerConnections.add(connection.identifier(), &connection);
     swOriginStoreForSession(connection.sessionID()).registerSWServerConnection(connection);
index d47e0ab..3b15f16 100644 (file)
@@ -86,6 +86,12 @@ public:
     void getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, WTF::Function<void (SandboxExtension::HandleArray&&)>&& completionHandler);
 #endif
 
+#if PLATFORM(IOS)
+    bool parentProcessHasServiceWorkerEntitlement() const;
+#else
+    bool parentProcessHasServiceWorkerEntitlement() const { return true; }
+#endif
+
 #if ENABLE(SERVICE_WORKER)
     // For now we just have one global connection to service worker context processes.
     // This will change in the future.
index 7611f64..568b831 100644 (file)
@@ -30,6 +30,7 @@
 #import "StorageProcess.h"
 
 #import "SandboxInitializationParameters.h"
+#import "SandboxUtilities.h"
 #import <WebCore/FileSystem.h>
 #import <WebCore/LocalizedStrings.h>
 #import <WebCore/NotImplemented.h>
@@ -58,6 +59,12 @@ void StorageProcess::initializeSandbox(const ChildProcessInitializationParameter
 #endif
 }
 
+bool StorageProcess::parentProcessHasServiceWorkerEntitlement() const
+{
+    static bool hasEntitlement = connectedProcessHasEntitlement(parentProcessConnection()->xpcConnection(), @"com.apple.developer.WebKit.ServiceWorkers");
+    return hasEntitlement;
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(IOS)
index 943ef3c..20e4cf4 100644 (file)
@@ -44,6 +44,7 @@
 #import "RemoteLayerTreeTransaction.h"
 #import "RemoteObjectRegistry.h"
 #import "RemoteObjectRegistryMessages.h"
+#import "SandboxUtilities.h"
 #import "UIDelegate.h"
 #import "VersionChecks.h"
 #import "ViewGestureController.h"
@@ -606,6 +607,11 @@ static void validate(WKWebViewConfiguration *configuration)
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::legacyEncryptedMediaAPIEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _legacyEncryptedMediaAPIEnabled]));
 #endif
 
+#if PLATFORM(IOS) && ENABLE(SERVICE_WORKER)
+    if (!WebKit::processHasEntitlement(@"com.apple.developer.WebKit.ServiceWorkers"))
+        pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::serviceWorkersEnabledKey(), WebKit::WebPreferencesStore::Value(false));
+#endif
+
 #if PLATFORM(IOS)
     CGRect bounds = self.bounds;
     _scrollView = adoptNS([[WKScrollView alloc] initWithFrame:bounds]);
index 16177f7..eff4a0a 100644 (file)
@@ -3180,6 +3180,9 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
 #endif
 #endif
 
+    if (store.getBoolValueForKey(WebPreferencesKey::serviceWorkersEnabledKey()))
+        RELEASE_ASSERT(parentProcessHasServiceWorkerEntitlement());
+
     if (m_drawingArea)
         m_drawingArea->updatePreferences(store);
 }
index 8fdcef0..bdb303c 100644 (file)
@@ -1213,6 +1213,12 @@ private:
     void updatePreferences(const WebPreferencesStore&);
     void updatePreferencesGenerated(const WebPreferencesStore&);
 
+#if PLATFORM(IOS)
+    bool parentProcessHasServiceWorkerEntitlement() const;
+#else
+    bool parentProcessHasServiceWorkerEntitlement() const { return true; }
+#endif
+
     void didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, WebCore::PolicyAction, uint64_t navigationID, const DownloadID&, std::optional<WebsitePoliciesData>&&);
     void continueWillSubmitForm(uint64_t frameID, uint64_t listenerID);
     void setUserAgent(const String&);
index 7ffb3f8..aaf25cb 100644 (file)
@@ -40,6 +40,7 @@
 #import "PluginView.h"
 #import "PrintInfo.h"
 #import "RemoteLayerTreeDrawingArea.h"
+#import "SandboxUtilities.h"
 #import "UserData.h"
 #import "VisibleContentRectUpdateInfo.h"
 #import "WKAccessibilityWebPageObjectIOS.h"
@@ -389,6 +390,12 @@ bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* event)
     return sendResult && eventWasHandled;
 }
 
+bool WebPage::parentProcessHasServiceWorkerEntitlement() const
+{
+    static bool hasEntitlement = connectedProcessHasEntitlement(WebProcess::singleton().parentProcessConnection()->xpcConnection(), @"com.apple.developer.WebKit.ServiceWorkers");
+    return hasEntitlement;
+}
+
 void WebPage::sendComplexTextInputToPlugin(uint64_t, const String&)
 {
     notImplemented();
index bc1c0f8..cc8e853 100644 (file)
@@ -1,3 +1,18 @@
+2018-02-16  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Add an entitlement check for service worker on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=182865
+        <rdar://problem/37505903>
+
+        Reviewed by Brady Eidson.
+
+        Added the service worker entitlements to WebKitTestRunner and TestWebKitAPI on iOS.
+
+        * TestWebKitAPI/Configurations/TestWebKitAPI-iOS.entitlements:
+        * WebKitTestRunner/Configurations/WebKitTestRunnerApp-iOS.entitlements:
+        * WebKitTestRunner/Configurations/WebKitTestRunnerApp.xcconfig:
+        * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
+
 2018-02-16  Youenn Fablet  <youenn@apple.com>
 
         Allow specifying which plug-ins are supported
index e6db892..53fb2f0 100644 (file)
@@ -6,5 +6,7 @@
        <array>
                <string>com.apple.TestWebKitAPI</string>
        </array>
+       <key>com.apple.developer.WebKit.ServiceWorkers</key>
+       <true/>
 </dict>
 </plist>
diff --git a/Tools/WebKitTestRunner/Configurations/WebKitTestRunnerApp-iOS.entitlements b/Tools/WebKitTestRunner/Configurations/WebKitTestRunnerApp-iOS.entitlements
new file mode 100644 (file)
index 0000000..581afaa
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>com.apple.developer.WebKit.ServiceWorkers</key>
+    <true/>
+</dict>
+</plist>
index 9f56d9c..97eea6d 100644 (file)
@@ -39,3 +39,5 @@ EXCLUDED_SOURCE_FILE_NAMES[sdk=appletv*] = ios/Launch.storyboard;
 EXCLUDED_SOURCE_FILE_NAMES[sdk=watch*] = ios/Launch.storyboard;
 
 TARGETED_DEVICE_FAMILY = 1,2;
+
+CODE_SIGN_ENTITLEMENTS[sdk=iphone*] = Configurations/WebKitTestRunnerApp-iOS.entitlements;
index e97ffb1..fc6f84e 100644 (file)
                841CC00D181185BF0042E9B6 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; };
                841CC00E181185BF0042E9B6 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
                8DD76FA10486AA7600D96B5E /* WebKitTestRunner */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WebKitTestRunner; sourceTree = BUILT_PRODUCTS_DIR; };
+               9B0D132E2036D346008FC8FB /* WebKitTestRunnerApp-iOS.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "WebKitTestRunnerApp-iOS.entitlements"; sourceTree = "<group>"; };
                A18510271B9ADE4800744AEB /* libWebKitTestRunner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWebKitTestRunner.a; sourceTree = BUILT_PRODUCTS_DIR; };
                A18510381B9ADF2200744AEB /* WebKitTestRunner.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = WebKitTestRunner.xcconfig; sourceTree = "<group>"; };
                A18510391B9ADFF800744AEB /* WebKitTestRunnerApp.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = WebKitTestRunnerApp.xcconfig; sourceTree = "<group>"; };
                                BC793427118F7DAF005EA8E2 /* DebugRelease.xcconfig */,
                                BC25197111D15E61002EBC01 /* InjectedBundle.xcconfig */,
                                A18510381B9ADF2200744AEB /* WebKitTestRunner.xcconfig */,
+                               9B0D132E2036D346008FC8FB /* WebKitTestRunnerApp-iOS.entitlements */,
                                A18510391B9ADFF800744AEB /* WebKitTestRunnerApp.xcconfig */,
                                BC251A1811D16795002EBC01 /* WebKitTestRunnerLibrary.xcconfig */,
                        );