WebKit Bugzilla
Attachment 347101 Details for
Bug 188568
: [GTK][WPE] Implement subprocess sandboxing
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188568-20180814150759.patch (text/plain), 47.33 KB, created by
Patrick Griffis
on 2018-08-14 12:08:00 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Patrick Griffis
Created:
2018-08-14 12:08:00 PDT
Size:
47.33 KB
patch
obsolete
>Subversion Revision: 234728 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 2b746477d97a49a3c977bce6f005354a6706ba0e..2be97be45e57de958d42d8318f1e8a3b8f62a460 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,12 @@ >+2018-08-14 Patrick Griffis <pgriffis@igalia.com> >+ >+ [GTK][WPE] Implement subprocess sandboxing >+ https://bugs.webkit.org/show_bug.cgi?id=188568 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * PlatformGTK.cmake: >+ > 2018-08-09 Charlie Turner <cturner@igalia.com> > > Fix copyright headers on new ISO parsing class >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 35cd77c926063e6d0b282aac3e9d20cec0885acd..8fcdb62b24e595a10164e9aecadc30031d317023 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,73 @@ >+2018-08-14 Patrick Griffis <pgriffis@igalia.com> >+ >+ [GTK][WPE] Implement subprocess sandboxing >+ https://bugs.webkit.org/show_bug.cgi?id=188568 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This implements sandboxing of subprocesses such as WebKitWebProcess. >+ >+ It does so via the bubblewrap project which uses namespaces on Linux. >+ This introduces two new dependencies: the bwrap executable and the >+ libseccomp library. >+ >+ Currently the sandbox is fairly open as to not introduce many >+ regressions in functionality with the hope that this can be tightened >+ up over time as WebKit improves and as external projects like >+ DBus, Pipewire, etc become more sandboxed and available. >+ >+ The sandbox is opt-in at runtime as it is a behavior change. >+ See webkit_web_context_set_sandbox_enabled() and the >+ WEBKIT_SANDBOX_ENABLED env var for developers. >+ >+ * Shared/SandboxExtension.h: >+ * Shared/glib/SandboxExtensionGLib.cpp: Added. >+ (WebKit::stringByResolvingSymlinksInPath): >+ (WebKit::resolvePathForSandboxExtension): >+ (WebKit::resolveAndCreateReadWriteDirectoryForSandboxExtension): >+ * SourcesGTK.txt: >+ * SourcesWPE.txt: >+ * UIProcess/API/glib/WebKitWebContext.cpp: >+ (webkit_web_context_set_sandbox_enabled): >+ (webkit_web_context_get_sandbox_enabled): >+ * UIProcess/API/gtk/WebKitWebContext.h: >+ * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt: >+ * UIProcess/Launcher/ProcessLauncher.h: >+ * UIProcess/Launcher/glib/ProcessLauncherGLib.cpp: >+ (WebKit::dbusAddressToPath): >+ (WebKit::bindIfExists): >+ (WebKit::bindX11): >+ (WebKit::bindDBusSession): >+ (WebKit::bindDBusSystem): >+ (WebKit::bindDconf): >+ (WebKit::bindWayland): >+ (WebKit::bindPulse): >+ (WebKit::bindFonts): >+ (WebKit::bindGtkData): >+ (WebKit::bindPathVar): >+ (WebKit::bindGstreamerData): >+ (WebKit::bindOpenGL): >+ (WebKit::bindV4l): >+ (WebKit::bindA11y): >+ (WebKit::memfd_create): >+ (WebKit::setupSeccomp): >+ (WebKit::getBwrapArgs): >+ (WebKit::isInsideFlatpak): >+ (WebKit::getFlatpakArgs): >+ (WebKit::ProcessLauncher::launchProcess): >+ * UIProcess/Network/NetworkProcessProxy.cpp: >+ (WebKit::NetworkProcessProxy::getLaunchOptions): >+ * UIProcess/Storage/StorageProcessProxy.cpp: >+ (WebKit::StorageProcessProxy::getLaunchOptions): >+ * UIProcess/WebProcessPool.h: >+ * UIProcess/WebProcessProxy.cpp: >+ (WebKit::WebProcessProxy::getLaunchOptions): >+ * UIProcess/WebsiteData/WebsiteDataStore.cpp: >+ (WebKit::WebsiteDataStore::resolveDirectoriesIfNecessary): >+ * UIProcess/WebsiteData/WebsiteDataStore.h: >+ (WebKit::WebsiteDataStore::resolvedNetworkCacheDirectory const): >+ (WebKit::WebsiteDataStore::resolvedLocalStorageDirectory const): >+ > 2018-08-09 Per Arne Vollan <pvollan@apple.com> > > DisplayRefreshMonitorMac should hold a weak pointer to WebPage. >diff --git a/Source/WebCore/PlatformGTK.cmake b/Source/WebCore/PlatformGTK.cmake >index e14ed4adcec092cd8830745f432c737c1e40dfd8..4eb05cd06db3daa6684c8a8f32de341f6d1e0e85 100644 >--- a/Source/WebCore/PlatformGTK.cmake >+++ b/Source/WebCore/PlatformGTK.cmake >@@ -106,6 +106,7 @@ list(APPEND WebCore_LIBRARIES > ${GLIB_GMODULE_LIBRARIES} > ${GLIB_GOBJECT_LIBRARIES} > ${GLIB_LIBRARIES} >+ ${LIBSECCOMP_LIBRARIES} > ${LIBSECRET_LIBRARIES} > ${LIBSOUP_LIBRARIES} > ${LIBTASN1_LIBRARIES} >@@ -125,6 +126,7 @@ list(APPEND WebCore_SYSTEM_INCLUDE_DIRECTORIES > ${ENCHANT_INCLUDE_DIRS} > ${GIO_UNIX_INCLUDE_DIRS} > ${GLIB_INCLUDE_DIRS} >+ ${LIBSECCOMP_INCLUDE_DIRS} > ${LIBSECRET_INCLUDE_DIRS} > ${LIBSOUP_INCLUDE_DIRS} > ${LIBTASN1_INCLUDE_DIRS} >diff --git a/Source/WebKit/Shared/SandboxExtension.h b/Source/WebKit/Shared/SandboxExtension.h >index cb53aade63e39f32e2bf62678de7c3cb942df382..4e1d594f34dbc408dd107f80692f46e5472455b6 100644 >--- a/Source/WebKit/Shared/SandboxExtension.h >+++ b/Source/WebKit/Shared/SandboxExtension.h >@@ -140,6 +140,9 @@ inline bool SandboxExtension::revoke() { return true; } > inline bool SandboxExtension::consume() { return true; } > inline bool SandboxExtension::consumePermanently() { return true; } > inline bool SandboxExtension::consumePermanently(const Handle&) { return true; } >+#endif >+ >+#if !ENABLE(SANDBOX_EXTENSIONS) && !PLATFORM(GTK) && !PLATFORM(WPE) > inline String stringByResolvingSymlinksInPath(const String& path) { return path; } > inline String resolvePathForSandboxExtension(const String& path) { return path; } > inline String resolveAndCreateReadWriteDirectoryForSandboxExtension(const String& path) { return path; } >diff --git a/Source/WebKit/Shared/glib/SandboxExtensionGLib.cpp b/Source/WebKit/Shared/glib/SandboxExtensionGLib.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..6d69aa54dde8862fb86f280d81769dbd1fb68638 >--- /dev/null >+++ b/Source/WebKit/Shared/glib/SandboxExtensionGLib.cpp >@@ -0,0 +1,59 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "SandboxExtension.h" >+ >+#include <glib.h> >+ >+namespace WebKit { >+ >+// We don't actually care about resolving symlinks because >+// the `bwrap` tool always handles this for us >+String stringByResolvingSymlinksInPath(const String& path) >+{ >+ return path; >+} >+ >+String resolvePathForSandboxExtension(const String& path) >+{ >+ return path; >+} >+ >+String resolveAndCreateReadWriteDirectoryForSandboxExtension(const String& path) >+{ >+ const char* cpath = path.utf8().data(); >+ if (!cpath[0]) >+ return path; >+ >+ if (g_mkdir_with_parents(cpath, 0700) == -1) { >+ g_warning("Could not create directory \"%s\": %s", cpath, g_strerror(errno)); >+ return { }; >+ } >+ >+ return path; >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt >index 38b600e2b83e8864b5b4eee8ffe3ccc6f5209ae9..445a8785ddf57a8ab951e548590354105b09ce00 100644 >--- a/Source/WebKit/SourcesGTK.txt >+++ b/Source/WebKit/SourcesGTK.txt >@@ -83,6 +83,7 @@ Shared/Plugins/unix/PluginSearchPath.cpp > > Shared/cairo/ShareableBitmapCairo.cpp @no-unify > >+Shared/glib/SandboxExtensionGLib.cpp > Shared/glib/ProcessExecutablePathGLib.cpp @no-unify > Shared/glib/WebContextMenuItemGlib.cpp > >diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt >index c71ae5c11cdce8665721245273d64b0f6c22ac5c..511f1474955eedc51c8838bdb8c813a4a8f53706 100644 >--- a/Source/WebKit/SourcesWPE.txt >+++ b/Source/WebKit/SourcesWPE.txt >@@ -78,6 +78,7 @@ Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp > > Shared/cairo/ShareableBitmapCairo.cpp > >+Shared/glib/SandboxExtensionGLib.cpp > Shared/glib/ProcessExecutablePathGLib.cpp > Shared/glib/WebContextMenuItemGlib.cpp > >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp >index 7b7f037e0a2e0a3a0042ecb7bc591e831c6594ea..bc7064c63eb2753bb8fdf7b417fcd00577bcbaad 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp >+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp >@@ -1147,6 +1147,41 @@ void webkit_web_context_register_uri_scheme(WebKitWebContext* context, const cha > context->priv->processPool->registerSchemeForCustomProtocol(String::fromUTF8(scheme)); > } > >+/** >+ * webkit_web_context_set_sandbox_enabled: >+ * @context: a #WebKitWebContext >+ * @enabled: if %TRUE enable sandboxing >+ * >+ * Set whether WebKit subprocesses will be sandboxed limiting access to the system. >+ * >+ * This cannot be changed after processes are launched and is only implemented on Linux. >+ * >+ * Since: 2.22 >+ */ >+void webkit_web_context_set_sandbox_enabled(WebKitWebContext* context, gboolean enabled) >+{ >+ g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); >+ >+ context->priv->processPool->setSandboxEnabled(enabled); >+} >+ >+/** >+ * webkit_web_context_get_sandbox_enabled: >+ * @context: a #WebKitWebContext >+ * >+ * Get whether sandboxing is currently enabled. >+ * >+ * Returns: %TRUE If sandboxing is enabled, or %FALSE otherwise. >+ * >+ * Since: 2.22 >+ */ >+gboolean webkit_web_context_get_sandbox_enabled(WebKitWebContext* context) >+{ >+ g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE); >+ >+ return context->priv->processPool->sandboxEnabled(); >+} >+ > /** > * webkit_web_context_get_spell_checking_enabled: > * @context: a #WebKitWebContext >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h >index 3149a329c27821ac4448f5dc24d0b0395229d4ad..bbdeac93316df2102b6e8c5cbb8e7b78f57f8939 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h >@@ -247,6 +247,13 @@ webkit_web_context_register_uri_scheme (WebKitWebContext > gpointer user_data, > GDestroyNotify user_data_destroy_func); > >+WEBKIT_API void >+webkit_web_context_set_sandbox_enabled (WebKitWebContext *context, >+ gboolean enabled); >+ >+WEBKIT_API gboolean >+webkit_web_context_get_sandbox_enabled (WebKitWebContext *context); >+ > WEBKIT_API gboolean > webkit_web_context_get_spell_checking_enabled (WebKitWebContext *context); > >diff --git a/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt b/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >index 3eb829860146b82caef2099af5581c135188d3b2..9df425df68e900aaa87c0c678ea7b55976ba84e5 100644 >--- a/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >+++ b/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >@@ -51,6 +51,8 @@ webkit_web_context_get_security_manager > webkit_web_context_set_additional_plugins_directory > webkit_web_context_get_plugins > webkit_web_context_get_plugins_finish >+webkit_web_context_get_sandbox_enabled >+webkit_web_context_set_sandbox_enabled > webkit_web_context_get_spell_checking_enabled > webkit_web_context_set_spell_checking_enabled > webkit_web_context_get_spell_checking_languages >diff --git a/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h b/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h >index 5c4bb3b9e11641d987811da6679465b6e31840a5..e6f55d3ac212daeca1478f8687bc84dc1d823603 100644 >--- a/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h >+++ b/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h >@@ -68,6 +68,11 @@ public: > bool shouldMakeProcessLaunchFailForTesting { false }; > CString customWebContentServiceBundleIdentifier; > >+#if PLATFORM(GTK) || PLATFORM(WPE) >+ Vector<String> extraSandboxPaths; >+ bool sandboxEnabled { false }; >+#endif >+ > #if ENABLE(DEVELOPER_MODE) && (PLATFORM(GTK) || PLATFORM(WPE)) > String processCmdPrefix; > #endif >diff --git a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp >index 52916971526da9935e3ff8ba653e733a2aa25a9c..13fa3502732ecad303894c1a5bae83aa788dd149 100644 >--- a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp >+++ b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp >@@ -44,6 +44,10 @@ > #include <wpe/wpe.h> > #endif > >+#if ENABLE(BUBBLEWRAP_SANDBOX) >+#include <seccomp.h> >+#endif >+ > namespace WebKit { > using namespace WebCore; > >@@ -53,6 +57,563 @@ static void childSetupFunction(gpointer userData) > close(socket); > } > >+#if ENABLE(BUBBLEWRAP_SANDBOX) >+ >+// From flatpak-run.c (LGPLv2.1+) >+static char* dbusAddressToPath(const char* address, bool abstract = false) >+{ >+ const char* path, *path_end; >+ >+ if (!address) >+ return nullptr; >+ >+ if (!g_str_has_prefix(address, "unix:")) >+ return nullptr; >+ >+ path = strstr(address, abstract ? "abstract=" : "path="); >+ if (!path) >+ return nullptr; >+ >+ path += strlen(abstract ? "abstract=" : "path="); >+ path_end = path; >+ while (*path_end && *path_end != ',') >+ path_end++; >+ >+ return g_strndup(path, path_end - path); >+} >+ >+enum class BindFlags { >+ ReadOnly, >+ ReadWrite, >+ Device, >+}; >+ >+static void bindIfExists(Vector<CString>& args, const char* path, BindFlags bindFlags = BindFlags::ReadOnly) >+{ >+ if (!path) >+ return; >+ >+ const char* type; >+ if (bindFlags == BindFlags::Device) >+ type = "--dev-bind-try"; >+ else if (bindFlags == BindFlags::ReadOnly) >+ type = "--ro-bind-try"; >+ else >+ type = "--bind-try"; >+ args.appendVector(Vector<CString>({ type, path, path })); >+} >+ >+static void bindX11(Vector<CString>& args) >+{ >+ const char* display = g_getenv("DISPLAY"); >+ if (!display || display[0] != ':' || !g_ascii_isdigit(const_cast<char*>(display)[1])) >+ display = ":0"; >+ GUniquePtr<char> x11File(g_strdup_printf("/tmp/.X11-unix/X%s", display + 1)); >+ bindIfExists(args, x11File.get(), BindFlags::ReadWrite); >+ >+ const char* xauth = g_getenv("XAUTHORITY"); >+ if (!xauth) { >+ const char* homeDir = g_get_home_dir(); >+ GUniquePtr<char> xauthFile(g_build_filename(homeDir, ".Xauthority", nullptr)); >+ bindIfExists(args, xauthFile.get()); >+ } else >+ bindIfExists(args, xauth); >+} >+ >+static void bindDBusSession(Vector<CString>& args) >+{ >+ const char* sessionAddress = g_getenv("DBUS_SESSION_BUS_ADDRESS"); >+ if (!sessionAddress) >+ return; >+ >+ GUniquePtr<char> sessionPath(dbusAddressToPath(sessionAddress)); >+ if (sessionPath) >+ bindIfExists(args, sessionPath.get(), BindFlags::ReadWrite); >+} >+ >+static void bindDBusSystem(Vector<CString>& args) >+{ >+ const char* systemAddress = g_getenv("DBUS_SYSTEM_BUS_ADDRESS"); >+ if (!systemAddress) >+ systemAddress = "unix:path=/var/run/dbus/system_bus_socket"; >+ >+ GUniquePtr<char> systemPath(dbusAddressToPath(systemAddress)); >+ if (systemPath) >+ bindIfExists(args, systemPath.get(), BindFlags::ReadWrite); >+} >+ >+static void bindDconf(Vector<CString>& args) >+{ >+ const char* runtimeDir = g_get_user_runtime_dir(); >+ GUniquePtr<char> dconfRuntimeDir(g_build_filename(runtimeDir, "dconf", nullptr)); >+ args.appendVector(Vector<CString>({ "--bind", dconfRuntimeDir.get(), dconfRuntimeDir.get() })); >+ >+ const char* dconfDir = g_getenv("DCONF_USER_CONFIG_DIR"); >+ if (dconfDir) >+ bindIfExists(args, dconfDir); >+ else { >+ const char* configDir = g_get_user_config_dir(); >+ GUniquePtr<char> dconfConfigDir(g_build_filename(configDir, "dconf", nullptr)); >+ bindIfExists(args, dconfConfigDir.get(), BindFlags::ReadWrite); >+ } >+} >+ >+static void bindWayland(Vector<CString>& args) >+{ >+ const char* display = g_getenv("WAYLAND_DISPLAY"); >+ if (!display) >+ display = "wayland-0"; >+ >+ const char* runtimeDir = g_get_user_runtime_dir(); >+ GUniquePtr<char> waylandRuntimeFile(g_build_filename(runtimeDir, display, nullptr)); >+ bindIfExists(args, waylandRuntimeFile.get(), BindFlags::ReadWrite); >+} >+ >+static void bindPulse(Vector<CString>& args) >+{ >+ // TODO: The server can be defined in config files we'd have to parse. >+ // They can also be set as X11 props, but that is getting a bit ridiculous. >+ const char* pulseServer = g_getenv("PULSE_SERVER"); >+ if (pulseServer) { >+ if (g_str_has_prefix(pulseServer, "unix:")) >+ bindIfExists(args, pulseServer + 5, BindFlags::ReadWrite); >+ // else it uses tcp >+ } else { >+ const char* runtimeDir = g_get_user_runtime_dir(); >+ GUniquePtr<char> pulseRuntimeDir(g_build_filename(runtimeDir, "pulse", nullptr)); >+ bindIfExists(args, pulseRuntimeDir.get(), BindFlags::ReadWrite); >+ } >+ >+ const char* pulseConfig = g_getenv("PULSE_CLIENTCONFIG"); >+ if (pulseConfig) >+ bindIfExists(args, pulseConfig); >+ >+ const char* configDir = g_get_user_config_dir(); >+ GUniquePtr<char> pulseConfigDir(g_build_filename(configDir, "pulse", nullptr)); >+ bindIfExists(args, pulseConfigDir.get()); >+ >+ const char* homeDir = g_get_home_dir(); >+ GUniquePtr<char> pulseHomeConfigDir(g_build_filename(homeDir, ".pulse", nullptr)); >+ GUniquePtr<char> asoundHomeConfigDir(g_build_filename(homeDir, ".asoundrc", nullptr)); >+ bindIfExists(args, pulseHomeConfigDir.get()); >+ bindIfExists(args, asoundHomeConfigDir.get()); >+} >+ >+static void bindFonts(Vector<CString>& args) >+{ >+ const char* configDir = g_get_user_config_dir(); >+ const char* homeDir = g_get_home_dir(); >+ const char* dataDir = g_get_user_data_dir(); >+ const char* cacheDir = g_get_user_cache_dir(); >+ >+ // Configs can include custom dirs but then we have to parse them... >+ GUniquePtr<char> fontConfig(g_build_filename(configDir, "fontconfig", nullptr)); >+ GUniquePtr<char> fontCache(g_build_filename(cacheDir, "fontconfig", nullptr)); >+ GUniquePtr<char> fontHomeConfig(g_build_filename(homeDir, ".fonts.conf", nullptr)); >+ GUniquePtr<char> fontHomeConfigDir(g_build_filename(configDir, ".fonts.conf.d", nullptr)); >+ GUniquePtr<char> fontData(g_build_filename(dataDir, "fonts", nullptr)); >+ GUniquePtr<char> fontHomeData(g_build_filename(homeDir, ".fonts", nullptr)); >+ bindIfExists(args, fontConfig.get()); >+ bindIfExists(args, fontCache.get(), BindFlags::ReadWrite); >+ bindIfExists(args, fontHomeConfig.get()); >+ bindIfExists(args, fontHomeConfigDir.get()); >+ bindIfExists(args, fontData.get()); >+ bindIfExists(args, fontHomeData.get()); >+} >+ >+static void bindGtkData(Vector<CString>& args) >+{ >+ const char* configDir = g_get_user_config_dir(); >+ const char* dataDir = g_get_user_data_dir(); >+ const char* homeDir = g_get_home_dir(); >+ >+ GUniquePtr<char> gtkConfig(g_build_filename(configDir, "gtk-3.0", nullptr)); >+ GUniquePtr<char> themeData(g_build_filename(dataDir, "themes", nullptr)); >+ GUniquePtr<char> themeHomeData(g_build_filename(homeDir, ".themes", nullptr)); >+ GUniquePtr<char> iconHomeData(g_build_filename(homeDir, ".icons", nullptr)); >+ bindIfExists(args, gtkConfig.get()); >+ bindIfExists(args, themeData.get()); >+ bindIfExists(args, themeHomeData.get()); >+ bindIfExists(args, iconHomeData.get()); >+} >+ >+static bool bindPathVar(Vector<CString>& args, const char* varname) >+{ >+ const char* pathValue = g_getenv(varname); >+ if (!pathValue) >+ return false; >+ >+ GUniquePtr<char*> splitPaths(g_strsplit(pathValue, ":", -1)); >+ for (size_t i; splitPaths.get()[i]; ++i) >+ bindIfExists(args, splitPaths.get()[i]); >+ >+ return true; >+} >+ >+static void bindGstreamerData(Vector<CString>& args) >+{ >+ if (!bindPathVar(args, "GST_PLUGIN_PATH_1_0")) >+ bindPathVar(args, "GST_PLUGIN_PATH"); >+ >+ if (!bindPathVar(args, "GST_PLUGIN_SYSTEM_PATH_1_0")) { >+ if (!bindPathVar(args, "GST_PLUGIN_SYSTEM_PATH")) { >+ GUniquePtr<char> gstData(g_build_filename(g_get_user_data_dir(), "gstreamer-1.0", nullptr)); >+ bindIfExists(args, gstData.get()); >+ } >+ } >+ >+ GUniquePtr<char> gstCache(g_build_filename(g_get_user_cache_dir(), "gstreamer-1.0", nullptr)); >+ bindIfExists(args, gstCache.get(), BindFlags::ReadWrite); >+ >+ bindIfExists(args, "/usr/libexec/gst-install-plugins-helper"); >+ bindIfExists(args, "/usr/local/libexec/gst-install-plugins-helper"); >+} >+ >+static void bindOpenGL(Vector<CString>& args) >+{ >+ args.appendVector(Vector<CString>({ >+ "--dev-bind-try", "/dev/dri", "/dev/dri", >+ // Mali >+ "--dev-bind-try", "/dev/mali", "/dev/mali", >+ "--dev-bind-try", "/dev/mali0", "/dev/mali0", >+ "--dev-bind-try", "/dev/umplock", "/dev/umplock", >+ // Nvidia >+ "--dev-bind-try", "/dev/nvidiactl", "/dev/nvidiactl", >+ "--dev-bind-try", "/dev/nvidia0", "/dev/nvidia0", >+ "--dev-bind-try", "/dev/nvidia", "/dev/nvidia", >+ })); >+} >+ >+static void bindV4l(Vector<CString>& args) >+{ >+ args.appendVector(Vector<CString>({ >+ "--dev-bind-try", "/dev/v4l", "/dev/v4l", >+ // Not pretty but a stop-gap for pipewire anyway >+ "--dev-bind-try", "/dev/video0", "/dev/video0", >+ "--dev-bind-try", "/dev/video1", "/dev/video1", >+ })); >+} >+ >+static void bindA11y(Vector<CString>& args) >+{ >+ static char* a11yPath = nullptr; >+ >+ if (a11yPath) { >+ bindIfExists(args, a11yPath, BindFlags::ReadWrite); >+ return; >+ } >+ >+ // FIXME: Avoid blocking IO... (It is cached for now to make it a one-time cost) >+ GRefPtr<GDBusConnection> sessionBus(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr)); >+ if (!sessionBus.get()) >+ return; >+ >+ GRefPtr<GDBusMessage> msg(g_dbus_message_new_method_call("org.a11y.Bus", "/org/a11y/bus", "org.a11y.Bus", "GetAddress")); >+ g_dbus_message_set_body(msg.get(), g_variant_new("()")); >+ GRefPtr<GDBusMessage> reply(g_dbus_connection_send_message_with_reply_sync( >+ sessionBus.get(), msg.get(), >+ G_DBUS_SEND_MESSAGE_FLAGS_NONE, >+ 30000, >+ nullptr, >+ nullptr, >+ nullptr)); >+ >+ GUniqueOutPtr<GError> error; >+ GUniqueOutPtr<char> a11yAddress; >+ if (reply.get()) { >+ if (g_dbus_message_to_gerror(reply.get(), &error.outPtr())) { >+ if (!g_error_matches(error.get(), G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) >+ g_warning("Can't find a11y bus: %s", error.get()->message); >+ } else >+ g_variant_get(g_dbus_message_get_body(reply.get()), "(s)", &a11yAddress.outPtr()); >+ } >+ >+ if (!a11yAddress.get()) >+ return; >+ >+ a11yPath = dbusAddressToPath(a11yAddress.get(), true); >+ bindIfExists(args, a11yPath, BindFlags::ReadWrite); >+} >+ >+static int memfd_create(const char* name, unsigned flags) >+{ >+ return syscall(__NR_memfd_create, name, flags); >+} >+ >+static int setupSeccomp() >+{ >+ /**** BEGIN NOTE ON CODE SHARING >+ * >+ * There are today a number of different Linux container >+ * implementations. That will likely continue for long into the >+ * future. But we can still try to share code, and it's important >+ * to do so because it affects what library and application writers >+ * can do, and we should support code portability between different >+ * container tools. >+ * >+ * This syscall blacklist is copied from linux-user-chroot, which was in turn >+ * clearly influenced by the Sandstorm.io blacklist. >+ * >+ * If you make any changes here, I suggest sending the changes along >+ * to other sandbox maintainers. Using the libseccomp list is also >+ * an appropriate venue: >+ * https://groups.google.com/forum/#!topic/libseccomp >+ * >+ * A non-exhaustive list of links to container tooling that might >+ * want to share this blacklist: >+ * >+ * https://github.com/sandstorm-io/sandstorm >+ * in src/sandstorm/supervisor.c++ >+ * http://cgit.freedesktop.org/xdg-app/xdg-app/ >+ * in common/flatpak-run.c >+ * https://git.gnome.org/browse/linux-user-chroot >+ * in src/setup-seccomp.c >+ * >+ **** END NOTE ON CODE SHARING >+ */ >+ // NOTE: LGPLv2.1+ >+ struct scmp_arg_cmp clone_arg = SCMP_A0(SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER); >+ struct { >+ int scall; >+ struct scmp_arg_cmp* arg; >+ } syscall_blacklist[] = { >+ /* Block dmesg */ >+ { SCMP_SYS(syslog), nullptr }, >+ /* Useless old syscall */ >+ { SCMP_SYS(uselib), nullptr }, >+ /* Don't allow disabling accounting */ >+ { SCMP_SYS(acct), nullptr }, >+ /* 16-bit code is unnecessary in the sandbox, and modify_ldt is a >+ historic source of interesting information leaks. */ >+ { SCMP_SYS(modify_ldt), nullptr }, >+ /* Don't allow reading current quota use */ >+ { SCMP_SYS(quotactl), nullptr }, >+ >+ /* Don't allow access to the kernel keyring */ >+ { SCMP_SYS(add_key), nullptr }, >+ { SCMP_SYS(keyctl), nullptr }, >+ { SCMP_SYS(request_key), nullptr }, >+ >+ /* Scary VM/NUMA ops */ >+ { SCMP_SYS(move_pages), nullptr }, >+ { SCMP_SYS(mbind), nullptr }, >+ { SCMP_SYS(get_mempolicy), nullptr }, >+ { SCMP_SYS(set_mempolicy), nullptr }, >+ { SCMP_SYS(migrate_pages), nullptr }, >+ >+ /* Don't allow subnamespace setups: */ >+ { SCMP_SYS(unshare), nullptr }, >+ { SCMP_SYS(mount), nullptr }, >+ { SCMP_SYS(pivot_root), nullptr }, >+ { SCMP_SYS(clone), &clone_arg }, >+ >+ /* Don't allow faking input to the controlling tty (CVE-2017-5226) */ >+ // FIXME: { SCMP_SYS(ioctl), &SCMP_A1(SCMP_CMP_EQ, (int)TIOCSTI) }, >+ >+ /* Profiling operations; we expect these to be done by tools from outside >+ * the sandbox. In particular perf has been the source of many CVEs. >+ */ >+ { SCMP_SYS(perf_event_open), nullptr }, >+ /* Don't allow you to switch to bsd emulation or whatnot */ >+ { SCMP_SYS(personality), nullptr }, >+ { SCMP_SYS(ptrace), nullptr } >+ }; >+ >+ scmp_filter_ctx seccomp = seccomp_init(SCMP_ACT_ALLOW); >+ if (!seccomp) >+ return -1; >+ >+ for (auto& rule : syscall_blacklist) { >+ int scall = rule.scall; >+ int r; >+ if (rule.arg) >+ r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), scall, 1, rule.arg); >+ else >+ r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), scall, 0); >+ if (r == -EFAULT) { >+ g_warning("Failed to add seccomp rule"); >+ seccomp_release(seccomp); >+ return -1; >+ } >+ } >+ >+ int tmpfd = memfd_create("seccomp-bpf", 0); >+ if (tmpfd == -1) { >+ g_warning("Failed to create memfd: %s", g_strerror(errno)); >+ seccomp_release(seccomp); >+ return -1; >+ } >+ >+ if (seccomp_export_bpf(seccomp, tmpfd)) { >+ g_warning("Failed to export seccomp bpf"); >+ seccomp_release(seccomp); >+ close(tmpfd); >+ return -1; >+ } >+ >+ lseek(tmpfd, 0, SEEK_SET); >+ seccomp_release(seccomp); >+ return tmpfd; >+} >+ >+static Vector<CString> getBwrapArgs(ProcessLauncher::ProcessType processType, const Vector<String>& extraPaths) >+{ >+ // It is impossible to know what access arbitrary plugins need and since it is for legacy >+ // reasons lets just leave it unsandboxed. >+ if (processType == ProcessLauncher::ProcessType::Plugin64 >+ || processType == ProcessLauncher::ProcessType::Plugin32) >+ return { }; >+ >+ Vector<CString> sandboxArgs = { >+ BWRAP_EXECUTABLE, >+ "--die-with-parent", >+ "--unshare-pid", >+ "--unshare-uts", >+ >+ // We assume /etc has safe permissions >+ // At a later point we can start masking privacy-concerning files >+ "--ro-bind", "/etc", "/etc", >+ "--dev", "/dev", >+ "--proc", "/proc", >+ "--tmpfs", "/tmp", >+ "--unsetenv", "TMPDIR", >+ "--dir", "/run", >+ "--symlink", "../run", "/var/run", >+ "--symlink", "../tmp", "/var/tmp", >+ "--ro-bind", "/sys/block", "/sys/block", >+ "--ro-bind", "/sys/bus", "/sys/bus", >+ "--ro-bind", "/sys/class", "/sys/class", >+ "--ro-bind", "/sys/dev", "/sys/dev", >+ "--ro-bind", "/sys/devices", "/sys/devices", >+ >+ "--ro-bind-try", "/usr/share", "/usr/share", >+ "--ro-bind-try", "/usr/local/share", "/usr/local/share", >+ >+ // We only grant access to the libdirs webkit is built with and >+ // guess system libdirs. This will always have some edge cases >+ "--ro-bind-try", "/lib", "/lib", >+ "--ro-bind-try", "/usr/lib", "/usr/lib", >+ "--ro-bind-try", "/usr/local/lib", "/usr/local/lib", >+ "--ro-bind-try", LIBDIR, LIBDIR, >+ "--ro-bind-try", "/lib64", "/lib64", >+ "--ro-bind-try", "/usr/lib64", "/usr/lib64", >+ "--ro-bind-try", "/usr/local/lib64", "/usr/local/lib64", >+ "--ro-bind-try", PKGLIBEXECDIR, PKGLIBEXECDIR, >+ }; >+ // We would have to parse ld config files for more info >+ bindPathVar(sandboxArgs, "LD_LIBRARY_PATH"); >+ >+ if (processType == ProcessLauncher::ProcessType::Network) { >+ // NOTE: Sadly the network process is used for `file://` URIs and for now >+ // we must just pass common things through to avoid regression >+ sandboxArgs.appendVector(Vector<CString>({ >+ "--ro-bind", "/home", "/home", >+ "--ro-bind-try", "/opt", "/opt", >+ "--ro-bind-try", "/srv", "/srv", >+ "--ro-bind-try", "/var", "/var", >+ "--ro-bind-try", "/mnt", "/mnt", >+ "--ro-bind-try", "/media", "/media", >+ })); >+ >+ // NOTE: DConf usage is probably entirely libsoups fault >+ // This requirement should be improved in the future >+ bindDBusSession(sandboxArgs); >+ bindDBusSystem(sandboxArgs); >+ bindDconf(sandboxArgs); >+ } >+ >+ // NOTE: This has network access for HLS via GStreamer >+ if (processType == ProcessLauncher::ProcessType::Web) { >+ // The web process itself needs access to dbus/x11/etc >+ bindX11(sandboxArgs); >+ bindWayland(sandboxArgs); >+ bindDBusSession(sandboxArgs); >+ bindDconf(sandboxArgs); >+ bindPulse(sandboxArgs); >+ bindFonts(sandboxArgs); >+ bindGtkData(sandboxArgs); >+ bindGstreamerData(sandboxArgs); >+ bindOpenGL(sandboxArgs); >+ bindV4l(sandboxArgs); >+ bindA11y(sandboxArgs); >+ } else { >+ // Only X11 users need this for XShm which is only the Web process >+ sandboxArgs.append("--unshare-ipc"); >+ } >+ >+ // Only process without any network access for now >+ if (processType == ProcessLauncher::ProcessType::Storage) >+ sandboxArgs.append("--unshare-net"); >+ >+#if ENABLE(DEVELOPER_MODE) >+ const char* execDirectory = g_getenv("WEBKIT_EXEC_PATH"); >+ if (execDirectory) { >+ String parentDir = FileSystem::directoryName(FileSystem::stringFromFileSystemRepresentation(execDirectory)); >+ bindIfExists(sandboxArgs, parentDir.utf8().data()); >+ } >+ >+ CString executablePath = getCurrentExecutablePath(); >+ if (!executablePath.isNull()) { >+ // Our executable is `/foo/bar/bin/Process`, we want `/foo/bar` as a usable prefix >+ String parentDir = FileSystem::directoryName(FileSystem::directoryName(FileSystem::stringFromFileSystemRepresentation(executablePath.data()))); >+ bindIfExists(sandboxArgs, parentDir.utf8().data()); >+ } >+#endif >+ >+ int seccompFd = setupSeccomp(); >+ if (seccompFd != -1) { >+ GUniquePtr<char> fdStr(g_strdup_printf("%d", seccompFd)); >+ // TODO: We leak this fd? >+ sandboxArgs.appendVector(Vector<CString>({ "--seccomp", fdStr.get() })); >+ } >+ >+ for (const String& path : extraPaths) { >+ const char* cpath = path.utf8().data(); >+ if (!cpath[0]) >+ g_warning("Empty path passed to sandbox, this is probably a bug"); >+ else >+ sandboxArgs.appendVector(Vector<CString>({ "--bind", cpath, cpath })); >+ } >+ >+ return sandboxArgs; >+} >+ >+#endif >+#if OS(LINUX) >+static bool isInsideFlatpak() >+{ >+ static int ret = -1; >+ if (ret != -1) >+ return ret; >+ >+ GUniquePtr<GKeyFile> infoFile(g_key_file_new()); >+ if (!g_key_file_load_from_file(infoFile.get(), "/.flatpak-info", G_KEY_FILE_NONE, nullptr)) { >+ ret = false; >+ return ret; >+ } >+ >+ // If we are in a `flatpak build` session we cannot launch ourselves since we aren't installed >+ GUniqueOutPtr<GError> error; >+ ret = !g_key_file_get_boolean(infoFile.get(), "Instance", "build", &error.outPtr()); >+ if (!ret && !error.get()) >+ g_warning("Not using Flatpak sandbox because in a build instance"); >+ >+ return ret; >+} >+ >+static Vector<CString> getFlatpakArgs(ProcessLauncher::ProcessType processType) >+{ >+ Vector<CString> sandboxArgs = { >+ "/usr/bin/flatpak-spawn", >+ }; >+ >+ if (processType == ProcessLauncher::ProcessType::Storage) >+ sandboxArgs.append("--no-network"); >+ >+ return sandboxArgs; >+} >+#endif >+ > void ProcessLauncher::launchProcess() > { > GPid pid = 0; >@@ -120,6 +681,24 @@ void ProcessLauncher::launchProcess() > } > #endif > >+#if OS(LINUX) >+ const char* sandboxEnv = g_getenv("WEBKIT_SANDBOX_ENABLED"); >+ bool sandboxEnabled = m_launchOptions.sandboxEnabled; >+ if (sandboxEnv) >+ sandboxEnabled = !strcmp(sandboxEnv, "1"); >+ >+ Vector<CString> sandboxArgs = { }; >+ if (sandboxEnabled) { >+ if (isInsideFlatpak()) >+ sandboxArgs = getFlatpakArgs(m_launchOptions.processType); >+#if ENABLE(BUBBLEWRAP_SANDBOX) >+ else >+ sandboxArgs = getBwrapArgs(m_launchOptions.processType, m_launchOptions.extraSandboxPaths); >+#endif >+ } >+ nargs += sandboxArgs.size(); >+#endif >+ > char** argv = g_newa(char*, nargs); > unsigned i = 0; > #if ENABLE(DEVELOPER_MODE) >@@ -127,6 +706,12 @@ void ProcessLauncher::launchProcess() > for (auto& arg : prefixArgs) > argv[i++] = const_cast<char*>(arg.data()); > #endif >+ >+#if OS(LINUX) >+ for (auto& arg : sandboxArgs) >+ argv[i++] = const_cast<char*>(arg.data()); >+#endif >+ > argv[i++] = const_cast<char*>(realExecutablePath.data()); > argv[i++] = processIdentifier.get(); > argv[i++] = webkitSocket.get(); >diff --git a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp >index 32430e8a81614f04ffaf5ebd2544c8e7c3dcd9c2..8f2b1f3e1cfb03dc9d42bef4f6db6b87a143eb75 100644 >--- a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp >+++ b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp >@@ -107,6 +107,15 @@ void NetworkProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launc > processPool().setShouldMakeNextNetworkProcessLaunchFailForTesting(false); > launchOptions.shouldMakeProcessLaunchFailForTesting = true; > } >+ >+#if PLATFORM(GTK) || PLATFORM(WPE) >+ API::WebsiteDataStore* store1 = processPool().websiteDataStore(); >+ WebsiteDataStore& store = store1->websiteDataStore(); >+ store.resolveDirectoriesIfNecessary(); >+ launchOptions.extraSandboxPaths.append(store.resolvedNetworkCacheDirectory()); >+ >+ launchOptions.sandboxEnabled = m_processPool.sandboxEnabled(); >+#endif > } > > void NetworkProcessProxy::connectionWillOpen(IPC::Connection& connection) >diff --git a/Source/WebKit/UIProcess/Storage/StorageProcessProxy.cpp b/Source/WebKit/UIProcess/Storage/StorageProcessProxy.cpp >index eb6605348ef831cf131a80f096aa7323f4317b23..a0f4530bb7f93ab0c8237c5a305520db7c1090c4 100644 >--- a/Source/WebKit/UIProcess/Storage/StorageProcessProxy.cpp >+++ b/Source/WebKit/UIProcess/Storage/StorageProcessProxy.cpp >@@ -87,6 +87,15 @@ void StorageProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launc > { > launchOptions.processType = ProcessLauncher::ProcessType::Storage; > ChildProcessProxy::getLaunchOptions(launchOptions); >+ >+#if PLATFORM(GTK) || PLATFORM(WPE) >+ launchOptions.sandboxEnabled = m_processPool.sandboxEnabled(); >+ >+ API::WebsiteDataStore* store1 = m_processPool.websiteDataStore(); >+ WebsiteDataStore& store = store1->websiteDataStore(); >+ store.resolveDirectoriesIfNecessary(); >+ launchOptions.extraSandboxPaths.append(store.resolvedIndexedDatabaseDirectory()); >+#endif > } > > void StorageProcessProxy::processWillShutDown(IPC::Connection& connection) >diff --git a/Source/WebKit/UIProcess/WebProcessPool.h b/Source/WebKit/UIProcess/WebProcessPool.h >index 25cc4d420c2e6f9acfea8b5e4cd81dcad66a47d8..4400f2c962eea59787fd640b3ac9dfa59abb317f 100644 >--- a/Source/WebKit/UIProcess/WebProcessPool.h >+++ b/Source/WebKit/UIProcess/WebProcessPool.h >@@ -472,6 +472,11 @@ public: > void removeMockMediaDevice(const String& persistentId); > void resetMockMediaDevices(); > >+#if PLATFORM(GTK) || PLATFORM(WPE) >+ void setSandboxEnabled(bool enabled) { m_sandboxEnabled = enabled; }; >+ bool sandboxEnabled() { return m_sandboxEnabled; }; >+#endif >+ > private: > void platformInitialize(); > >@@ -716,6 +721,10 @@ private: > > HashMap<WebCore::SecurityOriginData, Vector<SuspendedPageProxy*>> m_suspendedPages; > HashMap<WebCore::SecurityOriginData, RefPtr<WebProcessProxy>> m_swappedProcesses; >+ >+#if PLATFORM(GTK) || PLATFORM(WPE) >+ bool m_sandboxEnabled { false }; >+#endif > }; > > template<typename T> >diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp >index 5e0bc60b505f6b1c70dbcd4d32fb8f9aa817f617..14b667a98a18de732d851d10d00833f855f32738 100644 >--- a/Source/WebKit/UIProcess/WebProcessProxy.cpp >+++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp >@@ -184,6 +184,14 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt > processPool().setShouldMakeNextWebProcessLaunchFailForTesting(false); > launchOptions.shouldMakeProcessLaunchFailForTesting = true; > } >+ >+#if PLATFORM(GTK) || PLATFORM(WPE) >+ launchOptions.sandboxEnabled = m_processPool->sandboxEnabled(); >+ >+ websiteDataStore().resolveDirectoriesIfNecessary(); >+ launchOptions.extraSandboxPaths.append(websiteDataStore().resolvedNetworkCacheDirectory()); >+ launchOptions.extraSandboxPaths.append(websiteDataStore().resolvedApplicationCacheDirectory()); >+#endif > } > > void WebProcessProxy::connectionWillOpen(IPC::Connection& connection) >diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >index a1372b1d7dd8be1b6dffc8be1a959707f70dff97..e4fdd0d40722a05d336e198858a256dc0a678d10 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >@@ -178,6 +178,10 @@ void WebsiteDataStore::resolveDirectoriesIfNecessary() > m_resolvedConfiguration.javaScriptConfigurationDirectory = resolvePathForSandboxExtension(m_configuration.javaScriptConfigurationDirectory); > if (!m_configuration.cacheStorageDirectory.isEmpty() && m_resolvedConfiguration.cacheStorageDirectory.isEmpty()) > m_resolvedConfiguration.cacheStorageDirectory = resolvePathForSandboxExtension(m_configuration.cacheStorageDirectory); >+ if (!m_configuration.networkCacheDirectory.isEmpty()) >+ m_resolvedConfiguration.networkCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration.networkCacheDirectory); >+ if (!m_configuration.localStorageDirectory.isEmpty()) >+ m_resolvedConfiguration.localStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration.localStorageDirectory); > > // Resolve directories for file paths. > if (!m_configuration.cookieStorageFile.isEmpty()) { >diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >index 94ef4e301841b449040c5ff020fff80f3783be24..4d974f73465c00b89dfb523f7157cfd7249d0bda 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >@@ -152,6 +152,9 @@ public: > const String& resolvedIndexedDatabaseDirectory() const { return m_resolvedConfiguration.indexedDBDatabaseDirectory; } > const String& resolvedServiceWorkerRegistrationDirectory() const { return m_resolvedConfiguration.serviceWorkerRegistrationDirectory; } > const String& resolvedResourceLoadStatisticsDirectory() const { return m_resolvedConfiguration.resourceLoadStatisticsDirectory; } >+ const String& resolvedNetworkCacheDirectory() const { return m_resolvedConfiguration.networkCacheDirectory; } >+ const String& resolvedLocalStorageDirectory() const { return m_resolvedConfiguration.localStorageDirectory; } >+ > > StorageManager* storageManager() { return m_storageManager.get(); } > >diff --git a/Source/cmake/FindLibseccomp.cmake b/Source/cmake/FindLibseccomp.cmake >new file mode 100644 >index 0000000000000000000000000000000000000000..e6a22803dda02581ff972ce8aeceac0bd09d1a84 >--- /dev/null >+++ b/Source/cmake/FindLibseccomp.cmake >@@ -0,0 +1,53 @@ >+# - Try to find libseccomp >+# Once done, this will define >+# >+# LIBSECCOMP_FOUND - system has libseccomp >+# LIBSECCOMP_INCLUDE_DIRS - the libseccomp include drectories >+# LIBSECCOMP_LIBRARIES - link these to use libseccomp >+# >+# Copyright (C) 2018 Igalia S.L. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS >+# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS >+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; >+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, >+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR >+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF >+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+find_package(PkgConfig) >+pkg_check_modules(PC_LIBSECCOMP libseccomp) >+ >+find_path(LIBSECCOMP_INCLUDE_DIRS >+ NAMES seccomp.h >+ HINTS ${PC_LIBSECCOMP_INCLUDEDIR} >+) >+ >+find_library(LIBSECCOMP_LIBRARIES >+ NAMES seccomp >+ HINTS ${PC_LIBSECCOMP_LIBDIR} >+) >+ >+include(FindPackageHandleStandardArgs) >+find_package_handle_standard_args(LIBSECCOMP >+ REQUIRED_VARS LIBSECCOMP_LIBRARIES >+ FOUND_VAR LIBSECCOMP_FOUND >+ VERSION_VAR PC_LIBSECCOMP_VERSION) >+ >+mark_as_advanced( >+ LIBSECCOMP_INCLUDE_DIRS >+ LIBSECCOMP_LIBRARIES >+) >\ No newline at end of file >diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake >index 945dedec22eff04197728abd5a6e501a950d507f..792fdee00d06e7d5786d3930e08da7b47870c3bd 100644 >--- a/Source/cmake/OptionsGTK.cmake >+++ b/Source/cmake/OptionsGTK.cmake >@@ -113,9 +113,11 @@ endif () > if (CMAKE_SYSTEM_NAME MATCHES "Linux") > WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEMORY_SAMPLER PRIVATE ON) > WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_RESOURCE_USAGE PRIVATE ON) >+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_BUBBLEWRAP_SANDBOX PUBLIC ON) > else () > WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEMORY_SAMPLER PRIVATE OFF) > WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_RESOURCE_USAGE PRIVATE OFF) >+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_BUBBLEWRAP_SANDBOX PRIVATE OFF) > endif () > > # Public options shared with other WebKit ports. Do not add any options here >@@ -201,6 +203,37 @@ if (ENABLE_ACCELERATED_2D_CANVAS) > endif () > endif () > >+# Since flatpak has its own sandbox we just ignore this option >+if (EXISTS "/.flatpak-info") >+ set(ENABLE_BUBBLEWRAP_SANDBOX OFF) >+endif () >+ >+if (ENABLE_BUBBLEWRAP_SANDBOX) >+ find_program(BWRAP_EXECUTABLE bwrap) >+ if (NOT BWRAP_EXECUTABLE) >+ message(FATAL_ERROR "bwrap executable is needed for ENABLE_BUBBLEWRAP_SANDBOX") >+ endif () >+ add_definitions(-DBWRAP_EXECUTABLE="${BWRAP_EXECUTABLE}") >+ >+ execute_process( >+ COMMAND "${BWRAP_EXECUTABLE}" --version >+ RESULT_VARIABLE BWRAP_RET >+ OUTPUT_VARIABLE BWRAP_OUTPUT >+ ) >+ if (BWRAP_RET) >+ message(FATAL_ERROR "Failed to run ${BWRAP_EXECUTABLE}") >+ endif () >+ string(REGEX MATCH "([0-9]+.[0-9]+.[0-9]+)" BWRAP_VERSION "${BWRAP_OUTPUT}") >+ if (NOT "${BWRAP_VERSION}" VERSION_GREATER_EQUAL "0.3.1") >+ message(FATAL_ERROR "bwrap must be >= 0.3.1 but ${BWRAP_VERSION} found") >+ endif () >+ >+ find_package(Libseccomp) >+ if (NOT LIBSECCOMP_FOUND) >+ message(FATAL_ERROR "libseccomp is needed for ENABLE_BUBBLEWRAP_SANDBOX") >+ endif () >+endif () >+ > if (USE_LIBSECRET) > find_package(Libsecret) > if (NOT LIBSECRET_FOUND) >diff --git a/Source/cmake/WebKitFeatures.cmake b/Source/cmake/WebKitFeatures.cmake >index e15b6fe1e9d2c9c5b2c9e7ff0d9fbf97f032ba47..1ba322b003c51a36a231c61bcd3f96ab3f739e6c 100644 >--- a/Source/cmake/WebKitFeatures.cmake >+++ b/Source/cmake/WebKitFeatures.cmake >@@ -90,6 +90,7 @@ macro(WEBKIT_OPTION_BEGIN) > WEBKIT_OPTION_DEFINE(ENABLE_ATTACHMENT_ELEMENT "Toggle attachment element support" PRIVATE OFF) > WEBKIT_OPTION_DEFINE(ENABLE_AVF_CAPTIONS "Toggle AVFoundation caption support" PRIVATE OFF) > WEBKIT_OPTION_DEFINE(ENABLE_CACHE_PARTITIONING "Toggle cache partitioning support" PRIVATE OFF) >+ WEBKIT_OPTION_DEFINE(ENABLE_BUBBLEWRAP_SANDBOX "Toggle bubblewrap sandboxing support" PRIVATE OFF) > WEBKIT_OPTION_DEFINE(ENABLE_CHANNEL_MESSAGING "Toggle MessageChannel and MessagePort support" PRIVATE ON) > WEBKIT_OPTION_DEFINE(ENABLE_CONTENT_FILTERING "Toggle content filtering support" PRIVATE OFF) > WEBKIT_OPTION_DEFINE(ENABLE_CONTEXT_MENUS "Toggle Context Menu support" PRIVATE ON) >diff --git a/ChangeLog b/ChangeLog >index 22dfeddbb58b3a3b4b5dbd18c54e631e34920674..48ecc4dd6b8dcbb5e941fbb6ebac72500beaadc4 100644 >--- a/ChangeLog >+++ b/ChangeLog >@@ -1,3 +1,17 @@ >+2018-08-14 Patrick Griffis <pgriffis@igalia.com> >+ >+ [GTK][WPE] Implement subprocess sandboxing >+ https://bugs.webkit.org/show_bug.cgi?id=188568 >+ >+ Add check for bwrap executable and libseccomp >+ used for sandboxing. >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Source/cmake/FindLibseccomp.cmake: Added. >+ * Source/cmake/OptionsGTK.cmake: >+ * Source/cmake/WebKitFeatures.cmake: >+ > 2018-07-30 Thibault Saunier <tsaunier@igalia.com> > > [GStreamer] Make codecparsers optionnal
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188568
:
347098
|
347101
|
347158
|
347367
|
347637
|
347745
|
348657
|
348658
|
348659
|
348781
|
349776
|
349885
|
349888
|
350383
|
350385
|
350637
|
350638
|
350654
|
350655
|
350657
|
350781
|
351231
|
351370
|
352043