From 5bdce3eb2474d2f8fe3b015253f55a578c7da855 Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Wed, 28 Nov 2018 13:28:29 -0800 Subject: [PATCH] feat: support mixed-sandbox mode on linux --- atom/browser/web_contents_preferences.cc | 6 +- patches/common/chromium/.patches | 1 + .../support_mixed_sandbox_with_zygote.patch | 71 +++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 patches/common/chromium/support_mixed_sandbox_with_zygote.patch diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index fd0112d6b7b68..b8202fb9506b7 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -247,10 +247,12 @@ void WebContentsPreferences::AppendCommandLineSwitches( // If the `sandbox` option was passed to the BrowserWindow's webPreferences, // pass `--enable-sandbox` to the renderer so it won't have any node.js // integration. - if (IsEnabled(options::kSandbox)) + if (IsEnabled(options::kSandbox)) { command_line->AppendSwitch(switches::kEnableSandbox); - else if (!command_line->HasSwitch(switches::kEnableSandbox)) + } else if (!command_line->HasSwitch(switches::kEnableSandbox)) { command_line->AppendSwitch(service_manager::switches::kNoSandbox); + command_line->AppendSwitch(::switches::kNoZygote); + } // Check if nativeWindowOpen is enabled. if (IsEnabled(options::kNativeWindowOpen)) diff --git a/patches/common/chromium/.patches b/patches/common/chromium/.patches index eb46624cd18c8..32f297d0875a7 100644 --- a/patches/common/chromium/.patches +++ b/patches/common/chromium/.patches @@ -76,3 +76,4 @@ chrome_process_finder.patch customizable_app_indicator_id_prefix.patch cross_site_document_resource_handler.patch content_allow_embedder_to_prevent_locking_scheme_registry.patch +support_mixed_sandbox_with_zygote.patch diff --git a/patches/common/chromium/support_mixed_sandbox_with_zygote.patch b/patches/common/chromium/support_mixed_sandbox_with_zygote.patch new file mode 100644 index 0000000000000..f643ecebfb455 --- /dev/null +++ b/patches/common/chromium/support_mixed_sandbox_with_zygote.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jeremy Apthorp +Date: Wed, 28 Nov 2018 13:20:27 -0800 +Subject: support mixed-sandbox with zygote + +On Linux, Chromium launches all new renderer processes via a "zygote" +process which has the sandbox pre-initialized (see +//docs/linux_zygote.md). In order to support mixed-sandbox mode, in +which some renderers are launched with the sandbox engaged and others +without it, we need the option to launch non-sandboxed renderers without +going through the zygote. + +Chromium already supports a `--no-zygote` flag, but it turns off the +zygote completely, and thus also disables sandboxing. This patch allows +the `--no-zygote` flag to affect renderer processes on a case-by-case +basis, checking immediately prior to launch whether to go through the +zygote or not based on the command-line of the to-be-launched renderer. + +This patch could conceivably be upstreamed, as it does not affect +production Chromium (which does not use the `--no-zygote` flag). +However, the patch would need to be reviewed by the security team, as it +does touch a security-sensitive class. + +diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc +index 05e0ee79e5ad..80512d14c3dc 100644 +--- a/content/browser/renderer_host/render_process_host_impl.cc ++++ b/content/browser/renderer_host/render_process_host_impl.cc +@@ -465,7 +465,7 @@ SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) { + class RendererSandboxedProcessLauncherDelegate + : public SandboxedProcessLauncherDelegate { + public: +- RendererSandboxedProcessLauncherDelegate() {} ++ RendererSandboxedProcessLauncherDelegate(bool use_zygote): use_zygote_(use_zygote) {} + + ~RendererSandboxedProcessLauncherDelegate() override {} + +@@ -485,6 +485,9 @@ class RendererSandboxedProcessLauncherDelegate + + #if BUILDFLAG(USE_ZYGOTE_HANDLE) + service_manager::ZygoteHandle GetZygote() override { ++ if (!use_zygote_) { ++ return nullptr; ++ } + const base::CommandLine& browser_command_line = + *base::CommandLine::ForCurrentProcess(); + base::CommandLine::StringType renderer_prefix = +@@ -498,6 +501,9 @@ class RendererSandboxedProcessLauncherDelegate + service_manager::SandboxType GetSandboxType() override { + return service_manager::SANDBOX_TYPE_RENDERER; + } ++ ++ private: ++ bool use_zygote_; + }; + + const char kSessionStorageHolderKey[] = "kSessionStorageHolderKey"; +@@ -1731,11 +1737,13 @@ bool RenderProcessHostImpl::Init() { + cmd_line->PrependWrapper(renderer_prefix); + AppendRendererCommandLine(cmd_line.get()); + ++ bool use_zygote = !cmd_line->HasSwitch(switches::kNoZygote); ++ + // Spawn the child process asynchronously to avoid blocking the UI thread. + // As long as there's no renderer prefix, we can use the zygote process + // at this stage. + child_process_launcher_ = std::make_unique( +- std::make_unique(), ++ std::make_unique(use_zygote), + std::move(cmd_line), GetID(), this, std::move(mojo_invitation_), + base::BindRepeating(&RenderProcessHostImpl::OnMojoError, id_)); + channel_->Pause();