Changeset 293509 in webkit


Ignore:
Timestamp:
Apr 27, 2022 8:49:37 AM (2 years ago)
Author:
pvollan@apple.com
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:
Location:
trunk/Source/WebKit
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r293507 r293509  
     12022-04-27  Per Arne Vollan  <pvollan@apple.com>
     2
     3        [macOS] The function getpwnam can sometimes fail
     4        https://bugs.webkit.org/show_bug.cgi?id=239513
     5        <rdar://89758690>
     6
     7        Reviewed by Darin Adler.
     8
     9        The system function getpwnam is caching the results from the first invocation, and will return the cached
     10        values after the first call. It may happen that opendirectoryd will invalidate the cached values by
     11        posting notifications. If that happens, getpwnam will then fail, since there are no cached values and
     12        the WebContent process' sandbox is blocking access to opendirectoryd. This patch addresses this issue
     13        by observing these notifications in the UI process, and recreating the cached values for getpwnam, by
     14        calling the function in the WebContent process while holding a temporary sandbox extenstion to
     15        opendirectoryd.
     16
     17        * GPUProcess/GPUProcess.h:
     18        * GPUProcess/GPUProcess.messages.in:
     19        * GPUProcess/mac/GPUProcessMac.mm:
     20        (WebKit::GPUProcess::openDirectoryCacheInvalidated):
     21        * GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in:
     22        * Shared/AuxiliaryProcess.h:
     23        * Shared/mac/AuxiliaryProcessMac.mm:
     24        (WebKit::getHomeDirectory):
     25        (WebKit::populateSandboxInitializationParameters):
     26        (WebKit::AuxiliaryProcess::openDirectoryCacheInvalidated):
     27        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
     28        (WebKit::WebProcessPool::registerNotificationObservers):
     29        (WebKit::WebProcessPool::unregisterNotificationObservers):
     30        * UIProcess/WebProcessPool.h:
     31        * WebProcess/WebProcess.h:
     32        * WebProcess/WebProcess.messages.in:
     33        * WebProcess/cocoa/WebProcessCocoa.mm:
     34        (WebKit::WebProcess::openDirectoryCacheInvalidated):
     35        * WebProcess/com.apple.WebProcess.sb.in:
     36
    1372022-04-26  Michael Catanzaro  <mcatanzaro@redhat.com>
    238
  • trunk/Source/WebKit/GPUProcess/GPUProcess.h

    r291775 r293509  
    203203#endif
    204204
     205#if PLATFORM(MAC)
     206    void openDirectoryCacheInvalidated(SandboxExtension::Handle&&);
     207#endif
     208
    205209    // Connections to WebProcesses.
    206210    HashMap<WebCore::ProcessIdentifier, Ref<GPUConnectionToWebProcess>> m_webProcessConnections;
  • trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in

    r290985 r293509  
    9292#endif
    9393
     94#if PLATFORM(MAC)
     95    OpenDirectoryCacheInvalidated(WebKit::SandboxExtension::Handle handle)
     96#endif
     97
    9498    WebProcessConnectionCountForTesting() -> (uint64_t count)
    9599}
  • trunk/Source/WebKit/GPUProcess/mac/GPUProcessMac.mm

    r289639 r293509  
    9898#endif
    9999}
     100
     101void GPUProcess::openDirectoryCacheInvalidated(SandboxExtension::Handle&& handle)
     102{
     103    AuxiliaryProcess::openDirectoryCacheInvalidated(WTFMove(handle));
     104}
     105
    100106#endif
    101107
  • trunk/Source/WebKit/GPUProcess/mac/com.apple.WebKit.GPUProcess.sb.in

    r292971 r293509  
    877877#endif
    878878
     879(allow mach-lookup
     880    (require-all
     881        (extension "com.apple.webkit.extension.mach")
     882        (global-name "com.apple.system.opendirectoryd.libinfo")))
     883
    879884(allow mach-lookup (with telemetry)
    880885    (global-name "com.apple.relatived.tempest")
  • trunk/Source/WebKit/Shared/AuxiliaryProcess.h

    r292793 r293509  
    2929#include "MessageReceiverMap.h"
    3030#include "MessageSender.h"
     31#include "SandboxExtension.h"
    3132#include <WebCore/ProcessIdentifier.h>
    3233#include <WebCore/RuntimeApplicationChecks.h>
     
    146147    void applyProcessCreationParameters(const AuxiliaryProcessCreationParameters&);
    147148
     149#if PLATFORM(MAC)
     150    void openDirectoryCacheInvalidated(SandboxExtension::Handle&&);
     151#endif
     152
    148153private:
    149154    virtual bool shouldOverrideQuarantine() { return true; }
  • trunk/Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm

    r293266 r293509  
    666666}
    667667
     668static String getHomeDirectory()
     669{
     670    // According to the man page for getpwuid_r, we should use sysconf(_SC_GETPW_R_SIZE_MAX) to determine the size of the buffer.
     671    // However, a buffer size of 4096 should be sufficient, since PATH_MAX is 1024.
     672    char buffer[4096];
     673    passwd pwd;
     674    passwd* result = nullptr;
     675    if (getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &result) || !result) {
     676        WTFLogAlways("%s: Couldn't find home directory", getprogname());
     677        RELEASE_ASSERT_NOT_REACHED();
     678    }
     679    return String::fromUTF8(pwd.pw_dir);
     680}
     681
    668682static void populateSandboxInitializationParameters(SandboxInitializationParameters& sandboxParameters)
    669683{
     
    691705    sandboxParameters.addConfDirectoryParameter("DARWIN_USER_CACHE_DIR", _CS_DARWIN_USER_CACHE_DIR);
    692706
    693     char buffer[4096];
    694     int bufferSize = sizeof(buffer);
    695     struct passwd pwd;
    696     struct passwd* result = 0;
    697     if (getpwuid_r(getuid(), &pwd, buffer, bufferSize, &result) || !result) {
    698         WTFLogAlways("%s: Couldn't find home directory\n", getprogname());
    699         exit(EX_NOPERM);
    700     }
    701 
    702     sandboxParameters.addPathParameter("HOME_DIR", pwd.pw_dir);
    703     String path = FileSystem::pathByAppendingComponent(String::fromUTF8(pwd.pw_dir), "Library"_s);
     707    auto homeDirectory = getHomeDirectory();
     708   
     709    sandboxParameters.addPathParameter("HOME_DIR", homeDirectory);
     710    String path = FileSystem::pathByAppendingComponent(homeDirectory, "Library"_s);
    704711    sandboxParameters.addPathParameter("HOME_LIBRARY_DIR", FileSystem::fileSystemRepresentation(path).data());
    705712    path = FileSystem::pathByAppendingComponent(path, "/Preferences"_s);
     
    825832#endif
    826833
     834void AuxiliaryProcess::openDirectoryCacheInvalidated(SandboxExtension::Handle&& handle)
     835{
     836    // When Open Directory has invalidated the in-process cache for the results of getpwnam/getpwuid_r,
     837    // we need to rebuild the cache by getting the home directory while holding a temporary sandbox
     838    // extension to the associated Open Directory service.
     839
     840    auto sandboxExtension = SandboxExtension::create(WTFMove(handle));
     841    if (!sandboxExtension)
     842        return;
     843
     844    sandboxExtension->consume();
     845
     846    getHomeDirectory();
     847
     848    sandboxExtension->revoke();
     849}
     850
    827851} // namespace WebKit
    828852
  • trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm

    r293266 r293509  
    8989#import "WebInspectorPreferenceObserver.h"
    9090#import <QuartzCore/CARemoteLayerServer.h>
     91#import <notify.h>
     92#import <notify_keys.h>
    9193#import <pal/spi/mac/NSApplicationSPI.h>
    9294#else
     
    708710   
    709711    addCFNotificationObserver(colorPreferencesDidChangeCallback, AppleColorPreferencesChangedNotification, CFNotificationCenterGetDistributedCenter());
     712
     713    const char* messages[] = { kNotifyDSCacheInvalidation, kNotifyDSCacheInvalidationGroup, kNotifyDSCacheInvalidationHost, kNotifyDSCacheInvalidationService, kNotifyDSCacheInvalidationUser };
     714    m_openDirectoryNotifyTokens.reserveInitialCapacity(std::size(messages));
     715    for (auto* message : messages) {
     716        int notifyToken;
     717        notify_register_dispatch(message, &notifyToken, dispatch_get_main_queue(), ^(int token) {
     718            RELEASE_LOG(Notifications, "OpenDirectory invalidated cache");
     719            auto handle = SandboxExtension::createHandleForMachLookup("com.apple.system.opendirectoryd.libinfo"_s, std::nullopt);
     720            if (!handle)
     721                return;
     722#if ENABLE(GPU_PROCESS)
     723            if (auto* gpuProcess = GPUProcessProxy::singletonIfCreated())
     724                gpuProcess->send(Messages::GPUProcess::OpenDirectoryCacheInvalidated(*handle), 0);
     725#endif
     726            sendToAllProcesses(Messages::WebProcess::OpenDirectoryCacheInvalidated(*handle));
     727        });
     728        m_openDirectoryNotifyTokens.append(notifyToken);
     729    }
    710730#elif !PLATFORM(MACCATALYST)
    711731    addCFNotificationObserver(backlightLevelDidChangeCallback, (__bridge CFStringRef)UIBacklightLevelChangedNotification);
     
    771791    [[NSNotificationCenter defaultCenter] removeObserver:m_deactivationObserver.get()];
    772792    removeCFNotificationObserver(AppleColorPreferencesChangedNotification, CFNotificationCenterGetDistributedCenter());
     793    for (auto token : m_openDirectoryNotifyTokens)
     794        notify_cancel(token);
    773795#elif !PLATFORM(MACCATALYST)
    774796    removeCFNotificationObserver((__bridge CFStringRef)UIBacklightLevelChangedNotification);
  • trunk/Source/WebKit/UIProcess/WebProcessPool.h

    r293266 r293509  
    811811    std::unique_ptr<WebCore::PowerObserver> m_powerObserver;
    812812    std::unique_ptr<PAL::SystemSleepListener> m_systemSleepListener;
     813    Vector<int> m_openDirectoryNotifyTokens;
    813814#endif
    814815#if ENABLE(IPC_TESTING_API)
  • trunk/Source/WebKit/WebProcess/WebProcess.h

    r293329 r293509  
    3030#include "CacheModel.h"
    3131#include "IdentifierTypes.h"
    32 #include "SandboxExtension.h"
    3332#include "StorageAreaMapIdentifier.h"
    3433#include "TextCheckerState.h"
     
    354353#endif
    355354
     355#if PLATFORM(MAC)
     356    void openDirectoryCacheInvalidated(SandboxExtension::Handle&&);
     357#endif
     358
    356359    bool areAllPagesThrottleable() const;
    357360
  • trunk/Source/WebKit/WebProcess/WebProcess.messages.in

    r292624 r293509  
    202202    SetMediaAccessibilityPreferences(WebCore::CaptionUserPreferences::CaptionDisplayMode displayMode, Vector<String> languages)
    203203#endif
     204
     205#if PLATFORM(MAC)
     206    OpenDirectoryCacheInvalidated(WebKit::SandboxExtension::Handle handle)
     207#endif
    204208}
  • trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm

    r292632 r293509  
    12911291}
    12921292
     1293#if PLATFORM(MAC)
     1294void WebProcess::openDirectoryCacheInvalidated(SandboxExtension::Handle&& handle)
     1295{
     1296    AuxiliaryProcess::openDirectoryCacheInvalidated(WTFMove(handle));
     1297}
     1298#endif
     1299
    12931300} // namespace WebKit
    12941301
  • trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in

    r292971 r293509  
    14671467       (global-name "com.apple.system.opendirectoryd.membership"))
    14681468)
     1469(allow mach-lookup
     1470    (require-all
     1471        (extension "com.apple.webkit.extension.mach")
     1472        (global-name "com.apple.system.opendirectoryd.libinfo")))
    14691473#else
    14701474(allow file-read* file-write* (subpath "/private/var/db/mds/system")) ;; FIXME: This should be removed when <rdar://problem/9538414> is fixed.
Note: See TracChangeset for help on using the changeset viewer.