Title: [293509] trunk/Source/WebKit
Revision
293509
Author
pvol...@apple.com
Date
2022-04-27 08:49:37 -0700 (Wed, 27 Apr 2022)

Log Message

[macOS] The function getpwnam can sometimes fail
https://bugs.webkit.org/show_bug.cgi?id=239513
<rdar://89758690>

Reviewed by Darin Adler.

The system function getpwnam is caching the results from the first invocation, and will return the cached
values after the first call. It may happen that opendirectoryd will invalidate the cached values by
posting notifications. If that happens, getpwnam will then fail, since there are no cached values and
the WebContent process' sandbox is blocking access to opendirectoryd. This patch addresses this issue
by observing these notifications in the UI process, and recreating the cached values for getpwnam, by
calling the function in the WebContent process while holding a temporary sandbox extenstion to
opendirectoryd.

* GPUProcess/GPUProcess.h:
* GPUProcess/GPUProcess.messages.in:
* GPUProcess/mac/GPUProcessMac.mm:
(WebKit::GPUProcess::openDirectoryCacheInvalidated):
* GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in:
* Shared/AuxiliaryProcess.h:
* Shared/mac/AuxiliaryProcessMac.mm:
(WebKit::getHomeDirectory):
(WebKit::populateSandboxInitializationParameters):
(WebKit::AuxiliaryProcess::openDirectoryCacheInvalidated):
* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::WebProcessPool::registerNotificationObservers):
(WebKit::WebProcessPool::unregisterNotificationObservers):
* UIProcess/WebProcessPool.h:
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:
* WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::WebProcess::openDirectoryCacheInvalidated):
* WebProcess/com.apple.WebProcess.sb.in:

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (293508 => 293509)


--- trunk/Source/WebKit/ChangeLog	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/ChangeLog	2022-04-27 15:49:37 UTC (rev 293509)
@@ -1,3 +1,39 @@
+2022-04-27  Per Arne Vollan  <pvol...@apple.com>
+
+        [macOS] The function getpwnam can sometimes fail
+        https://bugs.webkit.org/show_bug.cgi?id=239513
+        <rdar://89758690>
+
+        Reviewed by Darin Adler.
+
+        The system function getpwnam is caching the results from the first invocation, and will return the cached
+        values after the first call. It may happen that opendirectoryd will invalidate the cached values by
+        posting notifications. If that happens, getpwnam will then fail, since there are no cached values and
+        the WebContent process' sandbox is blocking access to opendirectoryd. This patch addresses this issue
+        by observing these notifications in the UI process, and recreating the cached values for getpwnam, by
+        calling the function in the WebContent process while holding a temporary sandbox extenstion to
+        opendirectoryd.
+
+        * GPUProcess/GPUProcess.h:
+        * GPUProcess/GPUProcess.messages.in:
+        * GPUProcess/mac/GPUProcessMac.mm:
+        (WebKit::GPUProcess::openDirectoryCacheInvalidated):
+        * GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in:
+        * Shared/AuxiliaryProcess.h:
+        * Shared/mac/AuxiliaryProcessMac.mm:
+        (WebKit::getHomeDirectory):
+        (WebKit::populateSandboxInitializationParameters):
+        (WebKit::AuxiliaryProcess::openDirectoryCacheInvalidated):
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (WebKit::WebProcessPool::registerNotificationObservers):
+        (WebKit::WebProcessPool::unregisterNotificationObservers):
+        * UIProcess/WebProcessPool.h:
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+        * WebProcess/cocoa/WebProcessCocoa.mm:
+        (WebKit::WebProcess::openDirectoryCacheInvalidated):
+        * WebProcess/com.apple.WebProcess.sb.in:
+
 2022-04-26  Michael Catanzaro  <mcatanz...@redhat.com>
 
         [GLib] Make WebKitSettings XSS auditor functions no-op

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.h (293508 => 293509)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.h	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.h	2022-04-27 15:49:37 UTC (rev 293509)
@@ -202,6 +202,10 @@
     void dispatchSimulatedNotificationsForPreferenceChange(const String& key) final;
 #endif
 
