Commit 4b5d0f91 authored by Alex Gough's avatar Alex Gough Committed by Commit Bot

Provide chrome://sandbox for Windows

Creates a webui to display a snapshot of sandboxed processes for
Windows. This CL includes only the basic plumbing and very basic
display of relevant information.

Process information must be obtained from the sandbox (broker) and
from the browser, as each knows different things about what is
running. For now we simply display this as json but in later CLs the
range of information available will be increased, and the lists of
processes from different sources will be joined together to form a
friendlier display of diagnostic information.

This will result in a larger |sandbox_internals_win.js| file which we
do not need on other platforms. Hence the file for Windows is split
from that for Linux or ChromeOS. We will display different information
to that provided by Linux or ChromeOS as the underlying sandbox
technology specific to the host OS so much of the data extraction code
is #ifdefed for OS_WIN or in _win.cc,h files.

Bug: 997273
TEST=navigate to chrome://sandbox on Windows, see a page

Change-Id: I91a4cb12a6a5b632d0da89f5ffccfcb30b177b62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1767660
Commit-Queue: Alex Gough <ajgo@chromium.org>
Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701897}
parent 27078ada
...@@ -562,6 +562,10 @@ ...@@ -562,6 +562,10 @@
<include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals.js" type="BINDATA" compress="gzip" /> <include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals.js" type="BINDATA" compress="gzip" />
</if> </if>
<if expr="is_win">
<include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" preprocess="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals_win.js" type="BINDATA" compress="gzip" />
</if>
<include name="IDR_MEDIA_ENGAGEMENT_HTML" file="resources\media\media_engagement.html" flattenhtml="true" type="BINDATA" compress="gzip" allowexternalscript="true" /> <include name="IDR_MEDIA_ENGAGEMENT_HTML" file="resources\media\media_engagement.html" flattenhtml="true" type="BINDATA" compress="gzip" allowexternalscript="true" />
<include name="IDR_MEDIA_ENGAGEMENT_JS" file="resources\media\media_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" /> <include name="IDR_MEDIA_ENGAGEMENT_JS" file="resources\media\media_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" />
<include name="IDR_MEDIA_ENGAGEMENT_SCORE_DETAILS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\media\media_engagement_score_details.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_MEDIA_ENGAGEMENT_SCORE_DETAILS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\media\media_engagement_score_details.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
......
...@@ -39,6 +39,9 @@ if (closure_compile) { ...@@ -39,6 +39,9 @@ if (closure_compile) {
"welcome:closure_compile", "welcome:closure_compile",
] ]
} }
if (is_win) {
deps += [ "sandbox_internals:closure_compile" ]
}
if (is_chromeos) { if (is_chromeos) {
deps += [ "chromeos:closure_compile" ] deps += [ "chromeos:closure_compile" ]
} }
......
# 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.
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
if (is_win) {
deps = [
":sandbox_internals_win",
]
}
}
js_library("sandbox_internals_win") {
deps = [
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:util",
]
}
file://sandbox/OWNERS
# COMPONENT: Internals>Sandbox
# TEAM: security-dev@chromium.org
...@@ -30,10 +30,13 @@ ...@@ -30,10 +30,13 @@
} }
</style> </style>
<script src="chrome://resources/js/cr.js"></script> <script src="chrome://resources/js/cr.js"></script>
<if expr="not is_android"> <if expr="is_linux">
<script src="chrome://resources/js/load_time_data.js"></script> <script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://sandbox/strings.js"></script> <script src="chrome://sandbox/strings.js"></script>
</if> </if>
<if expr="is_win">
<script src="chrome://resources/js/promise_resolver.js"></script>
</if>
<script src="chrome://resources/js/util.js"></script> <script src="chrome://resources/js/util.js"></script>
<script src="sandbox_internals.js"></script> <script src="sandbox_internals.js"></script>
</head> </head>
...@@ -44,5 +47,8 @@ ...@@ -44,5 +47,8 @@
</table> </table>
<p id="evaluation"></p> <p id="evaluation"></p>
<if expr="is_win">
<pre id="raw-info"></pre>
</if>
</body> </body>
</html> </html>
// 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.
/**
* @typedef {{
* processId: number,
* processType: string,
* name: string,
* metricsName: string
* }}
*/
let BrowserHostProcess;
/**
* @typedef {{
* processId: number
* }}
*/
let RendererHostProcess;
/**
* @typedef {{
* processIds: !Array<number>
* }}
*/
let PolicyDiagnostic;
/**
* @typedef {{
* browser: !Array<!BrowserHostProcess>,
* renderer: !Array<!RendererHostProcess>,
* policies: !Array<!PolicyDiagnostic>
* }}
*/
let SandboxDiagnostics;
/**
* TODO(997273) Join lists into a single table with one row per process
* and add additional fields from Policy objects.
*/
/** @param {!SandboxDiagnostics} results */
function onGetSandboxDiagnostics(results) {
$('raw-info').textContent =
'browserProcesses:' + JSON.stringify(results.browser, null, 2) + '\n' +
'rendererProcesses:' + JSON.stringify(results.renderer, null, 2) + '\n' +
'policies:' + JSON.stringify(results.policies, null, 2);
}
document.addEventListener('DOMContentLoaded', () => {
cr.sendWithPromise('requestSandboxDiagnostics').then(onGetSandboxDiagnostics);
});
...@@ -613,13 +613,20 @@ jumbo_split_static_library("ui") { ...@@ -613,13 +613,20 @@ jumbo_split_static_library("ui") {
] ]
} }
if (is_android || is_linux) { if (is_win || is_android || is_linux) {
sources += [ sources += [
"webui/sandbox_internals_ui.cc", "webui/sandbox_internals_ui.cc",
"webui/sandbox_internals_ui.h", "webui/sandbox_internals_ui.h",
] ]
} }
if (is_win) {
sources += [
"webui/sandbox/sandbox_handler.cc",
"webui/sandbox/sandbox_handler.h",
]
}
if (is_android) { if (is_android) {
sources += [ sources += [
"android/android_about_app_info.cc", "android/android_about_app_info.cc",
......
...@@ -214,7 +214,7 @@ ...@@ -214,7 +214,7 @@
#include "chrome/browser/ui/webui/discards/discards_ui.h" #include "chrome/browser/ui/webui/discards/discards_ui.h"
#endif #endif
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
#include "chrome/browser/ui/webui/sandbox_internals_ui.h" #include "chrome/browser/ui/webui/sandbox_internals_ui.h"
#endif #endif
...@@ -689,7 +689,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, ...@@ -689,7 +689,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<CastUI>; return &NewWebUI<CastUI>;
} }
#endif #endif
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
if (url.host_piece() == chrome::kChromeUISandboxHost) { if (url.host_piece() == chrome::kChromeUISandboxHost) {
return &NewWebUI<SandboxInternalsUI>; return &NewWebUI<SandboxInternalsUI>;
} }
......
// 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
// 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_
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
#include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.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) #if defined(OS_ANDROID)
#include "chrome/common/sandbox_status_extension_android.mojom.h" #include "chrome/common/sandbox_status_extension_android.mojom.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
...@@ -79,6 +83,10 @@ content::WebUIDataSource* CreateDataSource() { ...@@ -79,6 +83,10 @@ content::WebUIDataSource* CreateDataSource() {
SandboxInternalsUI::SandboxInternalsUI(content::WebUI* web_ui) SandboxInternalsUI::SandboxInternalsUI(content::WebUI* web_ui)
: content::WebUIController(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); Profile* profile = Profile::FromWebUI(web_ui);
content::WebUIDataSource::Add(profile, CreateDataSource()); content::WebUIDataSource::Add(profile, CreateDataSource());
} }
......
...@@ -322,7 +322,7 @@ const char kChromeUIHatsURL[] = "chrome://hats/"; ...@@ -322,7 +322,7 @@ const char kChromeUIHatsURL[] = "chrome://hats/";
const char kChromeUILinuxProxyConfigHost[] = "linux-proxy-config"; const char kChromeUILinuxProxyConfigHost[] = "linux-proxy-config";
#endif #endif
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
const char kChromeUISandboxHost[] = "sandbox"; const char kChromeUISandboxHost[] = "sandbox";
#endif #endif
......
...@@ -281,7 +281,7 @@ extern const char kChromeUIHatsURL[]; ...@@ -281,7 +281,7 @@ extern const char kChromeUIHatsURL[];
extern const char kChromeUILinuxProxyConfigHost[]; extern const char kChromeUILinuxProxyConfigHost[];
#endif #endif
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
extern const char kChromeUISandboxHost[]; extern const char kChromeUISandboxHost[];
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment