Changeset 234910 in webkit


Ignore:
Timestamp:
Aug 15, 2018 8:34:01 PM (6 years ago)
Author:
commit-queue@webkit.org
Message:

We should cache the compiled sandbox profile in a data vault
https://bugs.webkit.org/show_bug.cgi?id=184991

Patch by Ben Richards <benton_richards@apple.com> on 2018-08-15
Reviewed by Ryosuke Niwa.

Source/WebCore:

Added functionality to FileHandle so that it can lock a file while open.
Added a function to FileSystem to delete non empty directories.

  • platform/FileHandle.cpp:

(WebCore::FileHandle::FileHandle):
(WebCore::FileHandle::open):
(WebCore::FileHandle::close):

  • platform/FileHandle.h:
  • platform/FileSystem.h:
  • platform/cocoa/FileSystemCocoa.mm:

(WebCore::FileSystem::deleteNonEmptyDirectory):

Source/WebKit:

This patch changes a few things (note: data vaults and sandbox entitlements are only used in internal builds):
(1) Instead of compiling a sandbox every time a process is launched, processes now look for a cached sandbox

in a process specific data vault on macOS platforms. (ChildProcessMac.mm)

(2) If a valid cached sandbox is not found, a process will create the data vault (or ensure that it exists),

compile a sandbox, and cache it.

(3) In order to create process specific data vaults, each process now has their own <process name>-OSX-sandbox.entitlements

file which contains an entitlement with a process specific "storage class" which ensures that each process
can only ever access its own data vault. (See the article on confluence "Data Vaults and Restricted Files" for more info)

(4) The sandbox entitlements file for the Network and WebContent services are loaded dynamically

through Scripts/<process name>-process-entitlements.sh which is triggered in a new build phase for each service.
The Storage process sandbox entitlements are loaded directly in Configurations/StorageService.xcconfig.
The reason that the sandbox entitlements are applied dynamically is so that these sandbox entitlements
are only applied when WK_USE_RESTRICTED_ENTITLEMENTS is YES. This means that open source builds will still work.

  • Configurations/Network-OSX-sandbox.entitlements: Added.
  • Configurations/Storage-OSX-sandbox.entitlements: Added.
  • Configurations/StorageService.xcconfig:
  • Configurations/WebContent-OSX-sandbox.entitlements: Added.
  • Configurations/WebKit.xcconfig:
  • NetworkProcess/NetworkProcess.h:
  • PluginProcess/PluginProcess.h:
  • Scripts/process-network-sandbox-entitlements.sh: Added.
  • Scripts/process-webcontent-sandbox-entitlements.sh: Added.
  • Shared/ChildProcess.h:
  • Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h:

(WebKit::XPCServiceInitializer):

  • Shared/SandboxInitializationParameters.h:

(WebKit::SandboxInitializationParameters::setOverrideSandboxProfilePath):
(WebKit::SandboxInitializationParameters::overrideSandboxProfilePath const):
(WebKit::SandboxInitializationParameters::setSandboxProfile):
(WebKit::SandboxInitializationParameters::sandboxProfile const):
(): Deleted.

  • Shared/mac/ChildProcessMac.mm:

(WebKit::SandboxProfileDeleter::operator()):
(WebKit::SandboxParametersDeleter::operator()):
(WebKit::SandboxInfo::SandboxInfo):
(WebKit::fileContents):
(WebKit::processStorageClass):
(WebKit::setAndSerializeSandboxParameters):
(WebKit::sandboxDataVaultParentDirectory):
(WebKit::sandboxDirectory):
(WebKit::sandboxFilePath):
(WebKit::ensureSandboxCacheDirectory):
(WebKit::writeSandboxDataToCacheFile):
(WebKit::compileAndCacheSandboxProfile):
(WebKit::tryApplyCachedSandbox):
(WebKit::webKit2Bundle):
(WebKit::getSandboxProfileOrProfilePath):
(WebKit::compileAndApplySandboxSlowCase):
(WebKit::applySandbox):
(WebKit::initializeSandboxParameters):
(WebKit::ChildProcess::initializeSandbox):

  • Shared/mac/SandboxInitialiationParametersMac.mm:

(WebKit::SandboxInitializationParameters::SandboxInitializationParameters):

  • StorageProcess/StorageProcess.h:
  • WebKit.xcodeproj/project.pbxproj:
  • WebProcess/WebProcess.h:

Source/WTF:

Added trace points for sandbox initialization and exposed functions needed for sandbox caching

  • wtf/SystemTracing.h:
  • wtf/spi/darwin/SandboxSPI.h:

Tools:

Added trace points for sandbox initialization

  • Tracing/SystemTracePoints.plist:
Location:
trunk
Files:
5 added
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r234887 r234910  
     12018-08-15  Ben Richards  <benton_richards@apple.com>
     2
     3        We should cache the compiled sandbox profile in a data vault
     4        https://bugs.webkit.org/show_bug.cgi?id=184991
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Added trace points for sandbox initialization and exposed functions needed for sandbox caching
     9
     10        * wtf/SystemTracing.h:
     11        * wtf/spi/darwin/SandboxSPI.h:
     12
    1132018-08-15  Michael Catanzaro  <mcatanzaro@igalia.com>
    214
  • trunk/Source/WTF/wtf/SystemTracing.h

    r234810 r234910  
    9797    ProcessLaunchStart,
    9898    ProcessLaunchEnd,
     99    InitializeSandboxStart,
     100    InitializeSandboxEnd,
    99101};
    100102
  • trunk/Source/WTF/wtf/spi/darwin/SandboxSPI.h

    r234810 r234910  
    4343WTF_EXTERN_C_BEGIN
    4444
     45typedef struct {
     46    char* builtin;
     47    unsigned char* data;
     48    size_t size;
     49#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
     50    char* trace;
     51#endif
     52} *sandbox_profile_t;
     53
     54typedef struct {
     55    const char **params;
     56    size_t size;
     57    size_t available;
     58} *sandbox_params_t;
     59
    4560extern const char *const APP_SANDBOX_READ;
    4661extern const char *const APP_SANDBOX_READ_WRITE;
     
    5570int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf);
    5671int64_t sandbox_extension_consume(const char *extension_token);
     72sandbox_params_t sandbox_create_params(void);
     73int sandbox_set_param(sandbox_params_t, const char *key, const char *value);
     74void sandbox_free_params(sandbox_params_t);
     75sandbox_profile_t sandbox_compile_file(const char *path, sandbox_params_t, char **error);
     76sandbox_profile_t sandbox_compile_string(const char *data, sandbox_params_t, char **error);
     77void sandbox_free_profile(sandbox_profile_t);
     78int sandbox_apply(sandbox_profile_t);
    5779
    5880WTF_EXTERN_C_END
  • trunk/Source/WebCore/ChangeLog

    r234905 r234910  
     12018-08-15  Ben Richards  <benton_richards@apple.com>
     2
     3        We should cache the compiled sandbox profile in a data vault
     4        https://bugs.webkit.org/show_bug.cgi?id=184991
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Added functionality to FileHandle so that it can lock a file while open.
     9        Added a function to FileSystem to delete non empty directories.
     10
     11        * platform/FileHandle.cpp:
     12        (WebCore::FileHandle::FileHandle):
     13        (WebCore::FileHandle::open):
     14        (WebCore::FileHandle::close):
     15        * platform/FileHandle.h:
     16        * platform/FileSystem.h:
     17        * platform/cocoa/FileSystemCocoa.mm:
     18        (WebCore::FileSystem::deleteNonEmptyDirectory):
     19
    1202018-08-15  Ryosuke Niwa  <rniwa@webkit.org>
    221
  • trunk/Source/WebCore/platform/FileHandle.cpp

    r234810 r234910  
    3333
    3434FileHandle::FileHandle(const String& path, FileSystem::FileOpenMode mode)
    35     : m_path(path)
    36     , m_mode(mode)
     35    : m_path { path }
     36    , m_mode { mode }
    3737{
    3838}
    3939
    4040FileHandle::FileHandle(FileHandle&& other)
    41     : m_path(WTFMove(other.m_path))
    42     , m_mode(WTFMove(other.m_mode))
    43     , m_fileHandle(std::exchange(other.m_fileHandle, FileSystem::invalidPlatformFileHandle))
     41    : m_path { WTFMove(other.m_path) }
     42    , m_mode { WTFMove(other.m_mode) }
     43    , m_fileHandle { std::exchange(other.m_fileHandle, FileSystem::invalidPlatformFileHandle) }
     44{
     45}
     46
     47FileHandle::FileHandle(const String& path, FileSystem::FileOpenMode mode, OptionSet<FileSystem::FileLockMode> lockMode)
     48    : m_path { path }
     49    , m_mode { mode }
     50    , m_lockMode { lockMode }
     51    , m_shouldLock { true }
    4452{
    4553}
     
    7886{
    7987    if (!*this)
    80         m_fileHandle = FileSystem::openFile(m_path, m_mode);
     88        m_fileHandle = m_shouldLock ? FileSystem::openAndLockFile(m_path, m_mode, m_lockMode) :  FileSystem::openFile(m_path, m_mode);
    8189    return static_cast<bool>(*this);
    8290}
     
    116124void FileHandle::close()
    117125{
    118     FileSystem::closeFile(m_fileHandle);
     126    if (m_shouldLock && *this) {
     127        // FileSystem::unlockAndCloseFile requires the file handle to be valid while closeFile does not
     128        FileSystem::unlockAndCloseFile(m_fileHandle);
     129    } else
     130        FileSystem::closeFile(m_fileHandle);
    119131}
    120132
  • trunk/Source/WebCore/platform/FileHandle.h

    r234810 r234910  
    3939    FileHandle() = default;
    4040    FileHandle(const String& path, FileSystem::FileOpenMode);
     41    FileHandle(const String& path, FileSystem::FileOpenMode, OptionSet<FileSystem::FileLockMode>);
    4142    FileHandle(const FileHandle& other) = delete;
    4243    FileHandle(FileHandle&& other);
     
    6061    FileSystem::FileOpenMode m_mode { FileSystem::FileOpenMode::Read };
    6162    FileSystem::PlatformFileHandle m_fileHandle { FileSystem::invalidPlatformFileHandle };
     63    OptionSet<FileSystem::FileLockMode> m_lockMode;
     64    bool m_shouldLock { false };
    6265};
    6366
  • trunk/Source/WebCore/platform/FileSystem.h

    r234810 r234910  
    185185#if PLATFORM(COCOA)
    186186WEBCORE_EXPORT NSString *createTemporaryDirectory(NSString *directoryPrefix);
     187WEBCORE_EXPORT bool deleteNonEmptyDirectory(const String&);
    187188#endif
    188189
  • trunk/Source/WebCore/platform/cocoa/FileSystemCocoa.mm

    r234810 r234910  
    135135}
    136136
     137bool deleteNonEmptyDirectory(const String& path)
     138{
     139    return [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
     140}
     141
    137142} // namespace FileSystem
    138143} // namespace WebCore
  • trunk/Source/WebKit/ChangeLog

    r234908 r234910  
     12018-08-15  Ben Richards  <benton_richards@apple.com>
     2
     3        We should cache the compiled sandbox profile in a data vault
     4        https://bugs.webkit.org/show_bug.cgi?id=184991
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        This patch changes a few things (note: data vaults and sandbox entitlements are only used in internal builds):
     9        (1) Instead of compiling a sandbox every time a process is launched, processes now look for a cached sandbox
     10            in a process specific data vault on macOS platforms. (ChildProcessMac.mm)
     11        (2) If a valid cached sandbox is not found, a process will create the data vault (or ensure that it exists),
     12            compile a sandbox, and cache it.
     13        (3) In order to create process specific data vaults, each process now has their own <process name>-OSX-sandbox.entitlements
     14            file which contains an entitlement with a process specific "storage class" which ensures that each process
     15            can only ever access its own data vault. (See the article on confluence "Data Vaults and Restricted Files" for more info)
     16        (4) The sandbox entitlements file for the Network and WebContent services are loaded dynamically
     17            through Scripts/<process name>-process-entitlements.sh which is triggered in a new build phase for each service.
     18            The Storage process sandbox entitlements are loaded directly in Configurations/StorageService.xcconfig.
     19            The reason that the sandbox entitlements are applied dynamically is so that these sandbox entitlements
     20            are only applied when WK_USE_RESTRICTED_ENTITLEMENTS is YES. This means that open source builds will still work.
     21
     22        * Configurations/Network-OSX-sandbox.entitlements: Added.
     23        * Configurations/Storage-OSX-sandbox.entitlements: Added.
     24        * Configurations/StorageService.xcconfig:
     25        * Configurations/WebContent-OSX-sandbox.entitlements: Added.
     26        * Configurations/WebKit.xcconfig:
     27        * NetworkProcess/NetworkProcess.h:
     28        * PluginProcess/PluginProcess.h:
     29        * Scripts/process-network-sandbox-entitlements.sh: Added.
     30        * Scripts/process-webcontent-sandbox-entitlements.sh: Added.
     31        * Shared/ChildProcess.h:
     32        * Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h:
     33        (WebKit::XPCServiceInitializer):
     34        * Shared/SandboxInitializationParameters.h:
     35        (WebKit::SandboxInitializationParameters::setOverrideSandboxProfilePath):
     36        (WebKit::SandboxInitializationParameters::overrideSandboxProfilePath const):
     37        (WebKit::SandboxInitializationParameters::setSandboxProfile):
     38        (WebKit::SandboxInitializationParameters::sandboxProfile const):
     39        (): Deleted.
     40        * Shared/mac/ChildProcessMac.mm:
     41        (WebKit::SandboxProfileDeleter::operator()):
     42        (WebKit::SandboxParametersDeleter::operator()):
     43        (WebKit::SandboxInfo::SandboxInfo):
     44        (WebKit::fileContents):
     45        (WebKit::processStorageClass):
     46        (WebKit::setAndSerializeSandboxParameters):
     47        (WebKit::sandboxDataVaultParentDirectory):
     48        (WebKit::sandboxDirectory):
     49        (WebKit::sandboxFilePath):
     50        (WebKit::ensureSandboxCacheDirectory):
     51        (WebKit::writeSandboxDataToCacheFile):
     52        (WebKit::compileAndCacheSandboxProfile):
     53        (WebKit::tryApplyCachedSandbox):
     54        (WebKit::webKit2Bundle):
     55        (WebKit::getSandboxProfileOrProfilePath):
     56        (WebKit::compileAndApplySandboxSlowCase):
     57        (WebKit::applySandbox):
     58        (WebKit::initializeSandboxParameters):
     59        (WebKit::ChildProcess::initializeSandbox):
     60        * Shared/mac/SandboxInitialiationParametersMac.mm:
     61        (WebKit::SandboxInitializationParameters::SandboxInitializationParameters):
     62        * StorageProcess/StorageProcess.h:
     63        * WebKit.xcodeproj/project.pbxproj:
     64        * WebProcess/WebProcess.h:
     65
    1662018-08-15  Ross Kirsling  <ross.kirsling@sony.com>
    267
  • trunk/Source/WebKit/Configurations/StorageService.xcconfig

    r234810 r234910  
    2626WK_XPC_SERVICE_IOS_ENTITLEMENTS_BASE = Databases-iOS;
    2727
     28WK_STORAGE_ENTITLEMENTS_RESTRICTED_NO = ;
     29WK_STORAGE_ENTITLEMENTS_RESTRICTED_YES = Configurations/Storage-OSX-sandbox.entitlements;
     30
     31CODE_SIGN_ENTITLEMENTS_COCOA_TOUCH_NO = $(WK_STORAGE_ENTITLEMENTS_RESTRICTED_$(WK_USE_RESTRICTED_ENTITLEMENTS));
    2832OTHER_CODE_SIGN_FLAGS = $(WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS);
    2933
  • trunk/Source/WebKit/Configurations/WebKit.xcconfig

    r234810 r234910  
    8383WK_MOBILE_GESTALT_LDFLAGS_cocoatouch = -lMobileGestalt;
    8484
     85WK_LIBSANDBOX_LDFLAGS = $(WK_LIBSANDBOX_LDFLAGS_$(WK_PLATFORM_NAME));
     86WK_LIBSANDBOX_LDFLAGS_macosx = -lsandbox;
     87
    8588WK_OPENGL_LDFLAGS = $(WK_OPENGL_LDFLAGS_$(WK_PLATFORM_NAME));
    8689WK_OPENGL_LDFLAGS_iphoneos = -framework OpenGLES;
     
    113116WK_URL_FORMATTING_LDFLAGS_YES = -framework URLFormatting;
    114117
    115 FRAMEWORK_AND_LIBRARY_LDFLAGS = -lobjc -framework CFNetwork -framework CoreAudio -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework Foundation -framework ImageIO -framework IOKit -framework WebKitLegacy -lnetwork $(WK_ACCESSIBILITY_LDFLAGS) $(WK_APPKIT_LDFLAGS) $(WK_ASSERTION_SERVICES_LDFLAGS) $(WK_CARBON_LDFLAGS) $(WK_CORE_PDF_LDFLAGS) $(WK_CORE_PREDICTION_LDFLAGS) $(WK_CORE_SERVICES_LDFLAGS) $(WK_GRAPHICS_SERVICES_LDFLAGS) $(WK_IOSURFACE_LDFLAGS) $(WK_LIBWEBRTC_LDFLAGS) $(WK_MOBILE_CORE_SERVICES_LDFLAGS) $(WK_MOBILE_GESTALT_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SAFE_BROWSING_LDFLAGS) $(WK_UIKIT_LDFLAGS) $(WK_URL_FORMATTING_LDFLAGS);
     118FRAMEWORK_AND_LIBRARY_LDFLAGS = -lobjc -framework CFNetwork -framework CoreAudio -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework Foundation -framework ImageIO -framework IOKit -framework WebKitLegacy -lnetwork $(WK_ACCESSIBILITY_LDFLAGS) $(WK_APPKIT_LDFLAGS) $(WK_ASSERTION_SERVICES_LDFLAGS) $(WK_CARBON_LDFLAGS) $(WK_CORE_PDF_LDFLAGS) $(WK_CORE_PREDICTION_LDFLAGS) $(WK_CORE_SERVICES_LDFLAGS) $(WK_GRAPHICS_SERVICES_LDFLAGS) $(WK_IOSURFACE_LDFLAGS) $(WK_LIBSANDBOX_LDFLAGS) $(WK_LIBWEBRTC_LDFLAGS) $(WK_MOBILE_CORE_SERVICES_LDFLAGS) $(WK_MOBILE_GESTALT_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SAFE_BROWSING_LDFLAGS) $(WK_UIKIT_LDFLAGS) $(WK_URL_FORMATTING_LDFLAGS);
    116119
    117120// Prevent C++ standard library basic_stringstream, operator new, delete and their related exception types from being exported as weak symbols.
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.h

    r234896 r234910  
    8181public:
    8282    static NetworkProcess& singleton();
     83    static constexpr ProcessType processType = ProcessType::Network;
    8384
    8485    template <typename T>
  • trunk/Source/WebKit/PluginProcess/PluginProcess.h

    r234810 r234910  
    5050public:
    5151    static PluginProcess& singleton();
     52    static constexpr ProcessType processType = ProcessType::Plugin;
    5253
    5354    void removeWebProcessConnection(WebProcessConnection*);
  • trunk/Source/WebKit/Shared/ChildProcess.h

    r234810 r234910  
    4040
    4141class SandboxInitializationParameters;
    42 
    43 struct ChildProcessInitializationParameters {
    44     String uiProcessName;
    45     String clientIdentifier;
    46     std::optional<WebCore::ProcessIdentifier> processIdentifier;
    47     IPC::Connection::Identifier connectionIdentifier;
    48     HashMap<String, String> extraInitializationData;
    49 #if PLATFORM(COCOA)
    50     OSObjectPtr<xpc_object_t> priorityBoostMessage;
    51 #endif
    52 };
     42struct ChildProcessInitializationParameters;
    5343
    5444class ChildProcess : protected IPC::Connection::Client, public IPC::MessageSender {
     
    5646
    5747public:
     48    enum class ProcessType : uint8_t {
     49        WebContent,
     50        Network,
     51        Storage,
     52        Plugin
     53    };
     54
    5855    void initialize(const ChildProcessInitializationParameters&);
    5956
     
    151148};
    152149
     150struct ChildProcessInitializationParameters {
     151    String uiProcessName;
     152    String clientIdentifier;
     153    std::optional<WebCore::ProcessIdentifier> processIdentifier;
     154    IPC::Connection::Identifier connectionIdentifier;
     155    HashMap<String, String> extraInitializationData;
     156    ChildProcess::ProcessType processType;
     157#if PLATFORM(COCOA)
     158    OSObjectPtr<xpc_object_t> priorityBoostMessage;
     159#endif
     160};
     161
    153162} // namespace WebKit
    154163
  • trunk/Source/WebKit/Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h

    r234810 r234910  
    113113#endif
    114114
     115    parameters.processType = XPCServiceType::processType;
     116
    115117    XPCServiceType::singleton().initialize(parameters);
    116118}
  • trunk/Source/WebKit/Shared/SandboxInitializationParameters.h

    r234810 r234910  
    5555    const char* value(size_t index) const;
    5656
    57     enum ProfileSelectionMode {
     57    enum class ProfileSelectionMode : uint8_t {
    5858        UseDefaultSandboxProfilePath,
    5959        UseOverrideSandboxProfilePath,
     
    6565    void setOverrideSandboxProfilePath(const String& path)
    6666    {
    67         m_profileSelectionMode = UseOverrideSandboxProfilePath;
     67        m_profileSelectionMode = ProfileSelectionMode::UseOverrideSandboxProfilePath;
    6868        m_overrideSandboxProfilePathOrSandboxProfile = path;
    6969    }
     
    7171    const String& overrideSandboxProfilePath() const
    7272    {
    73         ASSERT(m_profileSelectionMode == UseOverrideSandboxProfilePath);
     73        ASSERT(m_profileSelectionMode == ProfileSelectionMode::UseOverrideSandboxProfilePath);
    7474        return m_overrideSandboxProfilePathOrSandboxProfile;
    7575    }
     
    7777    void setSandboxProfile(const String& profile)
    7878    {
    79         m_profileSelectionMode = UseSandboxProfile;
     79        m_profileSelectionMode = ProfileSelectionMode::UseSandboxProfile;
    8080        m_overrideSandboxProfilePathOrSandboxProfile = profile;
    8181    }
     
    8383    const String& sandboxProfile() const
    8484    {
    85         ASSERT(m_profileSelectionMode == UseSandboxProfile);
     85        ASSERT(m_profileSelectionMode == ProfileSelectionMode::UseSandboxProfile);
    8686        return m_overrideSandboxProfilePathOrSandboxProfile;
    8787    }
  • trunk/Source/WebKit/Shared/mac/ChildProcessMac.mm

    r234810 r234910  
    3232#import "QuarantineSPI.h"
    3333#import "SandboxInitializationParameters.h"
     34#import "SandboxUtilities.h"
    3435#import "WKFoundation.h"
    3536#import "XPCServiceEntryPoint.h"
     37#import <WebCore/FileHandle.h>
    3638#import <WebCore/FileSystem.h>
    3739#import <WebCore/SystemVersion.h>
     40#import <mach-o/dyld.h>
    3841#import <mach/mach.h>
    3942#import <mach/task.h>
     43#import <pal/crypto/CryptoDigest.h>
    4044#import <pwd.h>
    4145#import <stdlib.h>
     46#import <sys/sysctl.h>
    4247#import <sysexits.h>
     48#import <wtf/DataLog.h>
     49#import <wtf/RandomNumber.h>
    4350#import <wtf/Scope.h>
     51#import <wtf/SystemTracing.h>
     52#import <wtf/WallTime.h>
    4453#import <wtf/spi/darwin/SandboxSPI.h>
     54#import <wtf/text/Base64.h>
     55#import <wtf/text/StringBuilder.h>
    4556
    4657#if USE(APPLE_INTERNAL_SDK)
    47 #include <HIServices/ProcessesPriv.h>
     58#import <HIServices/ProcessesPriv.h>
     59#import <rootless.h>
     60#endif
     61
     62#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     63#define USE_CACHE_COMPILED_SANDBOX 1
     64#else
     65#define USE_CACHE_COMPILED_SANDBOX 0
    4866#endif
    4967
     
    5775
    5876namespace WebKit {
     77
     78#if USE(CACHE_COMPILED_SANDBOX)
     79using SandboxProfile = typename std::remove_pointer<sandbox_profile_t>::type;
     80struct SandboxProfileDeleter {
     81    void operator()(SandboxProfile* ptr)
     82    {
     83        sandbox_free_profile(ptr);
     84    }
     85};
     86using SandboxProfilePtr = std::unique_ptr<SandboxProfile, SandboxProfileDeleter>;
     87
     88using SandboxParameters = typename std::remove_pointer<sandbox_params_t>::type;
     89struct SandboxParametersDeleter {
     90    void operator()(SandboxParameters* ptr)
     91    {
     92        sandbox_free_params(ptr);
     93    }
     94};
     95using SandboxParametersPtr = std::unique_ptr<SandboxParameters, SandboxParametersDeleter>;
     96
     97struct CachedSandboxHeader {
     98    uint32_t versionNumber;
     99    uint32_t libsandboxVersion;
     100    uint32_t headerSize;
     101    uint32_t builtinSize; // If a builtin doesn't exist, this is UINT_MAX.
     102    uint32_t dataSize;
     103};
     104// The file is layed out on disk like:
     105// byte 0
     106// CachedSandboxHeader <- sizeof(CachedSandboxHeader) bytes
     107// SandboxHeader <- CachedSandboxHeader::headerSize bytes
     108// [SandboxBuiltin] optional. Present if CachedSandboxHeader::builtinSize is not UINT_MAX. If present, builtinSize bytes (not including null termination).
     109// SandboxData <- CachedSandboxHeader::dataSize bytes
     110// byte N
     111
     112struct SandboxInfo {
     113    SandboxInfo(const String& parentDirectoryPath, const String& directoryPath, const String& filePath, const SandboxParametersPtr& sandboxParameters, const CString& header, const ChildProcess::ProcessType& processType, const SandboxInitializationParameters& initializationParameters, const String& profileOrProfilePath, bool isProfilePath)
     114        : parentDirectoryPath { parentDirectoryPath }
     115        , directoryPath { directoryPath }
     116        , filePath { filePath }
     117        , sandboxParameters { sandboxParameters }
     118        , header { header }
     119        , processType { processType }
     120        , initializationParameters { initializationParameters }
     121        , profileOrProfilePath { profileOrProfilePath }
     122        , isProfilePath { isProfilePath }
     123    {
     124    }
     125
     126    const String& parentDirectoryPath;
     127    const String& directoryPath;
     128    const String& filePath;
     129    const SandboxParametersPtr& sandboxParameters;
     130    const CString& header;
     131    const ChildProcess::ProcessType& processType;
     132    const SandboxInitializationParameters& initializationParameters;
     133    const String& profileOrProfilePath;
     134    const bool isProfilePath;
     135};
     136
     137constexpr uint32_t CachedSandboxVersionNumber = 0;
     138#endif // USE(CACHE_COMPILED_SANDBOX)
    59139
    60140static void initializeTimerCoalescingPolicy()
     
    113193}
    114194
    115 void ChildProcess::initializeSandbox(const ChildProcessInitializationParameters& parameters, SandboxInitializationParameters& sandboxParameters)
     195#if USE(CACHE_COMPILED_SANDBOX)
     196static std::optional<Vector<char>> fileContents(const String& path, bool shouldLock = false, OptionSet<FileSystem::FileLockMode> lockMode = FileSystem::FileLockMode::Exclusive)
     197{
     198    FileHandle file = shouldLock ? FileHandle(path, FileSystem::FileOpenMode::Read, lockMode) : FileHandle(path, FileSystem::FileOpenMode::Read);
     199    file.open();
     200    if (!file)
     201        return std::nullopt;
     202
     203    char chunk[4096];
     204    constexpr size_t chunkSize = WTF_ARRAY_LENGTH(chunk);
     205    size_t contentSize = 0;
     206    Vector<char> contents;
     207    contents.reserveInitialCapacity(chunkSize);
     208    while (size_t bytesRead = file.read(chunk, chunkSize)) {
     209        contents.append(chunk, bytesRead);
     210        contentSize += bytesRead;
     211    }
     212    contents.resize(contentSize);
     213
     214    return contents;
     215}
     216
     217#if USE(APPLE_INTERNAL_SDK)
     218// These strings must match the last segment of the "com.apple.rootless.storage.<this part must match>" entry in each
     219// process's restricted entitlements file (ex. Configurations/Networking-OSX-restricted.entitlements).
     220constexpr const char* processStorageClass(ChildProcess::ProcessType type)
     221{
     222    switch (type) {
     223    case ChildProcess::ProcessType::WebContent:
     224        return "WebKitWebContentSandbox";
     225    case ChildProcess::ProcessType::Network:
     226        return "WebKitNetworkingSandbox";
     227    case ChildProcess::ProcessType::Storage:
     228        return "WebKitStorageSandbox";
     229    case ChildProcess::ProcessType::Plugin:
     230        return "WebKitPluginSandbox";
     231    }
     232}
     233#endif // USE(APPLE_INTERNAL_SDK)
     234
     235static std::optional<CString> setAndSerializeSandboxParameters(const SandboxInitializationParameters& initializationParameters, const SandboxParametersPtr& sandboxParameters, const String& profileOrProfilePath, bool isProfilePath)
     236{
     237    StringBuilder builder;
     238    for (size_t i = 0; i < initializationParameters.count(); ++i) {
     239        const char* name = initializationParameters.name(i);
     240        const char* value = initializationParameters.value(i);
     241        if (sandbox_set_param(sandboxParameters.get(), name, value)) {
     242            WTFLogAlways("%s: Could not set sandbox parameter: %s\n", getprogname(), strerror(errno));
     243            CRASH();
     244        }
     245        builder.append(name, strlen(name));
     246        builder.append(':');
     247        builder.append(value, strlen(value));
     248        builder.append(':');
     249    }
     250    if (isProfilePath) {
     251        auto contents = fileContents(profileOrProfilePath);
     252        if (!contents)
     253            return std::nullopt;
     254        builder.append(contents->data(), contents->size());
     255    } else
     256        builder.append(profileOrProfilePath);
     257    return builder.toString().ascii();
     258}
     259
     260static String sandboxDataVaultParentDirectory()
     261{
     262    char temp[PATH_MAX];
     263    size_t length = confstr(_CS_DARWIN_USER_CACHE_DIR, temp, sizeof(temp));
     264    if (!length) {
     265        WTFLogAlways("%s: Could not retrieve user cache directory path: %s\n", getprogname(), strerror(errno));
     266        exit(EX_NOPERM);
     267    }
     268    RELEASE_ASSERT(length <= sizeof(temp));
     269    char resolvedPath[PATH_MAX];
     270    if (!realpath(temp, resolvedPath)) {
     271        WTFLogAlways("%s: Could not canonicalize user cache directory path: %s\n", getprogname(), strerror(errno));
     272        exit(EX_NOPERM);
     273    }
     274    return resolvedPath;
     275}
     276
     277static String sandboxDirectory(ChildProcess::ProcessType processType, const String& parentDirectory)
     278{
     279    StringBuilder directory;
     280    directory.append(parentDirectory);
     281    switch (processType) {
     282    case ChildProcess::ProcessType::WebContent:
     283        directory.append("/com.apple.WebKit.WebContent.Sandbox");
     284        break;
     285    case ChildProcess::ProcessType::Network:
     286        directory.append("/com.apple.WebKit.Networking.Sandbox");
     287        break;
     288    case ChildProcess::ProcessType::Storage:
     289        directory.append("/com.apple.WebKit.Storage.Sandbox");
     290        break;
     291    case ChildProcess::ProcessType::Plugin:
     292        directory.append("/com.apple.WebKit.Plugin.Sandbox");
     293        break;
     294    }
     295
     296#if !USE(APPLE_INTERNAL_SDK)
     297    // Add .OpenSource suffix so that open source builds don't try to access a data vault used by system Safari.
     298    directory.append(".OpenSource");
     299#endif
     300
     301    return directory.toString();
     302}
     303
     304static String sandboxFilePath(const String& directoryPath, const CString& header)
     305{
     306    StringBuilder sandboxFile;
     307    sandboxFile.append(directoryPath);
     308    sandboxFile.append("/CompiledSandbox+");
     309
     310    // Make the filename semi-unique based on the contents of the header.
     311    auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);
     312    crypto->addBytes(header.data(), header.length());
     313    Vector<uint8_t> hash = crypto->computeHash();
     314    String readableHash = WTF::base64URLEncode(hash.data(), hash.size());
     315
     316    sandboxFile.append(readableHash);
     317    return sandboxFile.toString();
     318}
     319
     320static bool ensureSandboxCacheDirectory(const SandboxInfo& info)
     321{
     322    if (!FileSystem::fileIsDirectory(info.parentDirectoryPath, FileSystem::ShouldFollowSymbolicLinks::Yes)) {
     323        FileSystem::makeAllDirectories(info.parentDirectoryPath);
     324        if (!FileSystem::fileIsDirectory(info.parentDirectoryPath, FileSystem::ShouldFollowSymbolicLinks::Yes)) {
     325            WTFLogAlways("%s: Could not create sandbox directory\n", getprogname());
     326            return false;
     327        }
     328    }
     329
     330#if USE(APPLE_INTERNAL_SDK)
     331    const char* storageClass = processStorageClass(info.processType);
     332    CString directoryPath = FileSystem::fileSystemRepresentation(info.directoryPath);
     333    if (directoryPath.isNull())
     334        return false;
     335
     336    auto makeDataVault = [&] {
     337        do {
     338            if (!rootless_mkdir_datavault(directoryPath.data(), 0700, storageClass))
     339                return true;
     340        } while (errno == EAGAIN);
     341        return false;
     342    };
     343
     344    if (makeDataVault())
     345        return true;
     346
     347    if (errno == EEXIST) {
     348        // The directory already exists. First we'll check if it is a data vault. If it is then
     349        // we are the ones who created it and we can continue. If it is not a datavault then we'll just
     350        // delete it and try to make a new one.
     351        if (!rootless_check_datavault_flag(directoryPath.data(), storageClass))
     352            return true;
     353
     354        bool isDirectory = FileSystem::fileIsDirectory(info.directoryPath, FileSystem::ShouldFollowSymbolicLinks::No);
     355        if (isDirectory) {
     356            if (!FileSystem::deleteNonEmptyDirectory(info.directoryPath))
     357                return false;
     358        } else {
     359            if (!FileSystem::deleteFile(info.directoryPath))
     360                return false;
     361        }
     362
     363        if (!makeDataVault())
     364            return false;
     365    } else {
     366        WTFLogAlways("%s: Sandbox directory couldn't be created: ", getprogname(), strerror(errno));
     367        return false;
     368    }
     369#else
     370    bool hasSandboxDirectory = FileSystem::fileIsDirectory(info.directoryPath, FileSystem::ShouldFollowSymbolicLinks::Yes);
     371    if (!hasSandboxDirectory) {
     372        if (FileSystem::makeAllDirectories(info.directoryPath)) {
     373            ASSERT(FileSystem::fileIsDirectory(info.directoryPath, FileSystem::ShouldFollowSymbolicLinks::Yes));
     374            hasSandboxDirectory = true;
     375        } else {
     376            // We may have raced with someone else making it. That's ok.
     377            hasSandboxDirectory = FileSystem::fileIsDirectory(info.directoryPath, FileSystem::ShouldFollowSymbolicLinks::Yes);
     378        }
     379    }
     380
     381    if (!hasSandboxDirectory) {
     382        // Bailing because we don't have a sandbox directory.
     383        return false;
     384    }
     385#endif // USE(APPLE_INTERNAL_SDK)
     386
     387    return true;
     388}
     389
     390static bool writeSandboxDataToCacheFile(const SandboxInfo& info, const Vector<char>& cacheFile)
     391{
     392    FileHandle file { info.filePath, FileSystem::FileOpenMode::Write, FileSystem::FileLockMode::Exclusive };
     393    return file.write(cacheFile.data(), cacheFile.size()) == safeCast<int>(cacheFile.size());
     394}
     395
     396static SandboxProfilePtr compileAndCacheSandboxProfile(const SandboxInfo& info)
     397{
     398    if (!ensureSandboxCacheDirectory(info))
     399        return nullptr;
     400
     401    char* error = nullptr;
     402    CString profileOrProfilePath = info.isProfilePath ? FileSystem::fileSystemRepresentation(info.profileOrProfilePath) : info.profileOrProfilePath.utf8();
     403    if (profileOrProfilePath.isNull())
     404        return nullptr;
     405    SandboxProfilePtr sandboxProfile { info.isProfilePath ? sandbox_compile_file(profileOrProfilePath.data(), info.sandboxParameters.get(), &error) : sandbox_compile_string(profileOrProfilePath.data(), info.sandboxParameters.get(), &error) };
     406    if (!sandboxProfile) {
     407        WTFLogAlways("%s: Could not compile WebContent sandbox: %s\n", getprogname(), error);
     408        return nullptr;
     409    }
     410
     411    const bool haveBuiltin = sandboxProfile->builtin;
     412    int32_t libsandboxVersion = NSVersionOfRunTimeLibrary("sandbox");
     413    RELEASE_ASSERT(libsandboxVersion > 0);
     414    CachedSandboxHeader cachedHeader {
     415        CachedSandboxVersionNumber,
     416        static_cast<uint32_t>(libsandboxVersion),
     417        safeCast<uint32_t>(info.header.length()),
     418        haveBuiltin ? safeCast<uint32_t>(strlen(sandboxProfile->builtin)) : std::numeric_limits<uint32_t>::max(),
     419        safeCast<uint32_t>(sandboxProfile->size)
     420    };
     421    const size_t expectedFileSize = sizeof(cachedHeader) + cachedHeader.headerSize + (haveBuiltin ? cachedHeader.builtinSize : 0) + cachedHeader.dataSize;
     422
     423    Vector<char> cacheFile;
     424    cacheFile.reserveInitialCapacity(expectedFileSize);
     425    cacheFile.append(bitwise_cast<uint8_t*>(&cachedHeader), sizeof(CachedSandboxHeader));
     426    cacheFile.append(info.header.data(), info.header.length());
     427    if (haveBuiltin)
     428        cacheFile.append(sandboxProfile->builtin, cachedHeader.builtinSize);
     429    cacheFile.append(sandboxProfile->data, cachedHeader.dataSize);
     430
     431    if (!writeSandboxDataToCacheFile(info, cacheFile))
     432        WTFLogAlways("%s: Unable to cache compiled sandbox\n", getprogname());
     433
     434    return sandboxProfile;
     435}
     436
     437static bool tryApplyCachedSandbox(const SandboxInfo& info)
     438{
     439#if USE(APPLE_INTERNAL_SDK)
     440    CString directoryPath = FileSystem::fileSystemRepresentation(info.directoryPath);
     441    if (directoryPath.isNull())
     442        return false;
     443    if (rootless_check_datavault_flag(directoryPath.data(), processStorageClass(info.processType)))
     444        return false;
     445#endif
     446
     447    auto contents = fileContents(info.filePath, true, FileSystem::FileLockMode::Shared);
     448    if (!contents || contents->isEmpty())
     449        return false;
     450    Vector<char> cachedSandboxContents = WTFMove(*contents);
     451    if (sizeof(CachedSandboxHeader) > cachedSandboxContents.size())
     452        return false;
     453
     454    // This data may be corrupted if the sandbox file was cached on a different platform with different endianness
     455    CachedSandboxHeader cachedSandboxHeader;
     456    memcpy(&cachedSandboxHeader, cachedSandboxContents.data(), sizeof(CachedSandboxHeader));
     457    int32_t libsandboxVersion = NSVersionOfRunTimeLibrary("sandbox");
     458    RELEASE_ASSERT(libsandboxVersion > 0);
     459    if (static_cast<uint32_t>(libsandboxVersion) != cachedSandboxHeader.libsandboxVersion)
     460        return false;
     461    if (cachedSandboxHeader.versionNumber != CachedSandboxVersionNumber)
     462        return false;
     463    const bool haveBuiltin = cachedSandboxHeader.builtinSize != std::numeric_limits<uint32_t>::max();
     464
     465    // These values are computed based on the disk layout specified below the definition of the CachedSandboxHeader struct
     466    // and must be changed if the layout changes.
     467    const char* sandboxHeaderPtr = bitwise_cast<char *>(cachedSandboxContents.data()) + sizeof(CachedSandboxHeader);
     468    const char* sandboxBuiltinPtr = sandboxHeaderPtr + cachedSandboxHeader.headerSize;
     469    unsigned char* sandboxDataPtr = bitwise_cast<unsigned char*>(haveBuiltin ? sandboxBuiltinPtr + cachedSandboxHeader.builtinSize : sandboxBuiltinPtr);
     470
     471    size_t expectedFileSize = sizeof(CachedSandboxHeader) + cachedSandboxHeader.headerSize + cachedSandboxHeader.dataSize;
     472    if (haveBuiltin)
     473        expectedFileSize += cachedSandboxHeader.builtinSize;
     474    if (cachedSandboxContents.size() != expectedFileSize)
     475        return false;
     476    if (cachedSandboxHeader.headerSize != info.header.length())
     477        return false;
     478    if (memcmp(sandboxHeaderPtr, info.header.data(), info.header.length()))
     479        return false;
     480
     481    SandboxProfile profile { };
     482    CString builtin;
     483    profile.builtin = nullptr;
     484    profile.size = cachedSandboxHeader.dataSize;
     485    if (haveBuiltin) {
     486        builtin = CString::newUninitialized(cachedSandboxHeader.builtinSize, profile.builtin);
     487        if (builtin.isNull())
     488            return false;
     489        memcpy(profile.builtin, sandboxBuiltinPtr, cachedSandboxHeader.builtinSize);
     490    }
     491    ASSERT(static_cast<void *>(sandboxDataPtr + profile.size) <= static_cast<void *>(cachedSandboxContents.data() + cachedSandboxContents.size()));
     492    profile.data = sandboxDataPtr;
     493
     494    if (sandbox_apply(&profile)) {
     495        WTFLogAlways("%s: Could not apply cached sandbox: %s\n", getprogname(), strerror(errno));
     496        return false;
     497    }
     498
     499    return true;
     500}
     501#endif // USE(CACHE_COMPILED_SANDBOX)
     502
     503static inline const NSBundle *webKit2Bundle()
    116504{
    117505#if WK_API_ENABLED
    118     NSBundle *webKit2Bundle = [NSBundle bundleForClass:NSClassFromString(@"WKWebView")];
     506    const static NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"WKWebView")];
    119507#else
    120     NSBundle *webKit2Bundle = [NSBundle bundleForClass:NSClassFromString(@"WKView")];
    121 #endif
    122     String defaultProfilePath = [webKit2Bundle pathForResource:[[NSBundle mainBundle] bundleIdentifier] ofType:@"sb"];
    123 
     508    const static NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"WKView")];
     509#endif
     510
     511    return bundle;
     512}
     513
     514static void getSandboxProfileOrProfilePath(const SandboxInitializationParameters& parameters, String& profileOrProfilePath, bool& isProfilePath)
     515{
     516    switch (parameters.mode()) {
     517    case SandboxInitializationParameters::ProfileSelectionMode::UseDefaultSandboxProfilePath:
     518        profileOrProfilePath = [webKit2Bundle() pathForResource:[[NSBundle mainBundle] bundleIdentifier] ofType:@"sb"];
     519        isProfilePath = true;
     520        return;
     521    case SandboxInitializationParameters::ProfileSelectionMode::UseOverrideSandboxProfilePath:
     522        profileOrProfilePath = parameters.overrideSandboxProfilePath();
     523        isProfilePath = true;
     524        return;
     525    case SandboxInitializationParameters::ProfileSelectionMode::UseSandboxProfile:
     526        profileOrProfilePath = parameters.sandboxProfile();
     527        isProfilePath = false;
     528        return;
     529    }
     530}
     531
     532static bool compileAndApplySandboxSlowCase(const String& profileOrProfilePath, bool isProfilePath, const SandboxInitializationParameters& parameters)
     533{
     534    char* errorBuf;
     535    CString temp = isProfilePath ? FileSystem::fileSystemRepresentation(profileOrProfilePath) : profileOrProfilePath.utf8();
     536    uint64_t flags = isProfilePath ? SANDBOX_NAMED_EXTERNAL : 0;
     537#pragma clang diagnostic push
     538#pragma clang diagnostic ignored "-Wdeprecated-declarations"
     539    if (sandbox_init_with_parameters(temp.data(), flags, parameters.namedParameterArray(), &errorBuf)) {
     540#pragma clang diagnostic pop
     541        WTFLogAlways("%s: Could not initialize sandbox profile [%s], error '%s'\n", getprogname(), temp.data(), errorBuf);
     542        for (size_t i = 0, count = parameters.count(); i != count; ++i)
     543            WTFLogAlways("%s=%s\n", parameters.name(i), parameters.value(i));
     544        return false;
     545    }
     546    return true;
     547}
     548
     549static bool applySandbox(const ChildProcessInitializationParameters& parameters, const SandboxInitializationParameters& sandboxInitializationParameters, const String& dataVaultParentDirectory)
     550{
     551    String profileOrProfilePath;
     552    bool isProfilePath;
     553    getSandboxProfileOrProfilePath(sandboxInitializationParameters, profileOrProfilePath, isProfilePath);
     554    if (profileOrProfilePath.isEmpty()) {
     555        WTFLogAlways("%s: Profile path is invalid\n", getprogname());
     556        CRASH();
     557    }
     558
     559#if USE(CACHE_COMPILED_SANDBOX)
     560    // The plugin process's DARWIN_USER_TEMP_DIR and DARWIN_USER_CACHE_DIR sandbox parameters are randomized so
     561    // so the compiled sandbox should not be cached because it won't be reused.
     562    if (parameters.processType == ChildProcess::ProcessType::Plugin)
     563        return compileAndApplySandboxSlowCase(profileOrProfilePath, isProfilePath, sandboxInitializationParameters);
     564
     565    SandboxParametersPtr sandboxParameters { sandbox_create_params() };
     566    if (!sandboxParameters) {
     567        WTFLogAlways("%s: Could not create sandbox parameters\n", getprogname());
     568        CRASH();
     569    }
     570    auto header = setAndSerializeSandboxParameters(sandboxInitializationParameters, sandboxParameters, profileOrProfilePath, isProfilePath);
     571    if (!header) {
     572        WTFLogAlways("%s: Sandbox parameters are invalid\n", getprogname());
     573        CRASH();
     574    }
     575
     576    String directoryPath { sandboxDirectory(parameters.processType, dataVaultParentDirectory) };
     577    String filePath = sandboxFilePath(directoryPath, *header);
     578    SandboxInfo info {
     579        dataVaultParentDirectory,
     580        directoryPath,
     581        filePath,
     582        sandboxParameters,
     583        *header,
     584        parameters.processType,
     585        sandboxInitializationParameters,
     586        profileOrProfilePath,
     587        isProfilePath
     588    };
     589
     590    if (tryApplyCachedSandbox(info))
     591        return true;
     592
     593    SandboxProfilePtr sandboxProfile = compileAndCacheSandboxProfile(info);
     594    if (!sandboxProfile)
     595        return compileAndApplySandboxSlowCase(profileOrProfilePath, isProfilePath, sandboxInitializationParameters);
     596
     597    if (sandbox_apply(sandboxProfile.get())) {
     598        WTFLogAlways("%s: Could not apply compiled sandbox: %s\n", getprogname(), strerror(errno));
     599        CRASH();
     600    }
     601
     602    return true;
     603#else
     604    UNUSED_PARAM(parameters);
     605    UNUSED_PARAM(dataVaultParentDirectory);
     606    return compileAndApplySandboxSlowCase(profileOrProfilePath, isProfilePath, sandboxInitializationParameters);
     607#endif // USE(CACHE_COMPILED_SANDBOX)
     608}
     609
     610static void initializeSandboxParameters(const ChildProcessInitializationParameters& parameters, SandboxInitializationParameters& sandboxParameters)
     611{
     612    // Verify user directory suffix.
    124613    if (sandboxParameters.userDirectorySuffix().isNull()) {
    125614        auto userDirectorySuffix = parameters.extraInitializationData.find("user-directory-suffix");
     
    153642    setenv("TMPDIR", temporaryDirectory, 1);
    154643
    155     sandboxParameters.addPathParameter("WEBKIT2_FRAMEWORK_DIR", [[webKit2Bundle bundlePath] stringByDeletingLastPathComponent]);
     644    sandboxParameters.addPathParameter("WEBKIT2_FRAMEWORK_DIR", [[webKit2Bundle() bundlePath] stringByDeletingLastPathComponent]);
    156645    sandboxParameters.addConfDirectoryParameter("DARWIN_USER_TEMP_DIR", _CS_DARWIN_USER_TEMP_DIR);
    157646    sandboxParameters.addConfDirectoryParameter("DARWIN_USER_CACHE_DIR", _CS_DARWIN_USER_CACHE_DIR);
     
    167656
    168657    sandboxParameters.addPathParameter("HOME_DIR", pwd.pw_dir);
    169 
    170658    String path = String::fromUTF8(pwd.pw_dir);
    171659    path.append("/Library");
    172 
    173660    sandboxParameters.addPathParameter("HOME_LIBRARY_DIR", FileSystem::fileSystemRepresentation(path).data());
    174 
    175661    path.append("/Preferences");
    176 
    177662    sandboxParameters.addPathParameter("HOME_LIBRARY_PREFERENCES_DIR", FileSystem::fileSystemRepresentation(path).data());
    178 
    179     switch (sandboxParameters.mode()) {
    180     case SandboxInitializationParameters::UseDefaultSandboxProfilePath:
    181     case SandboxInitializationParameters::UseOverrideSandboxProfilePath: {
    182         String sandboxProfilePath = sandboxParameters.mode() == SandboxInitializationParameters::UseDefaultSandboxProfilePath ? defaultProfilePath : sandboxParameters.overrideSandboxProfilePath();
    183         if (!sandboxProfilePath.isEmpty()) {
    184             CString profilePath = FileSystem::fileSystemRepresentation(sandboxProfilePath);
    185             char* errorBuf;
    186 #pragma clang diagnostic push
    187 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    188             if (sandbox_init_with_parameters(profilePath.data(), SANDBOX_NAMED_EXTERNAL, sandboxParameters.namedParameterArray(), &errorBuf)) {
    189 #pragma clang diagnostic pop
    190                 WTFLogAlways("%s: Couldn't initialize sandbox profile [%s], error '%s'\n", getprogname(), profilePath.data(), errorBuf);
    191                 for (size_t i = 0, count = sandboxParameters.count(); i != count; ++i)
    192                     WTFLogAlways("%s=%s\n", sandboxParameters.name(i), sandboxParameters.value(i));
    193                 exit(EX_NOPERM);
    194             }
    195         }
    196 
    197         break;
    198     }
    199     case SandboxInitializationParameters::UseSandboxProfile: {
    200         char* errorBuf;
    201 #pragma clang diagnostic push
    202 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    203         if (sandbox_init_with_parameters(sandboxParameters.sandboxProfile().utf8().data(), 0, sandboxParameters.namedParameterArray(), &errorBuf)) {
    204 #pragma clang diagnostic pop
    205             WTFLogAlways("%s: Couldn't initialize sandbox profile, error '%s'\n", getprogname(), errorBuf);
    206             for (size_t i = 0, count = sandboxParameters.count(); i != count; ++i)
    207                 WTFLogAlways("%s=%s\n", sandboxParameters.name(i), sandboxParameters.value(i));
    208             exit(EX_NOPERM);
    209         }
    210 
    211         break;
    212     }
     663}
     664
     665void ChildProcess::initializeSandbox(const ChildProcessInitializationParameters& parameters, SandboxInitializationParameters& sandboxParameters)
     666{
     667    TraceScope traceScope(InitializeSandboxStart, InitializeSandboxEnd);
     668
     669#if USE(CACHE_COMPILED_SANDBOX)
     670    // This must be called before initializeSandboxParameters so that the path does not include the user directory suffix.
     671    // We don't want the user directory suffix because we want all processes of the same type to use the same cache directory.
     672    String dataVaultParentDirectory { sandboxDataVaultParentDirectory() };
     673#else
     674    String dataVaultParentDirectory;
     675#endif
     676
     677    initializeSandboxParameters(parameters, sandboxParameters);
     678
     679    if (!applySandbox(parameters, sandboxParameters, dataVaultParentDirectory)) {
     680        WTFLogAlways("%s: Unable to apply sandbox\n", getprogname());
     681        CRASH();
    213682    }
    214683
  • trunk/Source/WebKit/Shared/mac/SandboxInitialiationParametersMac.mm

    r234810 r234910  
    3030
    3131SandboxInitializationParameters::SandboxInitializationParameters()
    32     : m_profileSelectionMode(UseDefaultSandboxProfilePath)
     32    : m_profileSelectionMode(ProfileSelectionMode::UseDefaultSandboxProfilePath)
    3333{
    3434}
  • trunk/Source/WebKit/StorageProcess/StorageProcess.h

    r234810 r234910  
    7272public:
    7373    static StorageProcess& singleton();
     74    static constexpr ProcessType processType = ProcessType::Storage;
     75
    7476    ~StorageProcess();
    7577
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r234810 r234910  
    34503450                4151E5C31FBB90A900E47E2D /* FormDataReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormDataReference.h; sourceTree = "<group>"; };
    34513451                4157E4AF20E2EC9800A6C0D7 /* com.google.o1dbrowserplugin.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.google.o1dbrowserplugin.sb; sourceTree = "<group>"; };
     3452                4188C154211377700012ABCD /* process-network-sandbox-entitlements.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "process-network-sandbox-entitlements.sh"; sourceTree = "<group>"; };
     3453                4188C156211377E80012ABCD /* process-webcontent-sandbox-entitlements.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "process-webcontent-sandbox-entitlements.sh"; sourceTree = "<group>"; };
     3454                4188C157211378520012ABCD /* Storage-OSX-sandbox.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Storage-OSX-sandbox.entitlements"; sourceTree = "<group>"; };
     3455                4188C158211378520012ABCD /* WebContent-OSX-sandbox.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "WebContent-OSX-sandbox.entitlements"; sourceTree = "<group>"; };
    34523456                41897ECB1F415D5C0016FA42 /* WebCacheStorageConnection.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebCacheStorageConnection.messages.in; sourceTree = "<group>"; };
    34533457                41897ECC1F415D5C0016FA42 /* WebCacheStorageProvider.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebCacheStorageProvider.cpp; sourceTree = "<group>"; };
     
    34703474                41B7ED71206965900087D853 /* NetworkMDNSRegister.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = NetworkMDNSRegister.messages.in; path = NetworkProcess/webrtc/NetworkMDNSRegister.messages.in; sourceTree = "<group>"; };
    34713475                41C858191F510DEE0065E085 /* CacheStorageEngineCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CacheStorageEngineCache.cpp; sourceTree = "<group>"; };
     3476                41D0FC7D20E43A5100076AE8 /* Network-OSX-sandbox.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Network-OSX-sandbox.entitlements"; sourceTree = "<group>"; };
    34723477                41D129D91F3D101400D15E47 /* WebCacheStorageProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebCacheStorageProvider.h; sourceTree = "<group>"; };
    34733478                41DC45941E3D6E1E00B11F51 /* NetworkRTCProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkRTCProvider.h; path = NetworkProcess/webrtc/NetworkRTCProvider.h; sourceTree = "<group>"; };
     
    51965201                                37119A7D20CCB64E002C6DC9 /* Network-iOS-minimalsimulator.entitlements */,
    51975202                                7C0BB9A918DCDF5A0006C086 /* Network-iOS.entitlements */,
     5203                                41D0FC7D20E43A5100076AE8 /* Network-OSX-sandbox.entitlements */,
    51985204                                BC8283AB16B4BEAD00A278FE /* NetworkService.xcconfig */,
    51995205                                A1EDD2DB1884B96400BBFE98 /* PluginProcessShim.xcconfig */,
     
    52045210                                A1EDD2DC1884B9B500BBFE98 /* SecItemShim.xcconfig */,
    52055211                                5183B3931379F85C00E8754E /* Shim.xcconfig */,
     5212                                4188C157211378520012ABCD /* Storage-OSX-sandbox.entitlements */,
    52065213                                51A60B29180CCD9000F3BF50 /* StorageService.xcconfig */,
    52075214                                1A4F976E100E7B6600637A18 /* Version.xcconfig */,
     
    52095216                                7C0BB9A818DCDE890006C086 /* WebContent-iOS.entitlements */,
    52105217                                37B418EB1C9624F20031E63B /* WebContent-or-Plugin-OSX-restricted.entitlements */,
     5218                                4188C158211378520012ABCD /* WebContent-OSX-sandbox.entitlements */,
    52115219                                7AF66E1120C07CB6007828EA /* WebContent-OSX.entitlements */,
    52125220                                372EBB4A2017E76000085064 /* WebContentService.Development.xcconfig */,
     
    86608668                                0FC08570187CE0A900780D86 /* model.py */,
    86618669                                0FC08571187CE0A900780D86 /* parser.py */,
     8670                                4188C154211377700012ABCD /* process-network-sandbox-entitlements.sh */,
    86628671                                7ACFAAD820B88D4F00C53203 /* process-webcontent-or-plugin-entitlements.sh */,
     8672                                4188C156211377E80012ABCD /* process-webcontent-sandbox-entitlements.sh */,
    86638673                        );
    86648674                        path = Scripts;
     
    1015910169                        buildConfigurationList = BC8283BD16B4BF7700A278FE /* Build configuration list for PBXNativeTarget "Networking" */;
    1016010170                        buildPhases = (
     10171                                41D0FC7F20E43B0B00076AE8 /* Remove stale entitlements file */,
    1016110172                                BC8283AD16B4BF7700A278FE /* Sources */,
    1016210173                                BC8283AE16B4BF7700A278FE /* Frameworks */,
    1016310174                                BC8283AF16B4BF7700A278FE /* Resources */,
     10175                                41D0FC8020E43B4500076AE8 /* Unlock keychain */,
     10176                                41D0FC8120E43B7000076AE8 /* Process Network entitlements */,
    1016410177                        );
    1016510178                        buildRules = (
     
    1042010433                        runOnlyForDeploymentPostprocessing = 0;
    1042110434                        shellPath = /bin/sh;
    10422                         shellScript = "set -e\n\nRELATIVE_SOURCE_PATH=\"usr/local/include/WebKitAdditions/WebKit/AdditionalResources\"\nSOURCE_PATH=\"$BUILT_PRODUCTS_DIR/$RELATIVE_SOURCE_PATH\"\n\nif [[ ! -d \"$SOURCE_PATH\" ]]; then\n    SOURCE_PATH=\"$SDK_DIR/$RELATIVE_SOURCE_PATH\"\nfi\n\nif [[ -d \"$SOURCE_PATH\" ]]; then\n    ditto $SOURCE_PATH \"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH\"\nfi";
     10435                        shellScript = "set -e\n\nRELATIVE_SOURCE_PATH=\"usr/local/include/WebKitAdditions/WebKit/AdditionalResources\"\nSOURCE_PATH=\"$BUILT_PRODUCTS_DIR/$RELATIVE_SOURCE_PATH\"\n\nif [[ ! -d \"$SOURCE_PATH\" ]]; then\n    SOURCE_PATH=\"$SDK_DIR/$RELATIVE_SOURCE_PATH\"\nfi\n\nif [[ -d \"$SOURCE_PATH\" ]]; then\n    ditto $SOURCE_PATH \"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH\"\nfi\n";
    1042310436                };
    1042410437                3713F0231429063D0036387F /* Check For Inappropriate Objective-C Class Names */ = {
     
    1045910472                        runOnlyForDeploymentPostprocessing = 0;
    1046010473                        shellPath = /bin/sh;
    10461                         shellScript = "if [[ \"${WK_MANUAL_SANDBOXING_ENABLED}\" != \"YES\" || \"${WK_PLATFORM_NAME}\" == \"macosx\" ]]; then\n    exit\nfi\n\nif [[ \"${ACTION}\" == \"build\" || \"${ACTION}\" == \"install\" ]]; then\n    for ((i = 0; i < ${SCRIPT_INPUT_FILE_COUNT}; ++i)); do\n        eval ENTITLEMENTS=\\${SCRIPT_INPUT_FILE_${i}}\n        ENTITLEMENTS_BASE=${ENTITLEMENTS##*/}\n        ENTITLEMENTS_BASE=${ENTITLEMENTS_BASE%.entitlements}\n        plutil -remove seatbelt-profiles -o \"${BUILT_PRODUCTS_DIR}/DerivedSources/WebKit2/${ENTITLEMENTS_BASE}-no-sandbox.entitlements\" \"${ENTITLEMENTS}\"\n    done\nfi";
     10474                        shellScript = "if [[ \"${WK_MANUAL_SANDBOXING_ENABLED}\" != \"YES\" || \"${WK_PLATFORM_NAME}\" == \"macosx\" ]]; then\n    exit\nfi\n\nif [[ \"${ACTION}\" == \"build\" || \"${ACTION}\" == \"install\" ]]; then\n    for ((i = 0; i < ${SCRIPT_INPUT_FILE_COUNT}; ++i)); do\n        eval ENTITLEMENTS=\\${SCRIPT_INPUT_FILE_${i}}\n        ENTITLEMENTS_BASE=${ENTITLEMENTS##*/}\n        ENTITLEMENTS_BASE=${ENTITLEMENTS_BASE%.entitlements}\n        plutil -remove seatbelt-profiles -o \"${BUILT_PRODUCTS_DIR}/DerivedSources/WebKit2/${ENTITLEMENTS_BASE}-no-sandbox.entitlements\" \"${ENTITLEMENTS}\"\n    done\nfi\n";
    1046210475                };
    1046310476                375A248817E5048E00C9A086 /* Postprocess WKBase.h */ = {
     
    1049310506                        shellScript = "if [[ \"${WK_MANUAL_SANDBOXING_ENABLED}\" != \"YES\" || \"${WK_PLATFORM_NAME}\" == \"macosx\" || \"${WK_PLATFORM_NAME}\" == \"iosmac\" ]]; then\n    exit\nfi\n\nif [[ \"${ACTION}\" == \"build\" || \"${ACTION}\" == \"install\" ]]; then\n    for ((i = 0; i < ${SCRIPT_INPUT_FILE_COUNT}; ++i)); do\n        eval SANDBOX_PROFILE=\\${SCRIPT_INPUT_FILE_${i}}\n        ditto \"${SANDBOX_PROFILE}\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/${SANDBOX_PROFILE##*/}\"\n    done\nfi\n";
    1049410507                };
     10508                41D0FC7F20E43B0B00076AE8 /* Remove stale entitlements file */ = {
     10509                        isa = PBXShellScriptBuildPhase;
     10510                        buildActionMask = 2147483647;
     10511                        files = (
     10512                        );
     10513                        inputPaths = (
     10514                        );
     10515                        name = "Remove stale entitlements file";
     10516                        outputPaths = (
     10517                        );
     10518                        runOnlyForDeploymentPostprocessing = 0;
     10519                        shellPath = /bin/sh;
     10520                        shellScript = "# We autogenerate this file, so don't want to retain an old copy during builds.\nrm -f ${TEMP_FILE_DIR}/${FULL_PRODUCT_NAME}.xcent\n";
     10521                };
     10522                41D0FC8020E43B4500076AE8 /* Unlock keychain */ = {
     10523                        isa = PBXShellScriptBuildPhase;
     10524                        buildActionMask = 2147483647;
     10525                        files = (
     10526                        );
     10527                        inputPaths = (
     10528                        );
     10529                        name = "Unlock keychain";
     10530                        outputPaths = (
     10531                        );
     10532                        runOnlyForDeploymentPostprocessing = 0;
     10533                        shellPath = /bin/sh;
     10534                        shellScript = "UNLOCK_SCRIPT_PATH=\"${SRCROOT}/../../../Internal/Tools/Scripts/unlock-safari-engineering-keychain-if-needed\"\n\n[[ -x \"${UNLOCK_SCRIPT_PATH}\" ]] && exec \"${UNLOCK_SCRIPT_PATH}\"\n\nexit 0\n";
     10535                };
     10536                41D0FC8120E43B7000076AE8 /* Process Network entitlements */ = {
     10537                        isa = PBXShellScriptBuildPhase;
     10538                        buildActionMask = 2147483647;
     10539                        files = (
     10540                        );
     10541                        inputPaths = (
     10542                                "$(TEMP_FILE_DIR)/$(FULL_PRODUCT_NAME).xcent",
     10543                        );
     10544                        name = "Process Network entitlements";
     10545                        outputPaths = (
     10546                        );
     10547                        runOnlyForDeploymentPostprocessing = 0;
     10548                        shellPath = /bin/sh;
     10549                        shellScript = "Scripts/process-network-sandbox-entitlements.sh\n";
     10550                };
    1049510551                5DF408C5131DD46700130071 /* Check For Weak VTables and Externals */ = {
    1049610552                        isa = PBXShellScriptBuildPhase;
     
    1057110627                        files = (
    1057210628                        );
    10573                         inputFileListPaths = (
    10574                         );
    1057510629                        inputPaths = (
    1057610630                                "$(TEMP_FILE_DIR)/$(FULL_PRODUCT_NAME).xcent",
    1057710631                        );
    1057810632                        name = "Process Plugin entitlements";
    10579                         outputFileListPaths = (
    10580                         );
    1058110633                        outputPaths = (
    1058210634                        );
     
    1059010642                        files = (
    1059110643                        );
    10592                         inputFileListPaths = (
    10593                         );
    1059410644                        inputPaths = (
    1059510645                                "$(TEMP_FILE_DIR)/$(FULL_PRODUCT_NAME).xcent",
    1059610646                        );
    1059710647                        name = "Process Plugin entitlements";
    10598                         outputFileListPaths = (
    10599                         );
    1060010648                        outputPaths = (
    1060110649                        );
     
    1061710665                        runOnlyForDeploymentPostprocessing = 0;
    1061810666                        shellPath = /bin/sh;
    10619                         shellScript = "Scripts/process-webcontent-or-plugin-entitlements.sh\n";
     10667                        shellScript = "Scripts/process-webcontent-or-plugin-entitlements.sh\nScripts/process-webcontent-sandbox-entitlements.sh\n";
    1062010668                };
    1062110669                7AFCBD5520B8917D00F55C9C /* Process WebContent entitlements */ = {
     
    1063210680                        runOnlyForDeploymentPostprocessing = 0;
    1063310681                        shellPath = /bin/sh;
    10634                         shellScript = "Scripts/process-webcontent-or-plugin-entitlements.sh\n";
     10682                        shellScript = "Scripts/process-webcontent-or-plugin-entitlements.sh\nScripts/process-webcontent-sandbox-entitlements.sh\n";
    1063510683                };
    1063610684                99CA3862207286DB00BAD578 /* Copy WebDriver Atoms to Framework Private Headers */ = {
  • trunk/Source/WebKit/WebProcess/WebProcess.h

    r234810 r234910  
    110110public:
    111111    static WebProcess& singleton();
     112    static constexpr ProcessType processType = ProcessType::WebContent;
    112113
    113114    template <typename T>
  • trunk/Tools/ChangeLog

    r234897 r234910  
     12018-08-15  Ben Richards  <benton_richards@apple.com>
     2
     3        We should cache the compiled sandbox profile in a data vault
     4        https://bugs.webkit.org/show_bug.cgi?id=184991
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Added trace points for sandbox initialization
     9
     10        * Tracing/SystemTracePoints.plist:
     11
    1122018-08-15  Ryan Haddad  <ryanhaddad@apple.com>
    213
  • trunk/Tools/Tracing/SystemTracePoints.plist

    r234810 r234910  
    301301                 <string>14004</string>
    302302             </dict>
     303             <dict>
     304                 <key>Name</key>
     305                 <string>Initialize Sandbox</string>
     306                 <key>Type</key>
     307                 <string>Interval</string>
     308                 <key>Component</key>
     309                 <string>47</string>
     310                 <key>CodeBegin</key>
     311                 <string>14005</string>
     312                 <key>CodeEnd</key>
     313                 <string>14006</string>
     314             </dict>
    303315         </array>
    304316     </dict>
Note: See TracChangeset for help on using the changeset viewer.