[Mac] Use the PID of the WebContent process when issuing local file read sandbox extensions
https://bugs.webkit.org/show_bug.cgi?id=200543
<rdar://problem/49394015>
Source/WebKit:

Reviewed by Brent Fulgham.

Adopt SPI to issue a process-specific sandbox extension for local file read, passing it the process
identifier of the WebContent process.

* Shared/Cocoa/SandboxExtensionCocoa.mm:
(WebKit::SandboxExtensionImpl::sandboxExtensionForType):
(WebKit::SandboxExtension::createHandleForReadByPid):
* Shared/SandboxExtension.h:
* UIProcess/Cocoa/WebPageProxyCocoa.mm:
(WebKit::WebPageProxy::createSandboxExtensionsIfNeeded):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::maybeInitializeSandboxExtensionHandle):
(WebKit::WebPageProxy::loadFile):

Source/WTF:

Reviewed by Brent Fulgham.

Add new SPI.

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


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@248832 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog
index 979b69b..220eb1d 100644
--- a/Source/WTF/ChangeLog
+++ b/Source/WTF/ChangeLog
@@ -1,3 +1,16 @@
+2019-08-18  Per Arne Vollan  <pvollan@apple.com>
+
+        [Mac] Use the PID of the WebContent process when issuing local file read sandbox extensions
+        https://bugs.webkit.org/show_bug.cgi?id=200543
+        <rdar://problem/49394015>
+
+        Reviewed by Brent Fulgham.
+
+        Add new SPI.
+        
+        * wtf/Platform.h:
+        * wtf/spi/darwin/SandboxSPI.h:
+
 2019-08-17  Darin Adler  <darin@apple.com>
 
         Tidy up checks to see if a character is in the Latin-1 range by using isLatin1 consistently
diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h
index 6355e8e..f14f006 100644
--- a/Source/WTF/wtf/Platform.h
+++ b/Source/WTF/wtf/Platform.h
@@ -1534,6 +1534,10 @@
 #define HAVE_SANDBOX_ISSUE_MACH_EXTENSION_TO_PROCESS_BY_PID 1
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400)
+#define HAVE_SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID 1
+#endif
+
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
 #define HAVE_MDNS_FAST_REGISTRATION 1
 #endif
diff --git a/Source/WTF/wtf/spi/darwin/SandboxSPI.h b/Source/WTF/wtf/spi/darwin/SandboxSPI.h
index f58f5aa..56c9f20 100644
--- a/Source/WTF/wtf/spi/darwin/SandboxSPI.h
+++ b/Source/WTF/wtf/spi/darwin/SandboxSPI.h
@@ -58,9 +58,12 @@
 extern const char *const APP_SANDBOX_READ_WRITE;
 extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT;
 
+extern const uint32_t SANDBOX_EXTENSION_USER_INTENT;
+
 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);
+char *sandbox_extension_issue_file_to_process_by_pid(const char *extension_class, const char *path, 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);
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 07183de..4a5e952 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,24 @@
+2019-08-18  Per Arne Vollan  <pvollan@apple.com>
+
+        [Mac] Use the PID of the WebContent process when issuing local file read sandbox extensions
+        https://bugs.webkit.org/show_bug.cgi?id=200543
+        <rdar://problem/49394015>
+        
+        Reviewed by Brent Fulgham.
+
+        Adopt SPI to issue a process-specific sandbox extension for local file read, passing it the process
+        identifier of the WebContent process.
+        
+        * Shared/Cocoa/SandboxExtensionCocoa.mm:
+        (WebKit::SandboxExtensionImpl::sandboxExtensionForType):
+        (WebKit::SandboxExtension::createHandleForReadByPid):
+        * Shared/SandboxExtension.h:
+        * UIProcess/Cocoa/WebPageProxyCocoa.mm:
+        (WebKit::WebPageProxy::createSandboxExtensionsIfNeeded):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::maybeInitializeSandboxExtensionHandle):
+        (WebKit::WebPageProxy::loadFile):
+
 2019-08-17  Tim Horton  <timothy_horton@apple.com>
 
         Layout tests that call resizeTo() crash when run on iOS with IOSurface support enabled