+#if PLATFORM(MAC)
+    void openDirectoryCacheInvalidated(SandboxExtension::Handle&&);
+#endif
+
     // Connections to WebProcesses.
     HashMap<WebCore::ProcessIdentifier, Ref<GPUConnectionToWebProcess>> m_webProcessConnections;
     MonotonicTime m_creationTime { MonotonicTime::now() };

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in (293508 => 293509)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in	2022-04-27 15:49:37 UTC (rev 293509)
@@ -91,6 +91,10 @@
     NotifyPreferencesChanged(String domain, String key, std::optional<String> encodedValue)
 #endif
 
+#if PLATFORM(MAC)
+    OpenDirectoryCacheInvalidated(WebKit::SandboxExtension::Handle handle)
+#endif
+
     WebProcessConnectionCountForTesting() -> (uint64_t count)
 }
 

Modified: trunk/Source/WebKit/GPUProcess/mac/GPUProcessMac.mm (293508 => 293509)


--- trunk/Source/WebKit/GPUProcess/mac/GPUProcessMac.mm	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/GPUProcess/mac/GPUProcessMac.mm	2022-04-27 15:49:37 UTC (rev 293509)
@@ -97,6 +97,12 @@
     setShouldOverrideScreenSupportsHighDynamicRange(true, allScreensAreHDR);
 #endif
 }
+
+void GPUProcess::openDirectoryCacheInvalidated(SandboxExtension::Handle&& handle)
+{
+    AuxiliaryProcess::openDirectoryCacheInvalidated(WTFMove(handle));
+}
+
 #endif
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in (293508 => 293509)


--- trunk/Source/WebKit/GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in	2022-04-27 15:49:37 UTC (rev 293509)
@@ -876,6 +876,11 @@
 )
 #endif
 
+(allow mach-lookup
+    (require-all
+        (extension "com.apple.webkit.extension.mach")
+        (global-name "com.apple.system.opendirectoryd.libinfo")))
+
 (allow mach-lookup (with telemetry)
     (global-name "com.apple.relatived.tempest")
 )

Modified: trunk/Source/WebKit/Shared/AuxiliaryProcess.h (293508 => 293509)


--- trunk/Source/WebKit/Shared/AuxiliaryProcess.h	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/Shared/AuxiliaryProcess.h	2022-04-27 15:49:37 UTC (rev 293509)
@@ -28,6 +28,7 @@
 #include "Connection.h"
 #include "MessageReceiverMap.h"
 #include "MessageSender.h"
+#include "SandboxExtension.h"
 #include <WebCore/ProcessIdentifier.h>
 #include <WebCore/RuntimeApplicationChecks.h>
 #include <WebCore/UserActivity.h>
@@ -145,6 +146,10 @@
 #endif
     void applyProcessCreationParameters(const AuxiliaryProcessCreationParameters&);
 
+#if PLATFORM(MAC)
+    void openDirectoryCacheInvalidated(SandboxExtension::Handle&&);
+#endif
+
 private:
     virtual bool shouldOverrideQuarantine() { return true; }
 

Modified: trunk/Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm (293508 => 293509)


--- trunk/Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm	2022-04-27 15:49:37 UTC (rev 293509)
@@ -665,6 +665,20 @@
     return osSystemMarketingVersion.left(secondDotIndex);
 }
 
