diff options
Diffstat (limited to 'chromium/chrome/browser/ui/webui/sandbox')
5 files changed, 324 insertions, 0 deletions
diff --git a/chromium/chrome/browser/ui/webui/sandbox/OWNERS b/chromium/chrome/browser/ui/webui/sandbox/OWNERS new file mode 100644 index 00000000000..058ee25caec --- /dev/null +++ b/chromium/chrome/browser/ui/webui/sandbox/OWNERS @@ -0,0 +1,3 @@ +file://sandbox/OWNERS +# COMPONENT: Internals>Sandbox +# TEAM: security-dev@chromium.org diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc new file mode 100644 index 00000000000..a4f1c53905c --- /dev/null +++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc @@ -0,0 +1,134 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/sandbox/sandbox_handler.h" + +#include <utility> + +#include "base/bind.h" +#include "base/numerics/safe_conversions.h" +#include "base/task/post_task.h" +#include "base/values.h" +#include "content/public/browser/browser_child_process_host_iterator.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_data.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_ui.h" +#include "content/public/common/process_type.h" +#include "services/service_manager/sandbox/win/sandbox_win.h" + +using content::BrowserChildProcessHostIterator; +using content::ChildProcessData; +using content::RenderProcessHost; + +namespace sandbox_handler { +namespace { +base::Value FetchBrowserChildProcesses() { + // The |BrowserChildProcessHostIterator| must only be used on the IO thread. + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + base::Value browser_processes(base::Value::Type::LIST); + + for (BrowserChildProcessHostIterator itr; !itr.Done(); ++itr) { + const ChildProcessData& process_data = itr.GetData(); + // Only add processes that have already started, i.e. with valid handles. + if (!process_data.GetProcess().IsValid()) + continue; + base::Value proc(base::Value::Type::DICTIONARY); + proc.SetPath("processId", base::Value(base::strict_cast<double>( + process_data.GetProcess().Pid()))); + proc.SetPath("processType", + base::Value(content::GetProcessTypeNameInEnglish( + process_data.process_type))); + proc.SetPath("name", base::Value(process_data.name)); + proc.SetPath("metricsName", base::Value(process_data.metrics_name)); + browser_processes.GetList().push_back(std::move(proc)); + } + + return browser_processes; +} + +base::Value FetchRenderHostProcesses() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + base::Value renderer_processes(base::Value::Type::LIST); + + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + RenderProcessHost* host = it.GetCurrentValue(); + // Skip processes that might not have started yet. + if (!host->GetProcess().IsValid()) + continue; + + base::Value proc(base::Value::Type::DICTIONARY); + proc.SetPath( + "processId", + base::Value(base::strict_cast<double>(host->GetProcess().Pid()))); + renderer_processes.GetList().push_back(std::move(proc)); + } + + return renderer_processes; +} + +} // namespace + +SandboxHandler::SandboxHandler() = default; +SandboxHandler::~SandboxHandler() = default; + +void SandboxHandler::RegisterMessages() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + web_ui()->RegisterMessageCallback( + "requestSandboxDiagnostics", + base::BindRepeating(&SandboxHandler::HandleRequestSandboxDiagnostics, + base::Unretained(this))); +} + +void SandboxHandler::HandleRequestSandboxDiagnostics( + const base::ListValue* args) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + CHECK_EQ(1U, args->GetList().size()); + sandbox_diagnostics_callback_id_ = args->GetList()[0].Clone(); + + AllowJavascript(); + + base::PostTaskAndReplyWithResult( + FROM_HERE, {content::BrowserThread::IO}, + base::Bind(&FetchBrowserChildProcesses), + base::Bind(&SandboxHandler::FetchBrowserChildProcessesCompleted, + weak_ptr_factory_.GetWeakPtr())); +} + +void SandboxHandler::FetchBrowserChildProcessesCompleted( + base::Value browser_processes) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + browser_processes_ = std::move(browser_processes); + + service_manager::SandboxWin::GetPolicyDiagnostics( + base::Bind(&SandboxHandler::FetchSandboxDiagnosticsCompleted, + weak_ptr_factory_.GetWeakPtr())); +} + +// This runs nested inside SandboxWin so we get out quickly. +void SandboxHandler::FetchSandboxDiagnosticsCompleted( + base::Value sandbox_policies) { + sandbox_policies_ = std::move(sandbox_policies); + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&SandboxHandler::GetRendererProcessesAndFinish, + weak_ptr_factory_.GetWeakPtr())); +} + +void SandboxHandler::GetRendererProcessesAndFinish() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + auto renderer_processes = FetchRenderHostProcesses(); + base::Value results(base::Value::Type::DICTIONARY); + results.SetPath("browser", std::move(browser_processes_)); + results.SetPath("policies", std::move(sandbox_policies_)); + results.SetPath("renderer", std::move(renderer_processes)); + ResolveJavascriptCallback(sandbox_diagnostics_callback_id_, + std::move(results)); +} + +} // namespace sandbox_handler diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.h b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.h new file mode 100644 index 00000000000..822044f28b3 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.h @@ -0,0 +1,52 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SANDBOX_SANDBOX_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SANDBOX_SANDBOX_HANDLER_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace base { +class Value; +class ListValue; +} // namespace base + +namespace sandbox_handler { +// This class takes care of sending the list of processes and their sandboxing +// status to the chrome://sandbox WebUI page when it is requested. +class SandboxHandler : public content::WebUIMessageHandler { + public: + SandboxHandler(); + ~SandboxHandler() override; + + private: + // content::WebUIMessageHandler: + void RegisterMessages() override; + + // Callback for the "requestSandboxDiagnostics" message. + void HandleRequestSandboxDiagnostics(const base::ListValue* args); + + void OnSandboxDataFetched(base::Value results); + + void FetchBrowserChildProcessesCompleted(base::Value browser_processes); + void FetchSandboxDiagnosticsCompleted(base::Value sandbox_policies); + void GetRendererProcessesAndFinish(); + + // The ID of the callback that will get invoked with the sandbox list. + base::Value sandbox_diagnostics_callback_id_; + base::Value browser_processes_; + base::Value sandbox_policies_; + + // Always keep this the last member of this class to make sure it's the + // first thing to be destructed. + base::WeakPtrFactory<SandboxHandler> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(SandboxHandler); +}; + +} // namespace sandbox_handler + +#endif // CHROME_BROWSER_UI_WEBUI_SANDBOX_SANDBOX_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc new file mode 100644 index 00000000000..9c3783b3791 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc @@ -0,0 +1,104 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h" + +#include <string> + +#include "build/build_config.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +#if defined(OS_WIN) +#include "chrome/browser/ui/webui/sandbox/sandbox_handler.h" +#endif + +#if defined(OS_ANDROID) +#include "chrome/common/sandbox_status_extension_android.mojom.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#endif + +#if defined(OS_LINUX) +#include "services/service_manager/sandbox/sandbox.h" +#include "services/service_manager/zygote/zygote_host_linux.h" +#endif + +namespace { + +#if defined(OS_LINUX) +static void SetSandboxStatusData(content::WebUIDataSource* source) { + // Get expected sandboxing status of renderers. + const int status = + service_manager::ZygoteHost::GetInstance()->GetRendererSandboxStatus(); + + source->AddBoolean("suid", status & service_manager::SandboxLinux::kSUID); + source->AddBoolean("userNs", status & service_manager::SandboxLinux::kUserNS); + source->AddBoolean("pidNs", status & service_manager::SandboxLinux::kPIDNS); + source->AddBoolean("netNs", status & service_manager::SandboxLinux::kNetNS); + source->AddBoolean("seccompBpf", + status & service_manager::SandboxLinux::kSeccompBPF); + source->AddBoolean("seccompTsync", + status & service_manager::SandboxLinux::kSeccompTSYNC); + source->AddBoolean("yamaBroker", + status & service_manager::SandboxLinux::kYama); + + // Yama does not enforce in user namespaces. + bool enforcing_yama_nonbroker = + status & service_manager::SandboxLinux::kYama && + !(status & service_manager::SandboxLinux::kUserNS); + source->AddBoolean("yamaNonbroker", enforcing_yama_nonbroker); + + // Require either the setuid or namespace sandbox for our first-layer sandbox. + bool good_layer1 = (status & service_manager::SandboxLinux::kSUID || + status & service_manager::SandboxLinux::kUserNS) && + status & service_manager::SandboxLinux::kPIDNS && + status & service_manager::SandboxLinux::kNetNS; + // A second-layer sandbox is also required to be adequately sandboxed. + bool good_layer2 = status & service_manager::SandboxLinux::kSeccompBPF; + source->AddBoolean("sandboxGood", good_layer1 && good_layer2); +} +#endif + +content::WebUIDataSource* CreateDataSource() { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUISandboxHost); + source->SetDefaultResource(IDR_SANDBOX_INTERNALS_HTML); + source->AddResourcePath("sandbox_internals.js", IDR_SANDBOX_INTERNALS_JS); + +#if defined(OS_LINUX) + SetSandboxStatusData(source); + source->UseStringsJs(); +#endif + + return source; +} + +} // namespace + +SandboxInternalsUI::SandboxInternalsUI(content::WebUI* web_ui) + : content::WebUIController(web_ui) { +#if defined(OS_WIN) + web_ui->AddMessageHandler( + std::make_unique<sandbox_handler::SandboxHandler>()); +#endif + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource::Add(profile, CreateDataSource()); +} + +void SandboxInternalsUI::RenderFrameCreated( + content::RenderFrameHost* render_frame_host) { +#if defined(OS_ANDROID) + mojo::AssociatedRemote<chrome::mojom::SandboxStatusExtension> sandbox_status; + render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface( + &sandbox_status); + sandbox_status->AddSandboxStatusExtension(); +#endif +} + +SandboxInternalsUI::~SandboxInternalsUI() {} diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h new file mode 100644 index 00000000000..5fbd2ea41f0 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h @@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SANDBOX_SANDBOX_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_SANDBOX_SANDBOX_INTERNALS_UI_H_ + +#include "base/macros.h" +#include "content/public/browser/web_ui_controller.h" + +// This WebUI page displays the status of the renderer sandbox on Linux and +// Android. The two OSes share the same basic page, but the data reported are +// obtained from different places: +// - On Linux, this object in the browser queries the renderer ZygoteHost +// to get the sandbox status of the renderers. The data are then specified +// as loadTimeData on the WebUI Page. +// - On Android, this object sends an IPC message to the +// SandboxStatusExtension in the renderer, which installs a JavaScript +// function on the web page to return the current sandbox status. +class SandboxInternalsUI : public content::WebUIController { + public: + explicit SandboxInternalsUI(content::WebUI* web_ui); + ~SandboxInternalsUI() override; + + void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; + + private: + DISALLOW_COPY_AND_ASSIGN(SandboxInternalsUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_SANDBOX_SANDBOX_INTERNALS_UI_H_ |