diff --git a/Source/WebKit/Shared/Cocoa/SandboxExtensionCocoa.mm b/Source/WebKit/Shared/Cocoa/SandboxExtensionCocoa.mm
index b0020ed..760ce46 100644
--- a/Source/WebKit/Shared/Cocoa/SandboxExtensionCocoa.mm
+++ b/Source/WebKit/Shared/Cocoa/SandboxExtensionCocoa.mm
@@ -101,6 +101,14 @@
 #endif
         case SandboxExtension::Type::Generic:
             return sandbox_extension_issue_generic(path, 0);
+        case SandboxExtension::Type::ReadByPid:
+#if HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID)
+            return sandbox_extension_issue_file_to_process_by_pid(APP_SANDBOX_READ, path, SANDBOX_EXTENSION_USER_INTENT, pid.value());
+#else
+            UNUSED_PARAM(pid);
+            ASSERT_NOT_REACHED();
+            return nullptr;
+#endif
         }
     }
 
@@ -337,6 +345,22 @@
     return true;
 }
 
+bool SandboxExtension::createHandleForReadByPid(const String& path, ProcessID pid, Handle& handle)
+{
+    ASSERT(!handle.m_sandboxExtension);
+    
+    if (!pid)
+        return false;
+
+    handle.m_sandboxExtension = SandboxExtensionImpl::create(path.utf8().data(), Type::ReadByPid, pid);
+    if (!handle.m_sandboxExtension) {
+        WTFLogAlways("Could not create sandbox extension");
+        return false;
+    }
+    
+    return true;
+}
+
 SandboxExtension::SandboxExtension(const Handle& handle)
     : m_sandboxExtension(WTFMove(handle.m_sandboxExtension))
 {
diff --git a/Source/WebKit/Shared/SandboxExtension.h b/Source/WebKit/Shared/SandboxExtension.h
index 693bd70..bae4a56 100644
--- a/Source/WebKit/Shared/SandboxExtension.h
+++ b/Source/WebKit/Shared/SandboxExtension.h
@@ -49,6 +49,7 @@
         ReadWrite,
         Mach,
         Generic,
+        ReadByPid
     };
 
     class Handle {
@@ -104,6 +105,7 @@
     static String createHandleForTemporaryFile(const String& prefix, Type, Handle&);
     static bool createHandleForGenericExtension(const String& extensionClass, Handle&);
     static bool createHandleForMachLookupByPid(const String& service, ProcessID, Handle&);
+    static bool createHandleForReadByPid(const String& path, ProcessID, Handle&);
     ~SandboxExtension();
 
     bool consume();
diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
index d961391..8a394af 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
@@ -126,6 +126,9 @@
     if (files.size() == 1) {
         BOOL isDirectory;
         if ([[NSFileManager defaultManager] fileExistsAtPath:files[0] isDirectory:&isDirectory] && !isDirectory) {
+#if HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID)
+            if (!SandboxExtension::createHandleForReadByPid("/", processIdentifier(), fileReadHandle))
+#endif
             SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, fileReadHandle);
             willAcquireUniversalFileReadSandboxExtension(m_process);
         }
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 485b31d..e69bc75 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -1076,6 +1076,12 @@
     // Inspector resources are in a directory with assumed access.
     ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
 
+#if HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID)
+    if (SandboxExtension::createHandleForReadByPid("/", process.processIdentifier(), sandboxExtensionHandle)) {
+        willAcquireUniversalFileReadSandboxExtension(process);
+        return;
+    }
+#endif
     if (SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle)) {
         willAcquireUniversalFileReadSandboxExtension(process);
         return;
@@ -1194,6 +1200,9 @@
     loadParameters.request = fileURL;
     loadParameters.shouldOpenExternalURLsPolicy = ShouldOpenExternalURLsPolicy::ShouldNotAllow;
     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
+#if HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID)
+    if (!SandboxExtension::createHandleForReadByPid(resourceDirectoryPath, processIdentifier(), loadParameters.sandboxExtensionHandle))
+#endif
     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
     addPlatformLoadParameters(loadParameters);