+static String getHomeDirectory()
+{
+    // According to the man page for getpwuid_r, we should use sysconf(_SC_GETPW_R_SIZE_MAX) to determine the size of the buffer.
+    // However, a buffer size of 4096 should be sufficient, since PATH_MAX is 1024.
+    char buffer[4096];
+    passwd pwd;
+    passwd* result = nullptr;
+    if (getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &result) || !result) {
+        WTFLogAlways("%s: Couldn't find home directory", getprogname());
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    return String::fromUTF8(pwd.pw_dir);
+}
+
 static void populateSandboxInitializationParameters(SandboxInitializationParameters& sandboxParameters)
 {
     RELEASE_ASSERT(!sandboxParameters.userDirectorySuffix().isNull());
@@ -690,17 +704,10 @@
     sandboxParameters.addConfDirectoryParameter("DARWIN_USER_TEMP_DIR", _CS_DARWIN_USER_TEMP_DIR);
     sandboxParameters.addConfDirectoryParameter("DARWIN_USER_CACHE_DIR", _CS_DARWIN_USER_CACHE_DIR);
 
-    char buffer[4096];
-    int bufferSize = sizeof(buffer);
-    struct passwd pwd;
-    struct passwd* result = 0;
-    if (getpwuid_r(getuid(), &pwd, buffer, bufferSize, &result) || !result) {
-        WTFLogAlways("%s: Couldn't find home directory\n", getprogname());
-        exit(EX_NOPERM);
-    }
-
-    sandboxParameters.addPathParameter("HOME_DIR", pwd.pw_dir);
-    String path = FileSystem::pathByAppendingComponent(String::fromUTF8(pwd.pw_dir), "Library"_s);
+    auto homeDirectory = getHomeDirectory();
+    
+    sandboxParameters.addPathParameter("HOME_DIR", homeDirectory);
+    String path = FileSystem::pathByAppendingComponent(homeDirectory, "Library"_s);
     sandboxParameters.addPathParameter("HOME_LIBRARY_DIR", FileSystem::fileSystemRepresentation(path).data());
     path = FileSystem::pathByAppendingComponent(path, "/Preferences"_s);
     sandboxParameters.addPathParameter("HOME_LIBRARY_PREFERENCES_DIR", FileSystem::fileSystemRepresentation(path).data());
@@ -824,6 +831,23 @@
 }
 #endif
 
+void AuxiliaryProcess::openDirectoryCacheInvalidated(SandboxExtension::Handle&& handle)
+{
+    // When Open Directory has invalidated the in-process cache for the results of getpwnam/getpwuid_r,
+    // we need to rebuild the cache by getting the home directory while holding a temporary sandbox
+    // extension to the associated Open Directory service.
+
+    auto sandboxExtension = SandboxExtension::create(WTFMove(handle));
+    if (!sandboxExtension)
+        return;
+
+    sandboxExtension->consume();
+
+    getHomeDirectory();
+
+    sandboxExtension->revoke();
+}
+
 } // namespace WebKit
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (293508 => 293509)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2022-04-27 15:49:37 UTC (rev 293509)
@@ -88,6 +88,8 @@
 #if PLATFORM(MAC)
 #import "WebInspectorPreferenceObserver.h"
 #import <QuartzCore/CARemoteLayerServer.h>
+#import <notify.h>
+#import <notify_keys.h>
 #import <pal/spi/mac/NSApplicationSPI.h>
 #else
 #import "UIKitSPI.h"
@@ -707,6 +709,24 @@
     }];
     
     addCFNotificationObserver(colorPreferencesDidChangeCallback, AppleColorPreferencesChangedNotification, CFNotificationCenterGetDistributedCenter());
+
+    const char* messages[] = { kNotifyDSCacheInvalidation, kNotifyDSCacheInvalidationGroup, kNotifyDSCacheInvalidationHost, kNotifyDSCacheInvalidationService, kNotifyDSCacheInvalidationUser };
+    m_openDirectoryNotifyTokens.reserveInitialCapacity(std::size(messages));
+    for (auto* message : messages) {
+        int notifyToken;
+        notify_register_dispatch(message, &notifyToken, dispatch_get_main_queue(), ^(int token) {
+            RELEASE_LOG(Notifications, "OpenDirectory invalidated cache");
+            auto handle = SandboxExtension::createHandleForMachLookup("com.apple.system.opendirectoryd.libinfo"_s, std::nullopt);
+            if (!handle)
+                return;
+#if ENABLE(GPU_PROCESS)
+            if (auto* gpuProcess = GPUProcessProxy::singletonIfCreated())
+                gpuProcess->send(Messages::GPUProcess::OpenDirectoryCacheInvalidated(*handle), 0);
+#endif
+            sendToAllProcesses(Messages::WebProcess::OpenDirectoryCacheInvalidated(*handle));
+        });
+        m_openDirectoryNotifyTokens.append(notifyToken);
+    }
 #elif !PLATFORM(MACCATALYST)
     addCFNotificationObserver(backlightLevelDidChangeCallback, (__bridge CFStringRef)UIBacklightLevelChangedNotification);
 #if PLATFORM(IOS)
@@ -770,6 +790,8 @@
     [[NSNotificationCenter defaultCenter] removeObserver:m_scrollerStyleNotificationObserver.get()];
     [[NSNotificationCenter defaultCenter] removeObserver:m_deactivationObserver.get()];
     removeCFNotificationObserver(AppleColorPreferencesChangedNotification, CFNotificationCenterGetDistributedCenter());
+    for (auto token : m_openDirectoryNotifyTokens)
+        notify_cancel(token);
 #elif !PLATFORM(MACCATALYST)
     removeCFNotificationObserver((__bridge CFStringRef)UIBacklightLevelChangedNotification);
 #if PLATFORM(IOS)

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (293508 => 293509)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2022-04-27 15:49:37 UTC (rev 293509)
@@ -810,6 +810,7 @@
 #if PLATFORM(MAC)
     std::unique_ptr<WebCore::PowerObserver> m_powerObserver;
     std::unique_ptr<PAL::SystemSleepListener> m_systemSleepListener;
+    Vector<int> m_openDirectoryNotifyTokens;
 #endif
 #if ENABLE(IPC_TESTING_API)
     IPCTester m_ipcTester;

Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (293508 => 293509)


--- trunk/Source/WebKit/WebProcess/WebProcess.h	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h	2022-04-27 15:49:37 UTC (rev 293509)
@@ -29,7 +29,6 @@
 #include "AuxiliaryProcess.h"
 #include "CacheModel.h"
 #include "IdentifierTypes.h"
-#include "SandboxExtension.h"
 #include "StorageAreaMapIdentifier.h"
 #include "TextCheckerState.h"
 #include "UserContentControllerIdentifier.h"
@@ -353,6 +352,10 @@
     void powerSourceDidChange(bool);
 #endif
 
+#if PLATFORM(MAC)
+    void openDirectoryCacheInvalidated(SandboxExtension::Handle&&);
+#endif
+
     bool areAllPagesThrottleable() const;
 
     void messagesAvailableForPort(const WebCore::MessagePortIdentifier&);

Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (293508 => 293509)


--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2022-04-27 15:49:37 UTC (rev 293509)
@@ -201,4 +201,8 @@
 #if HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
     SetMediaAccessibilityPreferences(WebCore::CaptionUserPreferences::CaptionDisplayMode displayMode, Vector<String> languages)
 #endif
+
+#if PLATFORM(MAC)
+    OpenDirectoryCacheInvalidated(WebKit::SandboxExtension::Handle handle)
+#endif
 }

Modified: trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm (293508 => 293509)


--- trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm	2022-04-27 15:49:37 UTC (rev 293509)
@@ -1290,6 +1290,13 @@
         WEBPROCESS_RELEASE_LOG_ERROR(Process, "Could not apply AudioComponent registrations, err(%ld)", static_cast<long>(err));
 }
 
+#if PLATFORM(MAC)
+void WebProcess::openDirectoryCacheInvalidated(SandboxExtension::Handle&& handle)
+{
+    AuxiliaryProcess::openDirectoryCacheInvalidated(WTFMove(handle));
+}
+#endif
+
 } // namespace WebKit
 
 #undef RELEASE_LOG_SESSION_ID

Modified: trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in (293508 => 293509)


--- trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in	2022-04-27 14:11:34 UTC (rev 293508)
+++ trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in	2022-04-27 15:49:37 UTC (rev 293509)
@@ -1466,6 +1466,10 @@
        (global-name "com.apple.system.opendirectoryd.libinfo")
        (global-name "com.apple.system.opendirectoryd.membership"))
 )
+(allow mach-lookup
+    (require-all
+        (extension "com.apple.webkit.extension.mach")
+        (global-name "com.apple.system.opendirectoryd.libinfo")))
 #else
 (allow file-read* file-write* (subpath "/private/var/db/mds/system")) ;; FIXME: This should be removed when <rdar://problem/9538414> is fixed.
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to