Skip to content

Commit

Permalink
Adds sandbox API for policy diagnostics
Browse files Browse the repository at this point in the history
This will eventually support a chrome://sandbox WebUI for Windows.

Adds PolicyList and PolicyInfo types, the GetPolicyInfo() interface
to the sandbox (broker) and a basic implementation which simply
returns an empty list.

The intention is that GetPolicyInfo() will be called on a low
priority thread, and will then wait until the tracking thread
can complete the work of cloning policy information before
returning.

PolicyInfo is merely stubbed out at the moment and will be expanded
to describe more of the policy once this gets plugged into the
webui later.

Change-Id: Ie6ea8180e26ad71fa9e1628a2e9eef8f46a93fbd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1756952
Commit-Queue: Alex Gough <ajgo@chromium.org>
Reviewed-by: Will Harris <wfh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695409}
  • Loading branch information
quidity authored and Commit Bot committed Sep 11, 2019
1 parent 02df911 commit 9a32130
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 3 deletions.
4 changes: 4 additions & 0 deletions sandbox/win/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ static_library("sandbox") {
"src/restricted_token_utils.h",
"src/sandbox.cc",
"src/sandbox.h",
"src/sandbox_constants.cc",
"src/sandbox_constants.h",
"src/sandbox_factory.h",
"src/sandbox_globals.cc",
"src/sandbox_nt_types.h",
Expand All @@ -102,6 +104,8 @@ static_library("sandbox") {
"src/sandbox_policy.h",
"src/sandbox_policy_base.cc",
"src/sandbox_policy_base.h",
"src/sandbox_policy_info.cc",
"src/sandbox_policy_info.h",
"src/sandbox_rand.cc",
"src/sandbox_rand.h",
"src/sandbox_types.h",
Expand Down
45 changes: 42 additions & 3 deletions sandbox/win/src/broker_services.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ enum {
THREAD_CTRL_NEW_JOB_TRACKER,
THREAD_CTRL_NEW_PROCESS_TRACKER,
THREAD_CTRL_PROCESS_SIGNALLED,
THREAD_CTRL_GET_POLICY_INFO,
THREAD_CTRL_QUIT,
THREAD_CTRL_LAST,
};
Expand Down Expand Up @@ -116,11 +117,11 @@ void ProcessTracker::FreeResources() {
}
}

// Helper redispatches to process events to tracker thread
// Helper redispatches process events to tracker thread.
void WINAPI ProcessEventCallback(PVOID param, BOOLEAN ignored) {
// This callback should do very little, and must be threadpool safe
// This callback should do very little, and must be threadpool safe.
ProcessTracker* tracker = reinterpret_cast<ProcessTracker*>(param);
// if this fails we can do nothing... we will leak the policy.
// If this fails we can do nothing... we will leak the policy.
::PostQueuedCompletionStatus(tracker->iocp, 0, THREAD_CTRL_PROCESS_SIGNALLED,
reinterpret_cast<LPOVERLAPPED>(tracker));
}
Expand Down Expand Up @@ -328,6 +329,28 @@ DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
return p->process_id == tracker->process_id;
}));

} else if (THREAD_CTRL_GET_POLICY_INFO == key) {
// Clone the policies for sandbox diagnostics.
std::unique_ptr<PolicyDiagnosticsReceiver> receiver;
receiver.reset(static_cast<PolicyDiagnosticsReceiver*>(
reinterpret_cast<void*>(ovl)));
// The PollicyInfo ctor copies essential information from the trackers.
auto policy_list = std::make_unique<PolicyList>();
for (auto&& process_tracker : processes) {
if (process_tracker->policy) {
policy_list->push_back(
std::make_unique<PolicyInfo>(process_tracker->policy.get()));
}
}
for (auto&& job_tracker : jobs) {
if (job_tracker->policy) {
policy_list->push_back(
std::make_unique<PolicyInfo>(job_tracker->policy.get()));
}
}
// Receiver should return quickly.
receiver->ReceiveDiagnostics(std::move(policy_list));

} else if (THREAD_CTRL_QUIT == key) {
// The broker object is being destroyed so the thread needs to exit.
for (auto&& tracker : processes) {
Expand Down Expand Up @@ -615,4 +638,20 @@ ResultCode BrokerServicesBase::WaitForAllTargets() {
return SBOX_ALL_OK;
}

ResultCode BrokerServicesBase::GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) {
CHECK(job_thread_.IsValid());
// Post to the job thread.
if (!::PostQueuedCompletionStatus(
job_port_.Get(), 0, THREAD_CTRL_GET_POLICY_INFO,
reinterpret_cast<LPOVERLAPPED>(receiver.get()))) {
receiver->OnError(SBOX_ERROR_GENERIC);
return SBOX_ERROR_GENERIC;
}

// Ownership has passed to tracker thread.
receiver.release();
return SBOX_ALL_OK;
}

} // namespace sandbox
3 changes: 3 additions & 0 deletions sandbox/win/src/broker_services.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_policy_info.h"
#include "sandbox/win/src/sharedmem_ipc_server.h"
#include "sandbox/win/src/win2k_threadpool.h"
#include "sandbox/win/src/win_utils.h"
Expand Down Expand Up @@ -48,6 +49,8 @@ class BrokerServicesBase final : public BrokerServices,
DWORD* last_error,
PROCESS_INFORMATION* target) override;
ResultCode WaitForAllTargets() override;
ResultCode GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) override;

private:
// The routine that the worker thread executes. It is in charge of
Expand Down
32 changes: 32 additions & 0 deletions sandbox/win/src/sandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include "sandbox/win/fuzzer/fuzzer_types.h"
#endif

#include <stddef.h>
#include <memory>
#include <vector>

#include "base/memory/ref_counted.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_types.h"
Expand All @@ -33,10 +37,14 @@
namespace sandbox {

class BrokerServices;
class PolicyDiagnosticsReceiver;
class PolicyInfo;
class ProcessState;
class TargetPolicy;
class TargetServices;

using PolicyList = std::vector<std::unique_ptr<PolicyInfo>>;

// BrokerServices exposes all the broker API.
// The basic use is to start the target(s) and wait for them to end.
//
Expand Down Expand Up @@ -96,6 +104,18 @@ class BrokerServices {
// more information.
virtual ResultCode WaitForAllTargets() = 0;

// This call creates a snapshot of policies managed by the sandbox and
// returns them via a helper class.
// Parameters:
// receiver: The |PolicyDiagnosticsReceiver| implementation will be
// called to accept the results of the call.
// Returns:
// ALL_OK if the request was dispatched. All other return values
// imply failure, and the responder will not receive its completion
// callback.
virtual ResultCode GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) = 0;

protected:
~BrokerServices() {}
};
Expand Down Expand Up @@ -145,6 +165,18 @@ class TargetServices {
~TargetServices() {}
};

// This class mediates calls to BrokerServices::GetPolicyDiagnostics().
class PolicyDiagnosticsReceiver {
public:
// ReceiveDiagnostics() should return quickly and should not block the
// thread on which it is called.
virtual void ReceiveDiagnostics(std::unique_ptr<PolicyList> policies) = 0;
// OnError() is passed any errors encountered and |ReceiveDiagnostics|
// will not be called.
virtual void OnError(ResultCode code) = 0;
virtual ~PolicyDiagnosticsReceiver() {}
};

} // namespace sandbox

#endif // SANDBOX_WIN_SRC_SANDBOX_H_
11 changes: 11 additions & 0 deletions sandbox/win/src/sandbox_constants.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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 "sandbox/win/src/sandbox_constants.h"

namespace sandbox {
// Strings used as keys in base::Value snapshots of Policies.
extern const char kProcessIds[] = "process_ids";

} // namespace sandbox
14 changes: 14 additions & 0 deletions sandbox/win/src/sandbox_constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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 SANDBOX_WIN_SRC_SANDBOX_CONSTANTS_H_
#define SANDBOX_WIN_SRC_SANDBOX_CONSTANTS_H_

namespace sandbox {
// Strings used as keys in base::Value snapshots of Policies.
extern const char kProcessIds[];

} // namespace sandbox

#endif // SANDBOX_WIN_SRC_SANDBOX_CONSTANTS_H_
3 changes: 3 additions & 0 deletions sandbox/win/src/sandbox_policy_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
namespace sandbox {

class LowLevelPolicy;
class PolicyInfo;
class TargetProcess;
struct PolicyGlobal;

Expand Down Expand Up @@ -113,6 +114,8 @@ class PolicyBase final : public TargetPolicy {
const base::HandlesToInheritVector& GetHandlesBeingShared();

private:
// Allow PolicyInfo to snapshot PolicyBase for diagnostics.
friend class PolicyInfo;
~PolicyBase();

// Sets up interceptions for a new target.
Expand Down
50 changes: 50 additions & 0 deletions sandbox/win/src/sandbox_policy_info.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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 "sandbox/win/src/sandbox_policy_info.h"

#include "base/numerics/safe_conversions.h"
#include "base/values.h"
#include "sandbox/win/src/sandbox_constants.h"
#include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/target_process.h"

namespace sandbox {

namespace {

base::Value ProcessIdList(std::vector<uint32_t>& pids) {
base::ListValue results;
for (auto pid : pids) {
results.GetList().push_back(base::Value(base::strict_cast<double>(pid)));
}

return std::move(results);
}
} // namespace

// We are a friend of PolicyBase so that we can steal its private members
// quickly in the BrokerServices tracker thread.
PolicyInfo::PolicyInfo(PolicyBase* policy) {
DCHECK(policy);
// TODO(crbug/997273) Add more fields once webui plumbing is complete.
{
AutoLock lock(&policy->lock_);
for (auto&& target_process : policy->targets_) {
process_ids_.push_back(
base::strict_cast<uint32_t>(target_process->ProcessId()));
}
}
}

PolicyInfo::~PolicyInfo() {}

base::Value PolicyInfo::GetValue() {
// TODO(crbug/997273) Add more fields once webui plumbing is complete.
base::DictionaryValue val;
val.SetKey(kProcessIds, ProcessIdList(process_ids_));
return std::move(val);
}

} // namespace sandbox
35 changes: 35 additions & 0 deletions sandbox/win/src/sandbox_policy_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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 SANDBOX_WIN_SRC_SANDBOX_POLICY_INFO_H_
#define SANDBOX_WIN_SRC_SANDBOX_POLICY_INFO_H_

#include <vector>

#include "base/values.h"

namespace sandbox {

class PolicyBase;

// Intended to rhyme with TargetPolicy, may eventually share a common base
// with a configuration holding class (i.e. this class will extend with dynamic
// members such as the |process_ids_| list.)
class PolicyInfo {
public:
// This should quickly copy what it needs from PolicyBase.
PolicyInfo(PolicyBase* policy);
~PolicyInfo();

base::Value GetValue();

private:
std::vector<uint32_t> process_ids_;

DISALLOW_COPY_AND_ASSIGN(PolicyInfo);
};

} // namespace sandbox

#endif // SANDBOX_WIN_SRC_SANDBOX_POLICY_INFO_H_
Loading

0 comments on commit 9a32130

Please sign in to comment.