summaryrefslogtreecommitdiffstats
path: root/security/sandbox
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox')
-rw-r--r--security/sandbox/chromium-shim/patches/with_update/fix_max_syscalls_linux_aarch64.patch25
-rwxr-xr-xsecurity/sandbox/chromium-shim/patches/with_update/patch_order.txt3
-rw-r--r--security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch310
-rw-r--r--security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch743
-rw-r--r--security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h4
-rw-r--r--security/sandbox/chromium/sandbox/win/src/broker_services.cc75
-rw-r--r--security/sandbox/chromium/sandbox/win/src/broker_services.h22
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc93
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h41
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_interception.cc48
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_interception.h24
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_policy.cc93
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_policy.h39
-rw-r--r--security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc114
-rw-r--r--security/sandbox/chromium/sandbox/win/src/ipc_tags.h1
-rw-r--r--security/sandbox/chromium/sandbox/win/src/sandbox.h22
-rw-r--r--security/sandbox/chromium/sandbox/win/src/sandbox_policy.h4
-rw-r--r--security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc9
-rw-r--r--security/sandbox/chromium/sandbox/win/src/target_services.cc10
-rw-r--r--security/sandbox/chromium/sandbox/win/src/target_services.h5
-rw-r--r--security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc5
-rw-r--r--security/sandbox/common/SandboxSettings.cpp5
-rw-r--r--security/sandbox/linux/SandboxInfo.cpp26
-rw-r--r--security/sandbox/linux/launch/SandboxLaunch.cpp25
-rw-r--r--security/sandbox/mac/Sandbox.mm2
-rw-r--r--security/sandbox/moz.build3
-rw-r--r--security/sandbox/test/browser_content_sandbox_fs_snap.js2
-rw-r--r--security/sandbox/test/browser_content_sandbox_fs_xdg.js2
-rw-r--r--security/sandbox/test/browser_content_sandbox_syscalls.js41
-rw-r--r--security/sandbox/test/browser_content_sandbox_utils.js22
-rw-r--r--security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp65
-rw-r--r--security/sandbox/win/src/sandboxbroker/sandboxBroker.h3
32 files changed, 162 insertions, 1724 deletions
diff --git a/security/sandbox/chromium-shim/patches/with_update/fix_max_syscalls_linux_aarch64.patch b/security/sandbox/chromium-shim/patches/with_update/fix_max_syscalls_linux_aarch64.patch
new file mode 100644
index 0000000000..c5f816213a
--- /dev/null
+++ b/security/sandbox/chromium-shim/patches/with_update/fix_max_syscalls_linux_aarch64.patch
@@ -0,0 +1,25 @@
+# HG changeset patch
+# User Paul Bone <pbone@mozilla.org>
+# Date 1708492973 -39600
+# Wed Feb 21 16:22:53 2024 +1100
+# Node ID 501cb36ee885ebd0939e1892f821d55ac149ceec
+# Parent cf015b6f24b494190f562b255147f96e8b8b4139
+Bug 1866396 - Hard code the number of system calls for Linux on aarch64 r=jld
+
+Differential Revision: https://phabricator.services.mozilla.com/D202293
+
+diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+--- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
++++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+@@ -51,9 +51,9 @@
+
+ #elif defined(__aarch64__)
+
+-#include <asm-generic/unistd.h>
++// The unistd.h included in the sysroot has a very old __NR_syscalls
+ #define MIN_SYSCALL 0u
+-#define MAX_PUBLIC_SYSCALL __NR_syscalls
++#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u)
+ #define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+
+ #else
diff --git a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt
index 8d40aeaa7f..028348a0f0 100755
--- a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt
+++ b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt
@@ -1,5 +1,3 @@
-revert_remove_AddTargetPeer.patch
-revert_remove_BrokerDuplicateHandle.patch
replace_ScopedNativeLibrary_in_ApplyMitigationsToCurrentThread.patch
ifdef_out_FromStringInternal.patch
add_option_to_not_use_restricting_sids.patch
@@ -32,3 +30,4 @@ derive_sid_from_name.patch
add_loongarch_defines.patch
block_NtImpersonateAnonymousToken_before_LowerToken.patch
fix_broker_alive_mutex.patch
+fix_max_syscalls_linux_aarch64.patch
diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch b/security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch
deleted file mode 100644
index 04020b60b7..0000000000
--- a/security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch
+++ /dev/null
@@ -1,310 +0,0 @@
-# HG changeset patch
-# User Toshihito Kikuchi <tkikuchi@mozilla.com>
-# Date 1589671259 25200
-# Sat May 16 16:20:59 2020 -0700
-# Node ID 0b5183a01df78cc85264f2eae2c4d8e407bb1112
-# Parent d093cd9ccfcf06f4a1f0d7f1a4bd0f143ef92b4b
-Add BrokerServicesBase::IsSafeDuplicationTarget. r=bobowen
-
-This patch adds BrokerServicesBase::IsSafeDuplicationTarget and
-BrokerServicesBase::AddTargetPeer using the new ProcessTracker introduced by
-https://chromium.googlesource.com/chromium/src.git/+/3d8382cf9dd44cf9c05e43e42c500f4825e1fed8
-We need these methods for HandlePolicy which is added as a different patch.
-
-Chromium used to have AddTargetPeer and IsActiveTarget, but removed by
-the following commits because they were no longer used in Chromium.
-https://chromium.googlesource.com/chromium/src.git/+/996b42db5296bd3d11b3d7fde1a4602bbcefed2c
-https://chromium.googlesource.com/chromium/src.git/+/e615a1152ac6e10f1a91f0629fb8b5ca223ffbdc
-
-diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
---- a/security/sandbox/chromium/sandbox/win/src/broker_services.cc
-+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
-@@ -154,16 +154,18 @@ namespace sandbox {
- BrokerServicesBase::BrokerServicesBase() {}
-
- // The broker uses a dedicated worker thread that services the job completion
- // port to perform policy notifications and associated cleanup tasks.
- ResultCode BrokerServicesBase::Init() {
- if (job_port_.IsValid() || thread_pool_)
- return SBOX_ERROR_UNEXPECTED_CALL;
-
-+ ::InitializeCriticalSection(&lock_);
-+
- job_port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0));
- if (!job_port_.IsValid())
- return SBOX_ERROR_CANNOT_INIT_BROKERSERVICES;
-
- no_targets_.Set(::CreateEventW(nullptr, true, false, nullptr));
-
- job_thread_.Set(::CreateThread(nullptr, 0, // Default security and stack.
- TargetEventsThread, this, 0, nullptr));
-@@ -191,16 +193,17 @@ BrokerServicesBase::~BrokerServicesBase(
-
- if (job_thread_.IsValid() &&
- WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_.Get(), 1000)) {
- // Cannot clean broker services.
- NOTREACHED();
- return;
- }
- thread_pool_.reset();
-+ ::DeleteCriticalSection(&lock_);
- }
-
- scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() {
- // If you change the type of the object being created here you must also
- // change the downcast to it in SpawnTarget().
- scoped_refptr<TargetPolicy> policy(new PolicyBase);
- // PolicyBase starts with refcount 1.
- policy->Release();
-@@ -283,16 +286,21 @@ DWORD WINAPI BrokerServicesBase::TargetE
- if (1 == target_counter) {
- ::ResetEvent(no_targets);
- }
- break;
- }
-
- case JOB_OBJECT_MSG_EXIT_PROCESS:
- case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: {
-+ {
-+ AutoLock lock(&broker->lock_);
-+ broker->active_targets_.erase(
-+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
-+ }
- size_t erase_result = child_process_ids.erase(
- static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
- if (erase_result != 1U) {
- // The process was untracked e.g. a child process of the target.
- --untracked_target_counter;
- DCHECK(untracked_target_counter >= 0);
- }
- --target_counter;
-@@ -348,27 +356,31 @@ DWORD WINAPI BrokerServicesBase::TargetE
- tracker->wait_handle = INVALID_HANDLE_VALUE;
- }
- processes.push_back(std::move(tracker));
-
- } else if (THREAD_CTRL_PROCESS_SIGNALLED == key) {
- ProcessTracker* tracker =
- static_cast<ProcessTracker*>(reinterpret_cast<void*>(ovl));
-
-+ {
-+ AutoLock lock(&broker->lock_);
-+ broker->active_targets_.erase(tracker->process_id);
-+ }
-+
- ::UnregisterWait(tracker->wait_handle);
- tracker->wait_handle = INVALID_HANDLE_VALUE;
-
- // PID is unique until the process handle is closed in dtor.
- processes.erase(std::remove_if(processes.begin(), processes.end(),
- [&](auto&& p) -> bool {
- return p->process_id ==
- tracker->process_id;
- }),
- processes.end());
--
- } 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<PolicyDiagnosticList>();
- for (auto&& process_tracker : processes) {
-@@ -637,47 +649,79 @@ ResultCode BrokerServicesBase::SpawnTarg
- // the tracker. The worker thread takes ownership of these objects.
- CHECK(::PostQueuedCompletionStatus(
- job_port_.Get(), 0, THREAD_CTRL_NEW_JOB_TRACKER,
- reinterpret_cast<LPOVERLAPPED>(tracker)));
- // There is no obvious recovery after failure here. Previous version with
- // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
- CHECK(
- AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), tracker));
-+
-+ AutoLock lock(&lock_);
-+ active_targets_.insert(process_info.process_id());
- } else {
-- // Duplicate the process handle to give the tracking machinery
-- // something valid to wait on in the tracking thread.
-- HANDLE tmp_process_handle = INVALID_HANDLE_VALUE;
-- if (!::DuplicateHandle(::GetCurrentProcess(), process_info.process_handle(),
-- ::GetCurrentProcess(), &tmp_process_handle,
-- SYNCHRONIZE, false, 0 /*no options*/)) {
-- *last_error = ::GetLastError();
-+ result = AddTargetPeerInternal(process_info.process_handle(),
-+ process_info.process_id(),
-+ policy_base, last_error);
-+ if (result != SBOX_ALL_OK) {
- // This may fail in the same way as Job associated processes.
- // crbug.com/480639.
- SpawnCleanup(target);
-- return SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE;
-+ return result;
- }
-- base::win::ScopedHandle dup_process_handle(tmp_process_handle);
-- ProcessTracker* tracker = new ProcessTracker(
-- policy_base, process_info.process_id(), std::move(dup_process_handle));
-- // The tracker and policy will leak if this call fails.
-- ::PostQueuedCompletionStatus(job_port_.Get(), 0,
-- THREAD_CTRL_NEW_PROCESS_TRACKER,
-- reinterpret_cast<LPOVERLAPPED>(tracker));
- }
-
- *target_info = process_info.Take();
- return result;
- }
-
- ResultCode BrokerServicesBase::WaitForAllTargets() {
- ::WaitForSingleObject(no_targets_.Get(), INFINITE);
- return SBOX_ALL_OK;
- }
-
-+bool BrokerServicesBase::IsSafeDuplicationTarget(DWORD process_id) {
-+ AutoLock lock(&lock_);
-+ return active_targets_.find(process_id) != active_targets_.end();
-+}
-+
-+ResultCode BrokerServicesBase::AddTargetPeerInternal(
-+ HANDLE peer_process_handle,
-+ DWORD peer_process_id,
-+ scoped_refptr<PolicyBase> policy_base,
-+ DWORD* last_error) {
-+ // Duplicate the process handle to give the tracking machinery
-+ // something valid to wait on in the tracking thread.
-+ HANDLE tmp_process_handle = INVALID_HANDLE_VALUE;
-+ if (!::DuplicateHandle(::GetCurrentProcess(), peer_process_handle,
-+ ::GetCurrentProcess(), &tmp_process_handle,
-+ SYNCHRONIZE, false, 0 /*no options*/)) {
-+ *last_error = ::GetLastError();
-+ return SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE;
-+ }
-+ base::win::ScopedHandle dup_process_handle(tmp_process_handle);
-+ ProcessTracker* tracker = new ProcessTracker(
-+ policy_base, peer_process_id, std::move(dup_process_handle));
-+ // The tracker and policy will leak if this call fails.
-+ ::PostQueuedCompletionStatus(job_port_.Get(), 0,
-+ THREAD_CTRL_NEW_PROCESS_TRACKER,
-+ reinterpret_cast<LPOVERLAPPED>(tracker));
-+
-+ AutoLock lock(&lock_);
-+ active_targets_.insert(peer_process_id);
-+
-+ return SBOX_ALL_OK;
-+}
-+
-+ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) {
-+ DWORD last_error;
-+ return AddTargetPeerInternal(peer_process, ::GetProcessId(peer_process),
-+ nullptr, &last_error);
-+}
-+
- 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);
-diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/security/sandbox/chromium/sandbox/win/src/broker_services.h
---- a/security/sandbox/chromium/sandbox/win/src/broker_services.h
-+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.h
-@@ -13,16 +13,17 @@
-
- #include "base/compiler_specific.h"
- #include "base/macros.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/win/scoped_handle.h"
- #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_base.h"
- #include "sandbox/win/src/sharedmem_ipc_server.h"
- #include "sandbox/win/src/win2k_threadpool.h"
- #include "sandbox/win/src/win_utils.h"
-
- namespace sandbox {
-
- // BrokerServicesBase ---------------------------------------------------------
- // Broker implementation version 0
-@@ -43,16 +44,24 @@ class BrokerServicesBase final : public
- scoped_refptr<TargetPolicy> CreatePolicy() override;
- ResultCode SpawnTarget(const wchar_t* exe_path,
- const wchar_t* command_line,
- scoped_refptr<TargetPolicy> policy,
- ResultCode* last_warning,
- DWORD* last_error,
- PROCESS_INFORMATION* target) override;
- ResultCode WaitForAllTargets() override;
-+ ResultCode AddTargetPeer(HANDLE peer_process) override;
-+
-+ // Checks if the supplied process ID matches one of the broker's active
-+ // target processes. We use this method for the specific purpose of
-+ // checking if we can safely duplicate a handle to the supplied process
-+ // in DuplicateHandleProxyAction.
-+ bool IsSafeDuplicationTarget(DWORD process_id);
-+
- ResultCode GetPolicyDiagnostics(
- std::unique_ptr<PolicyDiagnosticsReceiver> receiver) override;
-
- private:
- // The routine that the worker thread executes. It is in charge of
- // notifications and cleanup-related tasks.
- static DWORD WINAPI TargetEventsThread(PVOID param);
-
-@@ -65,14 +74,27 @@ class BrokerServicesBase final : public
- base::win::ScopedHandle no_targets_;
-
- // Handle to the worker thread that reacts to job notifications.
- base::win::ScopedHandle job_thread_;
-
- // Provides a pool of threads that are used to wait on the IPC calls.
- std::unique_ptr<ThreadProvider> thread_pool_;
-
-+ // The set representing the broker's active target processes including
-+ // both sandboxed and unsandboxed peer processes.
-+ std::set<DWORD> active_targets_;
-+
-+ // Lock used to protect active_targets_ from being simultaneously accessed
-+ // by multiple threads.
-+ CRITICAL_SECTION lock_;
-+
-+ ResultCode AddTargetPeerInternal(HANDLE peer_process_handle,
-+ DWORD peer_process_id,
-+ scoped_refptr<PolicyBase> policy_base,
-+ DWORD* last_error);
-+
- DISALLOW_COPY_AND_ASSIGN(BrokerServicesBase);
- };
-
- } // namespace sandbox
-
- #endif // SANDBOX_WIN_SRC_BROKER_SERVICES_H_
-diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
---- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
-+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
-@@ -96,16 +96,24 @@ class BrokerServices {
-
- // This call blocks (waits) for all the targets to terminate.
- // Returns:
- // ALL_OK if successful. All other return values imply failure.
- // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
- // more information.
- virtual ResultCode WaitForAllTargets() = 0;
-
-+ // Adds an unsandboxed process as a peer for policy decisions (e.g.
-+ // HANDLES_DUP_ANY policy).
-+ // Returns:
-+ // ALL_OK if successful. All other return values imply failure.
-+ // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
-+ // more information.
-+ virtual ResultCode AddTargetPeer(HANDLE peer_process) = 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
diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch b/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch
deleted file mode 100644
index 970c0d1db2..0000000000
--- a/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch
+++ /dev/null
@@ -1,743 +0,0 @@
-# HG changeset patch
-# User Toshihito Kikuchi <tkikuchi@mozilla.com>
-# Date 1589671733 25200
-# Sat May 16 16:28:53 2020 -0700
-# Node ID 91bb5c3807cfe657cc24c9a3c217dd1f57db6d5c
-# Parent 22eb0bf7180801edf775be44cf299a50e01eb7bf
-Reinstate sandbox::TargetServices::BrokerDuplicateHandle. r=bobowen
-
-This patch reverts the commit removing sandbox::TargetServices::BrokerDuplicateHandle
-and applies the new IpcTag type.
-
-https://chromium.googlesource.com/chromium/src.git/+/569193665184525ca366e65d0735f5c851106e43
-https://chromium.googlesource.com/chromium/src.git/+/c8cff7f9663ce6d1ef35e5c717f43c867c3906eb
-
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
-@@ -0,0 +1,93 @@
-+// Copyright (c) 2012 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/handle_dispatcher.h"
-+
-+#include <stdint.h>
-+
-+#include "base/win/scoped_handle.h"
-+#include "sandbox/win/src/handle_interception.h"
-+#include "sandbox/win/src/handle_policy.h"
-+#include "sandbox/win/src/ipc_tags.h"
-+#include "sandbox/win/src/policy_broker.h"
-+#include "sandbox/win/src/policy_params.h"
-+#include "sandbox/win/src/sandbox.h"
-+#include "sandbox/win/src/sandbox_nt_util.h"
-+#include "sandbox/win/src/sandbox_types.h"
-+#include "sandbox/win/src/sandbox_utils.h"
-+
-+namespace sandbox {
-+
-+HandleDispatcher::HandleDispatcher(PolicyBase* policy_base)
-+ : policy_base_(policy_base) {
-+ static const IPCCall duplicate_handle_proxy = {
-+ {IpcTag::DUPLICATEHANDLEPROXY,
-+ {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}},
-+ reinterpret_cast<CallbackGeneric>(
-+ &HandleDispatcher::DuplicateHandleProxy)};
-+
-+ ipc_calls_.push_back(duplicate_handle_proxy);
-+}
-+
-+bool HandleDispatcher::SetupService(InterceptionManager* manager,
-+ IpcTag service) {
-+ // We perform no interceptions for handles right now.
-+ switch (service) {
-+ case IpcTag::DUPLICATEHANDLEPROXY:
-+ return true;
-+
-+ default:
-+ return false;
-+ }
-+}
-+
-+bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc,
-+ HANDLE source_handle,
-+ uint32_t target_process_id,
-+ uint32_t desired_access,
-+ uint32_t options) {
-+ static NtQueryObject QueryObject = NULL;
-+ if (!QueryObject)
-+ ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
-+
-+ // Get a copy of the handle for use in the broker process.
-+ HANDLE handle_temp;
-+ if (!::DuplicateHandle(ipc->client_info->process, source_handle,
-+ ::GetCurrentProcess(), &handle_temp,
-+ 0, FALSE, DUPLICATE_SAME_ACCESS | options)) {
-+ ipc->return_info.win32_result = ::GetLastError();
-+ return false;
-+ }
-+ options &= ~DUPLICATE_CLOSE_SOURCE;
-+ base::win::ScopedHandle handle(handle_temp);
-+
-+ // Get the object type (32 characters is safe; current max is 14).
-+ BYTE buffer[sizeof(OBJECT_TYPE_INFORMATION) + 32 * sizeof(wchar_t)];
-+ OBJECT_TYPE_INFORMATION* type_info =
-+ reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer);
-+ ULONG size = sizeof(buffer) - sizeof(wchar_t);
-+ NTSTATUS error =
-+ QueryObject(handle.Get(), ObjectTypeInformation, type_info, size, &size);
-+ if (!NT_SUCCESS(error)) {
-+ ipc->return_info.nt_status = error;
-+ return false;
-+ }
-+ type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0';
-+
-+ CountedParameterSet<HandleTarget> params;
-+ params[HandleTarget::NAME] = ParamPickerMake(type_info->Name.Buffer);
-+ params[HandleTarget::TARGET] = ParamPickerMake(target_process_id);
-+
-+ EvalResult eval = policy_base_->EvalPolicy(IpcTag::DUPLICATEHANDLEPROXY,
-+ params.GetBase());
-+ ipc->return_info.win32_result =
-+ HandlePolicy::DuplicateHandleProxyAction(eval, handle.Get(),
-+ target_process_id,
-+ &ipc->return_info.handle,
-+ desired_access, options);
-+ return true;
-+}
-+
-+} // namespace sandbox
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h
-@@ -0,0 +1,41 @@
-+// Copyright (c) 2012 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_SRC_HANDLE_DISPATCHER_H_
-+#define SANDBOX_SRC_HANDLE_DISPATCHER_H_
-+
-+#include <stdint.h>
-+
-+#include "base/macros.h"
-+#include "sandbox/win/src/crosscall_server.h"
-+#include "sandbox/win/src/sandbox_policy_base.h"
-+
-+namespace sandbox {
-+
-+// This class handles handle-related IPC calls.
-+class HandleDispatcher : public Dispatcher {
-+ public:
-+ explicit HandleDispatcher(PolicyBase* policy_base);
-+ ~HandleDispatcher() override {}
-+
-+ // Dispatcher interface.
-+ bool SetupService(InterceptionManager* manager, IpcTag service) override;
-+
-+ private:
-+ // Processes IPC requests coming from calls to
-+ // TargetServices::DuplicateHandle() in the target.
-+ bool DuplicateHandleProxy(IPCInfo* ipc,
-+ HANDLE source_handle,
-+ uint32_t target_process_id,
-+ uint32_t desired_access,
-+ uint32_t options);
-+
-+ PolicyBase* policy_base_;
-+ DISALLOW_COPY_AND_ASSIGN(HandleDispatcher);
-+};
-+
-+} // namespace sandbox
-+
-+#endif // SANDBOX_SRC_HANDLE_DISPATCHER_H_
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc
-@@ -0,0 +1,45 @@
-+// Copyright (c) 2012 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/handle_interception.h"
-+
-+#include "sandbox/win/src/crosscall_client.h"
-+#include "sandbox/win/src/ipc_tags.h"
-+#include "sandbox/win/src/sandbox_factory.h"
-+#include "sandbox/win/src/sandbox_nt_util.h"
-+#include "sandbox/win/src/sharedmem_ipc_client.h"
-+#include "sandbox/win/src/target_services.h"
-+
-+namespace sandbox {
-+
-+ResultCode DuplicateHandleProxy(HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options) {
-+ *target_handle = NULL;
-+
-+ void* memory = GetGlobalIPCMemory();
-+ if (NULL == memory)
-+ return SBOX_ERROR_NO_SPACE;
-+
-+ SharedMemIPCClient ipc(memory);
-+ CrossCallReturn answer = {0};
-+ ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY,
-+ source_handle, target_process_id,
-+ desired_access, options, &answer);
-+ if (SBOX_ALL_OK != code)
-+ return code;
-+
-+ if (answer.win32_result) {
-+ ::SetLastError(answer.win32_result);
-+ return SBOX_ERROR_GENERIC;
-+ }
-+
-+ *target_handle = answer.handle;
-+ return SBOX_ALL_OK;
-+}
-+
-+} // namespace sandbox
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.h b/security/sandbox/chromium/sandbox/win/src/handle_interception.h
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.h
-@@ -0,0 +1,24 @@
-+// Copyright (c) 2012 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/nt_internals.h"
-+#include "sandbox/win/src/sandbox_types.h"
-+
-+#ifndef SANDBOX_SRC_HANDLE_INTERCEPTION_H_
-+#define SANDBOX_SRC_HANDLE_INTERCEPTION_H_
-+
-+namespace sandbox {
-+
-+// TODO(jschuh) Add an interception to catch dangerous DuplicateHandle calls.
-+
-+ResultCode DuplicateHandleProxy(HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options);
-+
-+} // namespace sandbox
-+
-+#endif // SANDBOX_SRC_HANDLE_INTERCEPTION_H_
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
-@@ -0,0 +1,93 @@
-+// Copyright (c) 2012 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/handle_policy.h"
-+
-+#include <string>
-+
-+#include "base/win/scoped_handle.h"
-+#include "sandbox/win/src/broker_services.h"
-+#include "sandbox/win/src/ipc_tags.h"
-+#include "sandbox/win/src/policy_engine_opcodes.h"
-+#include "sandbox/win/src/policy_params.h"
-+#include "sandbox/win/src/sandbox_types.h"
-+#include "sandbox/win/src/sandbox_utils.h"
-+
-+namespace sandbox {
-+
-+bool HandlePolicy::GenerateRules(const wchar_t* type_name,
-+ TargetPolicy::Semantics semantics,
-+ LowLevelPolicy* policy) {
-+ PolicyRule duplicate_rule(ASK_BROKER);
-+
-+ switch (semantics) {
-+ case TargetPolicy::HANDLES_DUP_ANY: {
-+ if (!duplicate_rule.AddNumberMatch(IF_NOT, HandleTarget::TARGET,
-+ ::GetCurrentProcessId(), EQUAL)) {
-+ return false;
-+ }
-+ break;
-+ }
-+
-+ case TargetPolicy::HANDLES_DUP_BROKER: {
-+ if (!duplicate_rule.AddNumberMatch(IF, HandleTarget::TARGET,
-+ ::GetCurrentProcessId(), EQUAL)) {
-+ return false;
-+ }
-+ break;
-+ }
-+
-+ default:
-+ return false;
-+ }
-+ if (!duplicate_rule.AddStringMatch(IF, HandleTarget::NAME, type_name,
-+ CASE_INSENSITIVE)) {
-+ return false;
-+ }
-+ if (!policy->AddRule(IpcTag::DUPLICATEHANDLEPROXY, &duplicate_rule)) {
-+ return false;
-+ }
-+ return true;
-+}
-+
-+DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result,
-+ HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options) {
-+ // The only action supported is ASK_BROKER which means duplicate the handle.
-+ if (ASK_BROKER != eval_result) {
-+ return ERROR_ACCESS_DENIED;
-+ }
-+
-+ base::win::ScopedHandle remote_target_process;
-+ if (target_process_id != ::GetCurrentProcessId()) {
-+ // Sandboxed children are dynamic, so we check that manually.
-+ if (!BrokerServicesBase::GetInstance()->IsSafeDuplicationTarget(
-+ target_process_id)) {
-+ return ERROR_ACCESS_DENIED;
-+ }
-+
-+ remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE,
-+ target_process_id));
-+ if (!remote_target_process.IsValid())
-+ return ::GetLastError();
-+ }
-+
-+ // If the policy didn't block us and we have no valid target, then the broker
-+ // (this process) is the valid target.
-+ HANDLE target_process = remote_target_process.IsValid() ?
-+ remote_target_process.Get() : ::GetCurrentProcess();
-+ if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, target_process,
-+ target_handle, desired_access, FALSE,
-+ options)) {
-+ return ::GetLastError();
-+ }
-+
-+ return ERROR_SUCCESS;
-+}
-+
-+} // namespace sandbox
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.h b/security/sandbox/chromium/sandbox/win/src/handle_policy.h
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.h
-@@ -0,0 +1,39 @@
-+// Copyright (c) 2012 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_SRC_HANDLE_POLICY_H_
-+#define SANDBOX_SRC_HANDLE_POLICY_H_
-+
-+#include <string>
-+
-+#include "sandbox/win/src/crosscall_server.h"
-+#include "sandbox/win/src/policy_low_level.h"
-+#include "sandbox/win/src/sandbox_policy.h"
-+
-+namespace sandbox {
-+
-+enum EvalResult;
-+
-+// This class centralizes most of the knowledge related to handle policy.
-+class HandlePolicy {
-+ public:
-+ // Creates the required low-level policy rules to evaluate a high-level
-+ // policy rule for handles, in particular duplicate action.
-+ static bool GenerateRules(const wchar_t* type_name,
-+ TargetPolicy::Semantics semantics,
-+ LowLevelPolicy* policy);
-+
-+ // Processes a 'TargetPolicy::DuplicateHandle()' request from the target.
-+ static DWORD DuplicateHandleProxyAction(EvalResult eval_result,
-+ HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options);
-+};
-+
-+} // namespace sandbox
-+
-+#endif // SANDBOX_SRC_HANDLE_POLICY_H_
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc
-new file mode 100644
---- /dev/null
-+++ b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc
-@@ -0,0 +1,114 @@
-+// Copyright (c) 2012 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 "base/strings/stringprintf.h"
-+#include "sandbox/win/src/handle_policy.h"
-+#include "sandbox/win/src/nt_internals.h"
-+#include "sandbox/win/src/sandbox.h"
-+#include "sandbox/win/src/sandbox_factory.h"
-+#include "sandbox/win/src/sandbox_policy.h"
-+#include "sandbox/win/src/win_utils.h"
-+#include "sandbox/win/tests/common/controller.h"
-+#include "testing/gtest/include/gtest/gtest.h"
-+
-+namespace sandbox {
-+
-+// Just waits for the supplied number of milliseconds.
-+SBOX_TESTS_COMMAND int Handle_WaitProcess(int argc, wchar_t **argv) {
-+ if (argc != 1)
-+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-+
-+ ::Sleep(::wcstoul(argv[0], NULL, 10));
-+ return SBOX_TEST_TIMED_OUT;
-+}
-+
-+// Attempts to duplicate an event handle into the target process.
-+SBOX_TESTS_COMMAND int Handle_DuplicateEvent(int argc, wchar_t **argv) {
-+ if (argc != 1)
-+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-+
-+ // Create a test event to use as a handle.
-+ base::win::ScopedHandle test_event;
-+ test_event.Set(::CreateEvent(NULL, TRUE, TRUE, NULL));
-+ if (!test_event.IsValid())
-+ return SBOX_TEST_FIRST_ERROR;
-+
-+ // Get the target process ID.
-+ DWORD target_process_id = ::wcstoul(argv[0], NULL, 10);
-+
-+ HANDLE handle = NULL;
-+ ResultCode result = SandboxFactory::GetTargetServices()->DuplicateHandle(
-+ test_event.Get(), target_process_id, &handle, 0, DUPLICATE_SAME_ACCESS);
-+
-+ return (result == SBOX_ALL_OK) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
-+}
-+
-+// Tests that duplicating an object works only when the policy allows it.
-+TEST(HandlePolicyTest, DuplicateHandle) {
-+ TestRunner target;
-+ TestRunner runner;
-+
-+ // Kick off an asynchronous target process for testing.
-+ target.SetAsynchronous(true);
-+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000"));
-+
-+ // First test that we fail to open the event.
-+ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
-+ target.process_id());
-+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-+
-+ // Now successfully open the event after adding a duplicate handle rule.
-+ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
-+ TargetPolicy::HANDLES_DUP_ANY,
-+ L"Event"));
-+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
-+}
-+
-+// Tests that duplicating an object works only when the policy allows it.
-+TEST(HandlePolicyTest, DuplicatePeerHandle) {
-+ TestRunner target;
-+ TestRunner runner;
-+
-+ // Kick off an asynchronous target process for testing.
-+ target.SetAsynchronous(true);
-+ target.SetUnsandboxed(true);
-+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000"));
-+
-+ // First test that we fail to open the event.
-+ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
-+ target.process_id());
-+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-+
-+ // Now successfully open the event after adding a duplicate handle rule.
-+ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
-+ TargetPolicy::HANDLES_DUP_ANY,
-+ L"Event"));
-+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
-+}
-+
-+// Tests that duplicating an object works only when the policy allows it.
-+TEST(HandlePolicyTest, DuplicateBrokerHandle) {
-+ TestRunner runner;
-+
-+ // First test that we fail to open the event.
-+ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
-+ ::GetCurrentProcessId());
-+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-+
-+ // Add the peer rule and make sure we fail again.
-+ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
-+ TargetPolicy::HANDLES_DUP_ANY,
-+ L"Event"));
-+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-+
-+
-+ // Now successfully open the event after adding a broker handle rule.
-+ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
-+ TargetPolicy::HANDLES_DUP_BROKER,
-+ L"Event"));
-+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
-+}
-+
-+} // namespace sandbox
-+
-diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
---- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
-+++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
-@@ -23,16 +23,17 @@ enum class IpcTag {
- NTOPENPROCESS,
- NTOPENPROCESSTOKEN,
- NTOPENPROCESSTOKENEX,
- CREATEPROCESSW,
- CREATEEVENT,
- OPENEVENT,
- NTCREATEKEY,
- NTOPENKEY,
-+ DUPLICATEHANDLEPROXY,
- GDI_GDIDLLINITIALIZE,
- GDI_GETSTOCKOBJECT,
- USER_REGISTERCLASSW,
- CREATETHREAD,
- USER_ENUMDISPLAYMONITORS,
- USER_ENUMDISPLAYDEVICES,
- USER_GETMONITORINFO,
- GDI_CREATEOPMPROTECTEDOUTPUTS,
-diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
---- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
-+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
-@@ -161,16 +161,30 @@ class TargetServices {
- // fails the current process could be terminated immediately.
- virtual void LowerToken() = 0;
-
- // Returns the ProcessState object. Through that object it's possible to have
- // information about the current state of the process, such as whether
- // LowerToken has been called or not.
- virtual ProcessState* GetState() = 0;
-
-+ // Requests the broker to duplicate the supplied handle into the target
-+ // process. The target process must be an active sandbox child process
-+ // and the source process must have a corresponding policy allowing
-+ // handle duplication for this object type.
-+ // Returns:
-+ // ALL_OK if successful. All other return values imply failure.
-+ // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
-+ // more information.
-+ virtual ResultCode DuplicateHandle(HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options) = 0;
-+
- protected:
- ~TargetServices() {}
- };
-
- class PolicyInfo {
- public:
- // Returns a JSON representation of the policy snapshot.
- // This pointer has the same lifetime as this PolicyInfo object.
-diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
---- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
-+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
-@@ -25,28 +25,32 @@ class TargetPolicy {
- // exactly like the CreateProcess API does. See the comment at the top of
- // process_thread_dispatcher.cc for more details.
- enum SubSystem {
- SUBSYS_FILES, // Creation and opening of files and pipes.
- SUBSYS_NAMED_PIPES, // Creation of named pipes.
- SUBSYS_PROCESS, // Creation of child processes.
- SUBSYS_REGISTRY, // Creation and opening of registry keys.
- SUBSYS_SYNC, // Creation of named sync objects.
-+ SUBSYS_HANDLES, // Duplication of handles to other processes.
- SUBSYS_WIN32K_LOCKDOWN, // Win32K Lockdown related policy.
- SUBSYS_SIGNED_BINARY // Signed binary policy.
- };
-
- // Allowable semantics when a rule is matched.
- enum Semantics {
- FILES_ALLOW_ANY, // Allows open or create for any kind of access that
- // the file system supports.
- FILES_ALLOW_READONLY, // Allows open or create with read access only.
- FILES_ALLOW_QUERY, // Allows access to query the attributes of a file.
- FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics
- // only.
-+ HANDLES_DUP_ANY, // Allows duplicating handles opened with any
-+ // access permissions.
-+ HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process.
- NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe.
- PROCESS_MIN_EXEC, // Allows to create a process with minimal rights
- // over the resulting process and thread handles.
- // No other parameters besides the command line are
- // passed to the child process.
- PROCESS_ALL_EXEC, // Allows the creation of a process and return full
- // access on the returned handles.
- // This flag can be used only when the main token of
-diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
---- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
-+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
-@@ -12,16 +12,17 @@
- #include "base/logging.h"
- #include "base/macros.h"
- #include "base/stl_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/win/win_util.h"
- #include "base/win/windows_version.h"
- #include "sandbox/win/src/acl.h"
- #include "sandbox/win/src/filesystem_policy.h"
-+#include "sandbox/win/src/handle_policy.h"
- #include "sandbox/win/src/interception.h"
- #include "sandbox/win/src/job.h"
- #include "sandbox/win/src/named_pipe_policy.h"
- #include "sandbox/win/src/policy_broker.h"
- #include "sandbox/win/src/policy_engine_processor.h"
- #include "sandbox/win/src/policy_low_level.h"
- #include "sandbox/win/src/process_mitigations.h"
- #include "sandbox/win/src/process_mitigations_win32k_policy.h"
-@@ -754,16 +755,24 @@ ResultCode PolicyBase::AddRuleInternal(S
- }
- case SUBSYS_REGISTRY: {
- if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
- NOTREACHED();
- return SBOX_ERROR_BAD_PARAMS;
- }
- break;
- }
-+ case SUBSYS_HANDLES: {
-+ if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
-+ NOTREACHED();
-+ return SBOX_ERROR_BAD_PARAMS;
-+ }
-+ break;
-+ }
-+
- case SUBSYS_WIN32K_LOCKDOWN: {
- // Win32k intercept rules only supported on Windows 8 and above. This must
- // match the version checks in process_mitigations.cc for consistency.
- if (base::win::GetVersion() >= base::win::Version::WIN8) {
- DCHECK_EQ(MITIGATION_WIN32K_DISABLE,
- mitigations_ & MITIGATION_WIN32K_DISABLE)
- << "Enable MITIGATION_WIN32K_DISABLE before adding win32k policy "
- "rules.";
-diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
---- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
-+++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
-@@ -7,16 +7,17 @@
- #include <new>
-
- #include <process.h>
- #include <stdint.h>
-
- #include "base/win/windows_version.h"
- #include "sandbox/win/src/crosscall_client.h"
- #include "sandbox/win/src/handle_closer_agent.h"
-+#include "sandbox/win/src/handle_interception.h"
- #include "sandbox/win/src/heap_helper.h"
- #include "sandbox/win/src/ipc_tags.h"
- #include "sandbox/win/src/process_mitigations.h"
- #include "sandbox/win/src/restricted_token_utils.h"
- #include "sandbox/win/src/sandbox.h"
- #include "sandbox/win/src/sandbox_nt_util.h"
- #include "sandbox/win/src/sandbox_types.h"
- #include "sandbox/win/src/sharedmem_ipc_client.h"
-@@ -239,9 +240,19 @@ void ProcessState::SetRevertedToSelf() {
- if (process_state_ < ProcessStateInternal::REVERTED_TO_SELF)
- process_state_ = ProcessStateInternal::REVERTED_TO_SELF;
- }
-
- void ProcessState::SetCsrssConnected(bool csrss_connected) {
- csrss_connected_ = csrss_connected;
- }
-
-+
-+ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options) {
-+ return sandbox::DuplicateHandleProxy(source_handle, target_process_id,
-+ target_handle, desired_access, options);
-+}
-+
- } // namespace sandbox
-diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h
---- a/security/sandbox/chromium/sandbox/win/src/target_services.h
-+++ b/security/sandbox/chromium/sandbox/win/src/target_services.h
-@@ -40,16 +40,21 @@ class ProcessState {
- class TargetServicesBase : public TargetServices {
- public:
- TargetServicesBase();
-
- // Public interface of TargetServices.
- ResultCode Init() override;
- void LowerToken() override;
- ProcessState* GetState() override;
-+ ResultCode DuplicateHandle(HANDLE source_handle,
-+ DWORD target_process_id,
-+ HANDLE* target_handle,
-+ DWORD desired_access,
-+ DWORD options) override;
-
- // Factory method.
- static TargetServicesBase* GetInstance();
-
- // Sends a simple IPC Message that has a well-known answer. Returns true
- // if the IPC was successful and false otherwise. There are 2 versions of
- // this test: 1 and 2. The first one send a simple message while the
- // second one send a message with an in/out param.
-diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
---- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
-+++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
-@@ -5,16 +5,17 @@
- #include "sandbox/win/src/top_level_dispatcher.h"
-
- #include <stdint.h>
- #include <string.h>
-
- #include "base/logging.h"
- #include "sandbox/win/src/crosscall_server.h"
- #include "sandbox/win/src/filesystem_dispatcher.h"
-+#include "sandbox/win/src/handle_dispatcher.h"
- #include "sandbox/win/src/interception.h"
- #include "sandbox/win/src/internal_types.h"
- #include "sandbox/win/src/ipc_tags.h"
- #include "sandbox/win/src/named_pipe_dispatcher.h"
- #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
- #include "sandbox/win/src/process_thread_dispatcher.h"
- #include "sandbox/win/src/registry_dispatcher.h"
- #include "sandbox/win/src/sandbox_policy_base.h"
-@@ -55,16 +56,20 @@ TopLevelDispatcher::TopLevelDispatcher(P
- ipc_targets_[static_cast<size_t>(IpcTag::OPENEVENT)] = dispatcher;
- sync_dispatcher_.reset(dispatcher);
-
- dispatcher = new RegistryDispatcher(policy_);
- ipc_targets_[static_cast<size_t>(IpcTag::NTCREATEKEY)] = dispatcher;
- ipc_targets_[static_cast<size_t>(IpcTag::NTOPENKEY)] = dispatcher;
- registry_dispatcher_.reset(dispatcher);
-
-+ dispatcher = new HandleDispatcher(policy_);
-+ ipc_targets_[static_cast<size_t>(IpcTag::DUPLICATEHANDLEPROXY)] = dispatcher;
-+ handle_dispatcher_.reset(dispatcher);
-+
- dispatcher = new ProcessMitigationsWin32KDispatcher(policy_);
- ipc_targets_[static_cast<size_t>(IpcTag::GDI_GDIDLLINITIALIZE)] = dispatcher;
- ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETSTOCKOBJECT)] = dispatcher;
- ipc_targets_[static_cast<size_t>(IpcTag::USER_REGISTERCLASSW)] = dispatcher;
- ipc_targets_[static_cast<size_t>(IpcTag::USER_ENUMDISPLAYMONITORS)] =
- dispatcher;
- ipc_targets_[static_cast<size_t>(IpcTag::USER_ENUMDISPLAYDEVICES)] =
- dispatcher;
diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
index 313511f22e..c43e73448f 100644
--- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -51,9 +51,9 @@
#elif defined(__aarch64__)
-#include <asm-generic/unistd.h>
+// The unistd.h included in the sysroot has a very old __NR_syscalls
#define MIN_SYSCALL 0u
-#define MAX_PUBLIC_SYSCALL __NR_syscalls
+#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u)
#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
#else
diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
index 0ba71bbd5d..613becf37b 100644
--- a/security/sandbox/chromium/sandbox/win/src/broker_services.cc
+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
@@ -159,8 +159,6 @@ ResultCode BrokerServicesBase::Init() {
if (job_port_.IsValid() || thread_pool_)
return SBOX_ERROR_UNEXPECTED_CALL;
- ::InitializeCriticalSection(&lock_);
-
job_port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0));
if (!job_port_.IsValid())
return SBOX_ERROR_CANNOT_INIT_BROKERSERVICES;
@@ -201,7 +199,6 @@ BrokerServicesBase::~BrokerServicesBase() {
return;
}
thread_pool_.reset();
- ::DeleteCriticalSection(&lock_);
}
scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() {
@@ -294,11 +291,6 @@ DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
case JOB_OBJECT_MSG_EXIT_PROCESS:
case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: {
- {
- AutoLock lock(&broker->lock_);
- broker->active_targets_.erase(
- static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
- }
size_t erase_result = child_process_ids.erase(
static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
if (erase_result != 1U) {
@@ -364,11 +356,6 @@ DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
ProcessTracker* tracker =
static_cast<ProcessTracker*>(reinterpret_cast<void*>(ovl));
- {
- AutoLock lock(&broker->lock_);
- broker->active_targets_.erase(tracker->process_id);
- }
-
::UnregisterWait(tracker->wait_handle);
tracker->wait_handle = INVALID_HANDLE_VALUE;
// Copy process_id so that we can legally reference it even after we have
@@ -659,19 +646,26 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
// SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
CHECK(
AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), tracker));
-
- AutoLock lock(&lock_);
- active_targets_.insert(process_info.process_id());
} else {
- result = AddTargetPeerInternal(process_info.process_handle(),
- process_info.process_id(),
- policy_base, last_error);
- if (result != SBOX_ALL_OK) {
+ // Duplicate the process handle to give the tracking machinery
+ // something valid to wait on in the tracking thread.
+ HANDLE tmp_process_handle = INVALID_HANDLE_VALUE;
+ if (!::DuplicateHandle(::GetCurrentProcess(), process_info.process_handle(),
+ ::GetCurrentProcess(), &tmp_process_handle,
+ SYNCHRONIZE, false, 0 /*no options*/)) {
+ *last_error = ::GetLastError();
// This may fail in the same way as Job associated processes.
// crbug.com/480639.
target->Terminate();
- return result;
+ return SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE;
}
+ base::win::ScopedHandle dup_process_handle(tmp_process_handle);
+ ProcessTracker* tracker = new ProcessTracker(
+ policy_base, process_info.process_id(), std::move(dup_process_handle));
+ // The tracker and policy will leak if this call fails.
+ ::PostQueuedCompletionStatus(job_port_.Get(), 0,
+ THREAD_CTRL_NEW_PROCESS_TRACKER,
+ reinterpret_cast<LPOVERLAPPED>(tracker));
}
*target_info = process_info.Take();
@@ -683,45 +677,6 @@ ResultCode BrokerServicesBase::WaitForAllTargets() {
return SBOX_ALL_OK;
}
-bool BrokerServicesBase::IsSafeDuplicationTarget(DWORD process_id) {
- AutoLock lock(&lock_);
- return active_targets_.find(process_id) != active_targets_.end();
-}
-
-ResultCode BrokerServicesBase::AddTargetPeerInternal(
- HANDLE peer_process_handle,
- DWORD peer_process_id,
- scoped_refptr<PolicyBase> policy_base,
- DWORD* last_error) {
- // Duplicate the process handle to give the tracking machinery
- // something valid to wait on in the tracking thread.
- HANDLE tmp_process_handle = INVALID_HANDLE_VALUE;
- if (!::DuplicateHandle(::GetCurrentProcess(), peer_process_handle,
- ::GetCurrentProcess(), &tmp_process_handle,
- SYNCHRONIZE, false, 0 /*no options*/)) {
- *last_error = ::GetLastError();
- return SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE;
- }
- base::win::ScopedHandle dup_process_handle(tmp_process_handle);
- ProcessTracker* tracker = new ProcessTracker(
- policy_base, peer_process_id, std::move(dup_process_handle));
- // The tracker and policy will leak if this call fails.
- ::PostQueuedCompletionStatus(job_port_.Get(), 0,
- THREAD_CTRL_NEW_PROCESS_TRACKER,
- reinterpret_cast<LPOVERLAPPED>(tracker));
-
- AutoLock lock(&lock_);
- active_targets_.insert(peer_process_id);
-
- return SBOX_ALL_OK;
-}
-
-ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) {
- DWORD last_error;
- return AddTargetPeerInternal(peer_process, ::GetProcessId(peer_process),
- nullptr, &last_error);
-}
-
ResultCode BrokerServicesBase::GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) {
CHECK(job_thread_.IsValid());
diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/security/sandbox/chromium/sandbox/win/src/broker_services.h
index 64dc6d66e5..1d7eafdea3 100644
--- a/security/sandbox/chromium/sandbox/win/src/broker_services.h
+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.h
@@ -19,7 +19,6 @@
#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_base.h"
#include "sandbox/win/src/sharedmem_ipc_server.h"
#include "sandbox/win/src/win2k_threadpool.h"
#include "sandbox/win/src/win_utils.h"
@@ -51,14 +50,6 @@ class BrokerServicesBase final : public BrokerServices,
DWORD* last_error,
PROCESS_INFORMATION* target) override;
ResultCode WaitForAllTargets() override;
- ResultCode AddTargetPeer(HANDLE peer_process) override;
-
- // Checks if the supplied process ID matches one of the broker's active
- // target processes. We use this method for the specific purpose of
- // checking if we can safely duplicate a handle to the supplied process
- // in DuplicateHandleProxyAction.
- bool IsSafeDuplicationTarget(DWORD process_id);
-
ResultCode GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) override;
@@ -84,19 +75,6 @@ class BrokerServicesBase final : public BrokerServices,
// Provides a pool of threads that are used to wait on the IPC calls.
std::unique_ptr<ThreadProvider> thread_pool_;
- // The set representing the broker's active target processes including
- // both sandboxed and unsandboxed peer processes.
- std::set<DWORD> active_targets_;
-
- // Lock used to protect active_targets_ from being simultaneously accessed
- // by multiple threads.
- CRITICAL_SECTION lock_;
-
- ResultCode AddTargetPeerInternal(HANDLE peer_process_handle,
- DWORD peer_process_id,
- scoped_refptr<PolicyBase> policy_base,
- DWORD* last_error);
-
DISALLOW_COPY_AND_ASSIGN(BrokerServicesBase);
};
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
deleted file mode 100644
index 611e33d2a6..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2012 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/handle_dispatcher.h"
-
-#include <stdint.h>
-
-#include "base/win/scoped_handle.h"
-#include "sandbox/win/src/handle_interception.h"
-#include "sandbox/win/src/handle_policy.h"
-#include "sandbox/win/src/ipc_tags.h"
-#include "sandbox/win/src/policy_broker.h"
-#include "sandbox/win/src/policy_params.h"
-#include "sandbox/win/src/sandbox.h"
-#include "sandbox/win/src/sandbox_nt_util.h"
-#include "sandbox/win/src/sandbox_types.h"
-#include "sandbox/win/src/sandbox_utils.h"
-
-namespace sandbox {
-
-HandleDispatcher::HandleDispatcher(PolicyBase* policy_base)
- : policy_base_(policy_base) {
- static const IPCCall duplicate_handle_proxy = {
- {IpcTag::DUPLICATEHANDLEPROXY,
- {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}},
- reinterpret_cast<CallbackGeneric>(
- &HandleDispatcher::DuplicateHandleProxy)};
-
- ipc_calls_.push_back(duplicate_handle_proxy);
-}
-
-bool HandleDispatcher::SetupService(InterceptionManager* manager,
- IpcTag service) {
- // We perform no interceptions for handles right now.
- switch (service) {
- case IpcTag::DUPLICATEHANDLEPROXY:
- return true;
-
- default:
- return false;
- }
-}
-
-bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc,
- HANDLE source_handle,
- uint32_t target_process_id,
- uint32_t desired_access,
- uint32_t options) {
- static NtQueryObject QueryObject = NULL;
- if (!QueryObject)
- ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
-
- // Get a copy of the handle for use in the broker process.
- HANDLE handle_temp;
- if (!::DuplicateHandle(ipc->client_info->process, source_handle,
- ::GetCurrentProcess(), &handle_temp,
- 0, FALSE, DUPLICATE_SAME_ACCESS | options)) {
- ipc->return_info.win32_result = ::GetLastError();
- return false;
- }
- options &= ~DUPLICATE_CLOSE_SOURCE;
- base::win::ScopedHandle handle(handle_temp);
-
- // Get the object type (32 characters is safe; current max is 14).
- BYTE buffer[sizeof(OBJECT_TYPE_INFORMATION) + 32 * sizeof(wchar_t)];
- OBJECT_TYPE_INFORMATION* type_info =
- reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer);
- ULONG size = sizeof(buffer) - sizeof(wchar_t);
- NTSTATUS error =
- QueryObject(handle.Get(), ObjectTypeInformation, type_info, size, &size);
- if (!NT_SUCCESS(error)) {
- ipc->return_info.nt_status = error;
- return false;
- }
- type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0';
-
- CountedParameterSet<HandleTarget> params;
- params[HandleTarget::NAME] = ParamPickerMake(type_info->Name.Buffer);
- params[HandleTarget::TARGET] = ParamPickerMake(target_process_id);
-
- EvalResult eval = policy_base_->EvalPolicy(IpcTag::DUPLICATEHANDLEPROXY,
- params.GetBase());
- ipc->return_info.win32_result =
- HandlePolicy::DuplicateHandleProxyAction(eval, handle.Get(),
- target_process_id,
- &ipc->return_info.handle,
- desired_access, options);
- return true;
-}
-
-} // namespace sandbox
-
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h
deleted file mode 100644
index 6f9adbc10b..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012 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_SRC_HANDLE_DISPATCHER_H_
-#define SANDBOX_SRC_HANDLE_DISPATCHER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "sandbox/win/src/crosscall_server.h"
-#include "sandbox/win/src/sandbox_policy_base.h"
-
-namespace sandbox {
-
-// This class handles handle-related IPC calls.
-class HandleDispatcher : public Dispatcher {
- public:
- explicit HandleDispatcher(PolicyBase* policy_base);
- ~HandleDispatcher() override {}
-
- // Dispatcher interface.
- bool SetupService(InterceptionManager* manager, IpcTag service) override;
-
- private:
- // Processes IPC requests coming from calls to
- // TargetServices::DuplicateHandle() in the target.
- bool DuplicateHandleProxy(IPCInfo* ipc,
- HANDLE source_handle,
- uint32_t target_process_id,
- uint32_t desired_access,
- uint32_t options);
-
- PolicyBase* policy_base_;
- DISALLOW_COPY_AND_ASSIGN(HandleDispatcher);
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_SRC_HANDLE_DISPATCHER_H_
-
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc
deleted file mode 100644
index 53db4a8b27..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012 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/handle_interception.h"
-
-#include "sandbox/win/src/crosscall_client.h"
-#include "sandbox/win/src/ipc_tags.h"
-#include "sandbox/win/src/sandbox_factory.h"
-#include "sandbox/win/src/sandbox_nt_util.h"
-#include "sandbox/win/src/sharedmem_ipc_client.h"
-#include "sandbox/win/src/target_services.h"
-#include "mozilla/sandboxing/sandboxLogging.h"
-
-namespace sandbox {
-
-ResultCode DuplicateHandleProxy(HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options) {
- *target_handle = NULL;
-
- void* memory = GetGlobalIPCMemory();
- if (NULL == memory)
- return SBOX_ERROR_NO_SPACE;
-
- SharedMemIPCClient ipc(memory);
- CrossCallReturn answer = {0};
- ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY,
- source_handle, target_process_id,
- desired_access, options, &answer);
- if (SBOX_ALL_OK != code)
- return code;
-
- if (answer.win32_result) {
- ::SetLastError(answer.win32_result);
- mozilla::sandboxing::LogBlocked("DuplicateHandle");
- return SBOX_ERROR_GENERIC;
- }
-
- *target_handle = answer.handle;
- mozilla::sandboxing::LogAllowed("DuplicateHandle");
- return SBOX_ALL_OK;
-}
-
-} // namespace sandbox
-
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.h b/security/sandbox/chromium/sandbox/win/src/handle_interception.h
deleted file mode 100644
index 6f60811f17..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_interception.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 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/nt_internals.h"
-#include "sandbox/win/src/sandbox_types.h"
-
-#ifndef SANDBOX_SRC_HANDLE_INTERCEPTION_H_
-#define SANDBOX_SRC_HANDLE_INTERCEPTION_H_
-
-namespace sandbox {
-
-// TODO(jschuh) Add an interception to catch dangerous DuplicateHandle calls.
-
-ResultCode DuplicateHandleProxy(HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options);
-
-} // namespace sandbox
-
-#endif // SANDBOX_SRC_HANDLE_INTERCEPTION_H_
-
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
deleted file mode 100644
index fa3295ae3f..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2012 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/handle_policy.h"
-
-#include <string>
-
-#include "base/win/scoped_handle.h"
-#include "sandbox/win/src/broker_services.h"
-#include "sandbox/win/src/ipc_tags.h"
-#include "sandbox/win/src/policy_engine_opcodes.h"
-#include "sandbox/win/src/policy_params.h"
-#include "sandbox/win/src/sandbox_types.h"
-#include "sandbox/win/src/sandbox_utils.h"
-
-namespace sandbox {
-
-bool HandlePolicy::GenerateRules(const wchar_t* type_name,
- TargetPolicy::Semantics semantics,
- LowLevelPolicy* policy) {
- PolicyRule duplicate_rule(ASK_BROKER);
-
- switch (semantics) {
- case TargetPolicy::HANDLES_DUP_ANY: {
- if (!duplicate_rule.AddNumberMatch(IF_NOT, HandleTarget::TARGET,
- ::GetCurrentProcessId(), EQUAL)) {
- return false;
- }
- break;
- }
-
- case TargetPolicy::HANDLES_DUP_BROKER: {
- if (!duplicate_rule.AddNumberMatch(IF, HandleTarget::TARGET,
- ::GetCurrentProcessId(), EQUAL)) {
- return false;
- }
- break;
- }
-
- default:
- return false;
- }
- if (!duplicate_rule.AddStringMatch(IF, HandleTarget::NAME, type_name,
- CASE_INSENSITIVE)) {
- return false;
- }
- if (!policy->AddRule(IpcTag::DUPLICATEHANDLEPROXY, &duplicate_rule)) {
- return false;
- }
- return true;
-}
-
-DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result,
- HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options) {
- // The only action supported is ASK_BROKER which means duplicate the handle.
- if (ASK_BROKER != eval_result) {
- return ERROR_ACCESS_DENIED;
- }
-
- base::win::ScopedHandle remote_target_process;
- if (target_process_id != ::GetCurrentProcessId()) {
- // Sandboxed children are dynamic, so we check that manually.
- if (!BrokerServicesBase::GetInstance()->IsSafeDuplicationTarget(
- target_process_id)) {
- return ERROR_ACCESS_DENIED;
- }
-
- remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE,
- target_process_id));
- if (!remote_target_process.IsValid())
- return ::GetLastError();
- }
-
- // If the policy didn't block us and we have no valid target, then the broker
- // (this process) is the valid target.
- HANDLE target_process = remote_target_process.IsValid() ?
- remote_target_process.Get() : ::GetCurrentProcess();
- if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, target_process,
- target_handle, desired_access, FALSE,
- options)) {
- return ::GetLastError();
- }
-
- return ERROR_SUCCESS;
-}
-
-} // namespace sandbox
-
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.h b/security/sandbox/chromium/sandbox/win/src/handle_policy.h
deleted file mode 100644
index 29ce5ab666..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_policy.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2012 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_SRC_HANDLE_POLICY_H_
-#define SANDBOX_SRC_HANDLE_POLICY_H_
-
-#include <string>
-
-#include "sandbox/win/src/crosscall_server.h"
-#include "sandbox/win/src/policy_low_level.h"
-#include "sandbox/win/src/sandbox_policy.h"
-
-namespace sandbox {
-
-enum EvalResult;
-
-// This class centralizes most of the knowledge related to handle policy.
-class HandlePolicy {
- public:
- // Creates the required low-level policy rules to evaluate a high-level
- // policy rule for handles, in particular duplicate action.
- static bool GenerateRules(const wchar_t* type_name,
- TargetPolicy::Semantics semantics,
- LowLevelPolicy* policy);
-
- // Processes a 'TargetPolicy::DuplicateHandle()' request from the target.
- static DWORD DuplicateHandleProxyAction(EvalResult eval_result,
- HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options);
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_SRC_HANDLE_POLICY_H_
-
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc
deleted file mode 100644
index 11382da811..0000000000
--- a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2012 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 "base/strings/stringprintf.h"
-#include "sandbox/win/src/handle_policy.h"
-#include "sandbox/win/src/nt_internals.h"
-#include "sandbox/win/src/sandbox.h"
-#include "sandbox/win/src/sandbox_factory.h"
-#include "sandbox/win/src/sandbox_policy.h"
-#include "sandbox/win/src/win_utils.h"
-#include "sandbox/win/tests/common/controller.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace sandbox {
-
-// Just waits for the supplied number of milliseconds.
-SBOX_TESTS_COMMAND int Handle_WaitProcess(int argc, wchar_t **argv) {
- if (argc != 1)
- return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
- ::Sleep(::wcstoul(argv[0], NULL, 10));
- return SBOX_TEST_TIMED_OUT;
-}
-
-// Attempts to duplicate an event handle into the target process.
-SBOX_TESTS_COMMAND int Handle_DuplicateEvent(int argc, wchar_t **argv) {
- if (argc != 1)
- return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
- // Create a test event to use as a handle.
- base::win::ScopedHandle test_event;
- test_event.Set(::CreateEvent(NULL, TRUE, TRUE, NULL));
- if (!test_event.IsValid())
- return SBOX_TEST_FIRST_ERROR;
-
- // Get the target process ID.
- DWORD target_process_id = ::wcstoul(argv[0], NULL, 10);
-
- HANDLE handle = NULL;
- ResultCode result = SandboxFactory::GetTargetServices()->DuplicateHandle(
- test_event.Get(), target_process_id, &handle, 0, DUPLICATE_SAME_ACCESS);
-
- return (result == SBOX_ALL_OK) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
-}
-
-// Tests that duplicating an object works only when the policy allows it.
-TEST(HandlePolicyTest, DuplicateHandle) {
- TestRunner target;
- TestRunner runner;
-
- // Kick off an asynchronous target process for testing.
- target.SetAsynchronous(true);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000"));
-
- // First test that we fail to open the event.
- base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
- target.process_id());
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-
- // Now successfully open the event after adding a duplicate handle rule.
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
- TargetPolicy::HANDLES_DUP_ANY,
- L"Event"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
-}
-
-// Tests that duplicating an object works only when the policy allows it.
-TEST(HandlePolicyTest, DuplicatePeerHandle) {
- TestRunner target;
- TestRunner runner;
-
- // Kick off an asynchronous target process for testing.
- target.SetAsynchronous(true);
- target.SetUnsandboxed(true);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000"));
-
- // First test that we fail to open the event.
- base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
- target.process_id());
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-
- // Now successfully open the event after adding a duplicate handle rule.
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
- TargetPolicy::HANDLES_DUP_ANY,
- L"Event"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
-}
-
-// Tests that duplicating an object works only when the policy allows it.
-TEST(HandlePolicyTest, DuplicateBrokerHandle) {
- TestRunner runner;
-
- // First test that we fail to open the event.
- base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
- ::GetCurrentProcessId());
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-
- // Add the peer rule and make sure we fail again.
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
- TargetPolicy::HANDLES_DUP_ANY,
- L"Event"));
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
-
-
- // Now successfully open the event after adding a broker handle rule.
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
- TargetPolicy::HANDLES_DUP_BROKER,
- L"Event"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
-}
-
-} // namespace sandbox
-
diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
index ec6de4a66a..e655fc4b9a 100644
--- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
@@ -28,7 +28,6 @@ enum class IpcTag {
OPENEVENT,
NTCREATEKEY,
NTOPENKEY,
- DUPLICATEHANDLEPROXY,
GDI_GDIDLLINITIALIZE,
GDI_GETSTOCKOBJECT,
USER_REGISTERCLASSW,
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
index 858c350558..6133687f48 100644
--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
@@ -102,14 +102,6 @@ class BrokerServices {
// more information.
virtual ResultCode WaitForAllTargets() = 0;
- // Adds an unsandboxed process as a peer for policy decisions (e.g.
- // HANDLES_DUP_ANY policy).
- // Returns:
- // ALL_OK if successful. All other return values imply failure.
- // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
- // more information.
- virtual ResultCode AddTargetPeer(HANDLE peer_process) = 0;
-
// This call creates a snapshot of policies managed by the sandbox and
// returns them via a helper class.
// Parameters:
@@ -172,20 +164,6 @@ class TargetServices {
// LowerToken has been called or not.
virtual ProcessState* GetState() = 0;
- // Requests the broker to duplicate the supplied handle into the target
- // process. The target process must be an active sandbox child process
- // and the source process must have a corresponding policy allowing
- // handle duplication for this object type.
- // Returns:
- // ALL_OK if successful. All other return values imply failure.
- // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
- // more information.
- virtual ResultCode DuplicateHandle(HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options) = 0;
-
virtual ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
uint8_t* break_before) = 0;
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
index 75514ef595..10a29d6f3b 100644
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
@@ -30,7 +30,6 @@ class TargetPolicy {
SUBSYS_PROCESS, // Creation of child processes.
SUBSYS_REGISTRY, // Creation and opening of registry keys.
SUBSYS_SYNC, // Creation of named sync objects.
- SUBSYS_HANDLES, // Duplication of handles to other processes.
SUBSYS_WIN32K_LOCKDOWN, // Win32K Lockdown related policy.
SUBSYS_SIGNED_BINARY, // Signed binary policy.
SUBSYS_LINE_BREAK // Complex line break policy.
@@ -44,9 +43,6 @@ class TargetPolicy {
FILES_ALLOW_QUERY, // Allows access to query the attributes of a file.
FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics
// only.
- HANDLES_DUP_ANY, // Allows duplicating handles opened with any
- // access permissions.
- HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process.
NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe.
PROCESS_MIN_EXEC, // Allows to create a process with minimal rights
// over the resulting process and thread handles.
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
index f228dbbc31..0a23cb4470 100644
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -17,7 +17,6 @@
#include "base/win/windows_version.h"
#include "sandbox/win/src/acl.h"
#include "sandbox/win/src/filesystem_policy.h"
-#include "sandbox/win/src/handle_policy.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/line_break_policy.h"
@@ -775,14 +774,6 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
}
break;
}
- case SUBSYS_HANDLES: {
- if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
- NOTREACHED();
- return SBOX_ERROR_BAD_PARAMS;
- }
- break;
- }
-
case SUBSYS_WIN32K_LOCKDOWN: {
// Win32k intercept rules only supported on Windows 8 and above. This must
// match the version checks in process_mitigations.cc for consistency.
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
index a80e0106ef..7bd0e87aab 100644
--- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
@@ -12,7 +12,6 @@
#include "base/win/windows_version.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/handle_closer_agent.h"
-#include "sandbox/win/src/handle_interception.h"
#include "sandbox/win/src/heap_helper.h"
#include "sandbox/win/src/line_break_interception.h"
#include "sandbox/win/src/ipc_tags.h"
@@ -246,15 +245,6 @@ void ProcessState::SetCsrssConnected(bool csrss_connected) {
csrss_connected_ = csrss_connected;
}
-ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options) {
- return sandbox::DuplicateHandleProxy(source_handle, target_process_id,
- target_handle, desired_access, options);
-}
-
ResultCode TargetServicesBase::GetComplexLineBreaks(const WCHAR* text,
uint32_t length,
uint8_t* break_before) {
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h
index 1d70d4cd34..0231a250f3 100644
--- a/security/sandbox/chromium/sandbox/win/src/target_services.h
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.h
@@ -45,11 +45,6 @@ class TargetServicesBase : public TargetServices {
ResultCode Init() override;
void LowerToken() override;
ProcessState* GetState() override;
- ResultCode DuplicateHandle(HANDLE source_handle,
- DWORD target_process_id,
- HANDLE* target_handle,
- DWORD desired_access,
- DWORD options) override;
ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
uint8_t* break_before) final;
diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
index 3c8f8e25e5..7c072d5279 100644
--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
+++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/filesystem_dispatcher.h"
-#include "sandbox/win/src/handle_dispatcher.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/ipc_tags.h"
@@ -62,10 +61,6 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) {
ipc_targets_[static_cast<size_t>(IpcTag::NTOPENKEY)] = dispatcher;
registry_dispatcher_.reset(dispatcher);
- dispatcher = new HandleDispatcher(policy_);
- ipc_targets_[static_cast<size_t>(IpcTag::DUPLICATEHANDLEPROXY)] = dispatcher;
- handle_dispatcher_.reset(dispatcher);
-
dispatcher = new ProcessMitigationsWin32KDispatcher(policy_);
ipc_targets_[static_cast<size_t>(IpcTag::GDI_GDIDLLINITIALIZE)] = dispatcher;
ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETSTOCKOBJECT)] = dispatcher;
diff --git a/security/sandbox/common/SandboxSettings.cpp b/security/sandbox/common/SandboxSettings.cpp
index b0b24bf7d0..d44413da0b 100644
--- a/security/sandbox/common/SandboxSettings.cpp
+++ b/security/sandbox/common/SandboxSettings.cpp
@@ -104,10 +104,9 @@ nsIXULRuntime::ContentWin32kLockdownState GetContentWin32kLockdownState() {
static auto getLockdownState = [] {
auto state = GetWin32kLockdownState();
- const char* stateStr = ContentWin32kLockdownStateToString(state);
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationCString(
CrashReporter::Annotation::ContentSandboxWin32kState,
- nsDependentCString(stateStr));
+ ContentWin32kLockdownStateToString(state));
return state;
};
diff --git a/security/sandbox/linux/SandboxInfo.cpp b/security/sandbox/linux/SandboxInfo.cpp
index 3d71e55921..aefd9dac2d 100644
--- a/security/sandbox/linux/SandboxInfo.cpp
+++ b/security/sandbox/linux/SandboxInfo.cpp
@@ -134,11 +134,21 @@ static bool CanCreateUserNamespace() {
// the new capabilities (in this case, cloning another namespace) to
// detect AppArmor policies that allow CLONE_NEWUSER but don't allow
// doing anything useful with it.
- pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID,
- nullptr, nullptr, nullptr, nullptr);
+ //
+ // Bug 1884347: There's a new AppArmor feature which can result in
+ // unsharing NEWUSER and NEWPID (or NEWNET etc.) in one syscall
+ // being allowed, but further use of capabilities will be blocked
+ // afterwards. That may be a bug, but we need to handle it.
+ pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER, nullptr, nullptr,
+ nullptr, nullptr);
if (pid == 0) {
- // In the child. Do as little as possible.
- _exit(0);
+ // The exact meaning of `unshare(CLONE_NEWPID)` is slightly
+ // counterintuitive but in this case it doesn't matter. This just
+ // needs to be some operation that attempts to use capabilities,
+ // to check if it's blocked by an LSM.
+ int rv = unshare(CLONE_NEWPID);
+ // Exit with status 0 on success, 1 on failure.
+ _exit(rv == 0 ? 0 : 1);
}
if (pid == -1) {
// Failure.
@@ -149,11 +159,17 @@ static bool CanCreateUserNamespace() {
return false;
}
// Otherwise, in the parent and successful.
- bool waitpid_ok = HANDLE_EINTR(waitpid(pid, nullptr, 0)) == pid;
+ int wstatus;
+ bool waitpid_ok = HANDLE_EINTR(waitpid(pid, &wstatus, 0)) == pid;
MOZ_ASSERT(waitpid_ok);
if (!waitpid_ok) {
return false;
}
+ // Check for failures reported by the child process.
+ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
+ setenv(kCacheEnvName, "0", 1);
+ return false;
+ }
setenv(kCacheEnvName, "1", 1);
return true;
}
diff --git a/security/sandbox/linux/launch/SandboxLaunch.cpp b/security/sandbox/linux/launch/SandboxLaunch.cpp
index bec94f3c4c..6617ff475d 100644
--- a/security/sandbox/linux/launch/SandboxLaunch.cpp
+++ b/security/sandbox/linux/launch/SandboxLaunch.cpp
@@ -511,6 +511,8 @@ static pid_t ForkWithFlags(int aFlags) {
return ret;
}
+// Returns true for success, or returns false and sets errno on
+// failure. Intended only for procfs pseudo-files.
static bool WriteStringToFile(const char* aPath, const char* aStr,
const size_t aLen) {
int fd = open(aPath, O_WRONLY);
@@ -519,6 +521,11 @@ static bool WriteStringToFile(const char* aPath, const char* aStr,
}
ssize_t written = write(fd, aStr, aLen);
if (close(fd) != 0 || written != ssize_t(aLen)) {
+ // procfs shouldn't ever cause a short write, but ensure that
+ // errno is set to something distinctive if it does
+ if (written >= 0) {
+ errno = EMSGSIZE;
+ }
return false;
}
return true;
@@ -537,6 +544,7 @@ static void ConfigureUserNamespace(uid_t uid, gid_t gid) {
len = static_cast<size_t>(SafeSPrintf(buf, "%d %d 1", uid, uid));
MOZ_RELEASE_ASSERT(len < sizeof(buf));
if (!WriteStringToFile("/proc/self/uid_map", buf, len)) {
+ SANDBOX_LOG_ERRNO("writing /proc/self/uid_map");
MOZ_CRASH("Failed to write /proc/self/uid_map");
}
@@ -549,6 +557,7 @@ static void ConfigureUserNamespace(uid_t uid, gid_t gid) {
len = static_cast<size_t>(SafeSPrintf(buf, "%d %d 1", gid, gid));
MOZ_RELEASE_ASSERT(len < sizeof(buf));
if (!WriteStringToFile("/proc/self/gid_map", buf, len)) {
+ SANDBOX_LOG_ERRNO("writing /proc/self/gid_map");
MOZ_CRASH("Failed to write /proc/self/gid_map");
}
}
@@ -641,6 +650,9 @@ void SandboxLaunch::StartChrootServer() {
char msg;
ssize_t msgLen = HANDLE_EINTR(read(mChrootServer, &msg, 1));
+ if (msgLen < 0) {
+ SANDBOX_LOG_ERRNO("chroot server couldn't read request");
+ }
if (msgLen == 0) {
// Process exited before chrooting (or chose not to chroot?).
_exit(0);
@@ -653,7 +665,10 @@ void SandboxLaunch::StartChrootServer() {
// exits at the end of this function, and which is always
// unwriteable.
int rv = chroot("/proc/self/fdinfo");
- MOZ_RELEASE_ASSERT(rv == 0);
+ if (rv != 0) {
+ SANDBOX_LOG_ERRNO("chroot");
+ MOZ_CRASH("chroot failed");
+ }
// Drop CAP_SYS_CHROOT ASAP. This must happen before responding;
// the main child won't be able to waitpid(), so it could start
@@ -664,10 +679,16 @@ void SandboxLaunch::StartChrootServer() {
// remove that. (Note: if the process can obtain directory fds, for
// example via SandboxBroker, it must be blocked from using fchdir.)
rv = chdir("/");
- MOZ_RELEASE_ASSERT(rv == 0);
+ if (rv != 0) {
+ SANDBOX_LOG_ERRNO("chdir(\"/\")");
+ MOZ_CRASH("chdir(\"/\") failed");
+ }
msg = kSandboxChrootResponse;
msgLen = HANDLE_EINTR(write(mChrootServer, &msg, 1));
+ if (msgLen < 0) {
+ SANDBOX_LOG_ERRNO("chroot server couldn't send response");
+ }
MOZ_RELEASE_ASSERT(msgLen == 1);
_exit(0);
}
diff --git a/security/sandbox/mac/Sandbox.mm b/security/sandbox/mac/Sandbox.mm
index 2c9972a8fa..e4167a335a 100644
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -303,11 +303,13 @@ bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage) {
// Nothing to do here specifically
break;
+#ifdef MOZ_APPLEMEDIA
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA: {
profile.append(SandboxPolicyUtilityAudioDecoderAppleMediaAddend);
params.push_back("MAC_OS_VERSION");
params.push_back(combinedVersion.c_str());
} break;
+#endif
default:
MOZ_ASSERT(false, "Invalid SandboxingKind");
diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build
index 806af7e58b..468573f220 100644
--- a/security/sandbox/moz.build
+++ b/security/sandbox/moz.build
@@ -113,9 +113,6 @@ elif CONFIG["OS_ARCH"] == "WINNT":
"chromium/sandbox/win/src/filesystem_policy.cc",
"chromium/sandbox/win/src/handle_closer.cc",
"chromium/sandbox/win/src/handle_closer_agent.cc",
- "chromium/sandbox/win/src/handle_dispatcher.cc",
- "chromium/sandbox/win/src/handle_interception.cc",
- "chromium/sandbox/win/src/handle_policy.cc",
"chromium/sandbox/win/src/heap_helper.cc",
"chromium/sandbox/win/src/interception.cc",
"chromium/sandbox/win/src/interception_agent.cc",
diff --git a/security/sandbox/test/browser_content_sandbox_fs_snap.js b/security/sandbox/test/browser_content_sandbox_fs_snap.js
index a8b26a1e31..06f04c1d33 100644
--- a/security/sandbox/test/browser_content_sandbox_fs_snap.js
+++ b/security/sandbox/test/browser_content_sandbox_fs_snap.js
@@ -18,7 +18,7 @@ Services.scriptloader.loadSubScript(
add_task(async function () {
// Ensure that SNAP is there
const snap = Services.env.get("SNAP");
- ok(snap.length > 1, "SNAP is defined");
+ Assert.greater(snap.length, 1, "SNAP is defined");
// If it is there, do actual testing
sanityChecks();
diff --git a/security/sandbox/test/browser_content_sandbox_fs_xdg.js b/security/sandbox/test/browser_content_sandbox_fs_xdg.js
index f5150fc329..34dee9d1a0 100644
--- a/security/sandbox/test/browser_content_sandbox_fs_xdg.js
+++ b/security/sandbox/test/browser_content_sandbox_fs_xdg.js
@@ -18,7 +18,7 @@ Services.scriptloader.loadSubScript(
add_task(async function () {
// Ensure that XDG_CONFIG_HOME is there
const xdgConfigHome = Services.env.get("XDG_CONFIG_HOME");
- ok(xdgConfigHome.length > 1, "XDG_CONFIG_HOME is defined");
+ Assert.greater(xdgConfigHome.length, 1, "XDG_CONFIG_HOME is defined");
// If it is there, do actual testing
sanityChecks();
diff --git a/security/sandbox/test/browser_content_sandbox_syscalls.js b/security/sandbox/test/browser_content_sandbox_syscalls.js
index dab47cf356..71d3c7ad12 100644
--- a/security/sandbox/test/browser_content_sandbox_syscalls.js
+++ b/security/sandbox/test/browser_content_sandbox_syscalls.js
@@ -262,7 +262,7 @@ add_task(async function () {
}
info(`security.sandbox.content.level=${level}`);
- ok(level > 0, "content sandbox is enabled.");
+ Assert.greater(level, 0, "content sandbox is enabled.");
let areSyscallsSandboxed = areContentSyscallsSandboxed(level);
@@ -282,7 +282,7 @@ add_task(async function () {
// exec something harmless, this should fail
let cmd = getOSExecCmd();
let rv = await SpecialPowers.spawn(browser, [{ lib, cmd }], callExec);
- ok(rv == -1, `exec(${cmd}) is not permitted`);
+ Assert.equal(rv, -1, `exec(${cmd}) is not permitted`);
}
// use open syscall
@@ -295,7 +295,7 @@ add_task(async function () {
[{ lib, path, flags }],
callOpen
);
- ok(fd < 0, "opening a file for writing in home is not permitted");
+ Assert.less(fd, 0, "opening a file for writing in home is not permitted");
}
// use open syscall
@@ -311,19 +311,24 @@ add_task(async function () {
callOpen
);
if (isMac()) {
- ok(
- fd === -1,
+ Assert.strictEqual(
+ fd,
+ -1,
"opening a file for writing in content temp is not permitted"
);
} else {
- ok(fd >= 0, "opening a file for writing in content temp is permitted");
+ Assert.greaterOrEqual(
+ fd,
+ 0,
+ "opening a file for writing in content temp is permitted"
+ );
}
}
// use fork syscall
if (isLinux() || isMac()) {
let rv = await SpecialPowers.spawn(browser, [{ lib }], callFork);
- ok(rv == -1, "calling fork is not permitted");
+ Assert.equal(rv, -1, "calling fork is not permitted");
}
// On macOS before 10.10 the |sysctl-name| predicate didn't exist for
@@ -336,21 +341,21 @@ add_task(async function () {
[{ lib, name: "kern.boottime" }],
callSysctl
);
- ok(rv == -1, "calling sysctl('kern.boottime') is not permitted");
+ Assert.equal(rv, -1, "calling sysctl('kern.boottime') is not permitted");
rv = await SpecialPowers.spawn(
browser,
[{ lib, name: "net.inet.ip.ttl" }],
callSysctl
);
- ok(rv == -1, "calling sysctl('net.inet.ip.ttl') is not permitted");
+ Assert.equal(rv, -1, "calling sysctl('net.inet.ip.ttl') is not permitted");
rv = await SpecialPowers.spawn(
browser,
[{ lib, name: "hw.ncpu" }],
callSysctl
);
- ok(rv == 0, "calling sysctl('hw.ncpu') is permitted");
+ Assert.equal(rv, 0, "calling sysctl('hw.ncpu') is permitted");
}
if (isLinux()) {
@@ -359,7 +364,11 @@ add_task(async function () {
// verify we block PR_CAPBSET_READ with EINVAL
let option = lazy.LIBC.PR_CAPBSET_READ;
let rv = await SpecialPowers.spawn(browser, [{ lib, option }], callPrctl);
- ok(rv === lazy.LIBC.EINVAL, "prctl(PR_CAPBSET_READ) is blocked");
+ Assert.strictEqual(
+ rv,
+ lazy.LIBC.EINVAL,
+ "prctl(PR_CAPBSET_READ) is blocked"
+ );
const kernelVersion = await getKernelVersion();
const glibcVersion = getGlibcVersion();
@@ -375,8 +384,9 @@ add_task(async function () {
[{ lib, dirfd, path, mode, flag: 0x01 }],
callFaccessat2
);
- ok(
- rv === lazy.LIBC.ENOSYS,
+ Assert.strictEqual(
+ rv,
+ lazy.LIBC.ENOSYS,
"faccessat2 (flag=0x01) was blocked with ENOSYS"
);
@@ -385,8 +395,9 @@ add_task(async function () {
[{ lib, dirfd, path, mode, flag: lazy.LIBC.AT_EACCESS }],
callFaccessat2
);
- ok(
- rv === lazy.LIBC.EACCES,
+ Assert.strictEqual(
+ rv,
+ lazy.LIBC.EACCES,
"faccessat2 (flag=0x200) was allowed, errno=EACCES"
);
} else {
diff --git a/security/sandbox/test/browser_content_sandbox_utils.js b/security/sandbox/test/browser_content_sandbox_utils.js
index ce6ed39ff6..9b4c4af70a 100644
--- a/security/sandbox/test/browser_content_sandbox_utils.js
+++ b/security/sandbox/test/browser_content_sandbox_utils.js
@@ -33,7 +33,7 @@ function sanityChecks() {
}
info(`security.sandbox.content.level=${level}`);
- ok(level > 0, "content sandbox is enabled.");
+ Assert.greater(level, 0, "content sandbox is enabled.");
let isFileIOSandboxed = isContentFileIOSandboxed(level);
@@ -234,7 +234,7 @@ function isContentFileIOSandboxed(level) {
// Returns the lowest sandbox level where blanket reading of the profile
// directory from the content process should be blocked by the sandbox.
-function minProfileReadSandboxLevel(level) {
+function minProfileReadSandboxLevel() {
switch (Services.appinfo.OS) {
case "WINNT":
return 3;
@@ -250,7 +250,7 @@ function minProfileReadSandboxLevel(level) {
// Returns the lowest sandbox level where blanket reading of the home
// directory from the content process should be blocked by the sandbox.
-function minHomeReadSandboxLevel(level) {
+function minHomeReadSandboxLevel() {
switch (Services.appinfo.OS) {
case "WINNT":
return 3;
@@ -391,8 +391,9 @@ function GetBrowserType(type) {
}
browserType = GetBrowserType[type];
- ok(
- browserType.remoteType === type,
+ Assert.strictEqual(
+ browserType.remoteType,
+ type,
`GetBrowserType(${type}) returns a ${type} process`
);
return browserType;
@@ -445,8 +446,9 @@ async function runTestsList(tests) {
test.func
);
- ok(
- result.ok == test.ok,
+ Assert.equal(
+ result.ok,
+ test.ok,
`reading ${test.desc} from a ${processType} process ` +
`is ${okString} (${test.file.path})`
);
@@ -454,7 +456,11 @@ async function runTestsList(tests) {
// if the directory is not expected to be readable,
// ensure the listing has zero entries
if (test.func === readDir && !test.ok) {
- ok(result.numEntries == 0, `directory list is empty (${test.file.path})`);
+ Assert.equal(
+ result.numEntries,
+ 0,
+ `directory list is empty (${test.file.path})`
+ );
}
if (test.cleanup != undefined) {
diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
index 9b9ed97262..3e2ce617bd 100644
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -30,7 +30,6 @@
#include "mozilla/Telemetry.h"
#include "mozilla/WinDllServices.h"
#include "mozilla/WindowsVersion.h"
-#include "mozilla/WinHeaderOnlyUtils.h"
#include "mozilla/ipc/LaunchError.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsCOMPtr.h"
@@ -116,11 +115,27 @@ static sandbox::ResultCode AddWin32kLockdownPolicy(
return result;
}
+static void CacheDirAndAutoClear(const nsAString& aDir,
+ StaticAutoPtr<nsString>* cacheVar) {
+ *cacheVar = new nsString(aDir);
+ ClearOnShutdown(cacheVar);
+
+ // Convert network share path to format for sandbox policy.
+ if (Substring(**cacheVar, 0, 2).Equals(u"\\\\"_ns)) {
+ (*cacheVar)->InsertLiteral(u"??\\UNC", 1);
+ }
+}
+
/* static */
-void SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices) {
+void SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices,
+ const nsAString& aBinDir) {
sBrokerService = aBrokerServices;
sRunningFromNetworkDrive = widget::WinUtils::RunningFromANetworkDrive();
+
+ if (!aBinDir.IsEmpty()) {
+ CacheDirAndAutoClear(aBinDir, &sBinDir);
+ }
}
static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey,
@@ -135,14 +150,9 @@ static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey,
return;
}
- *cacheVar = new nsString();
- ClearOnShutdown(cacheVar);
- MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(**cacheVar));
-
- // Convert network share path to format for sandbox policy.
- if (Substring(**cacheVar, 0, 2).Equals(u"\\\\"_ns)) {
- (*cacheVar)->InsertLiteral(u"??\\UNC", 1);
- }
+ nsAutoString dirPath;
+ MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(dirPath));
+ CacheDirAndAutoClear(dirPath, cacheVar);
}
/* static */
@@ -166,7 +176,6 @@ void SandboxBroker::GeckoDependentInitialize() {
return;
}
- CacheDirAndAutoClear(dirSvc, NS_GRE_DIR, &sBinDir);
CacheDirAndAutoClear(dirSvc, NS_APP_USER_PROFILE_50_DIR, &sProfileDir);
CacheDirAndAutoClear(dirSvc, NS_WIN_LOCAL_APPDATA_DIR, &sLocalAppDataDir);
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
@@ -481,33 +490,11 @@ static sandbox::ResultCode AllowProxyLoadFromBinDir(
sandbox::TargetPolicy* aPolicy) {
// Allow modules in the directory containing the executable such as
// mozglue.dll, nss3.dll, etc.
- static UniquePtr<nsString> sInstallDir;
- if (!sInstallDir) {
- // Since this function can be called before sBinDir is initialized,
- // we cache the install path by ourselves.
- UniquePtr<wchar_t[]> appDirStr;
- if (GetInstallDirectory(appDirStr)) {
- sInstallDir = MakeUnique<nsString>(appDirStr.get());
- sInstallDir->Append(u"\\*");
-
- auto setClearOnShutdown = [ptr = &sInstallDir]() -> void {
- ClearOnShutdown(ptr);
- };
- if (NS_IsMainThread()) {
- setClearOnShutdown();
- } else {
- SchedulerGroup::Dispatch(NS_NewRunnableFunction(
- "InitSignedPolicyRulesToBypassCig", std::move(setClearOnShutdown)));
- }
- }
-
- if (!sInstallDir) {
- return sandbox::SBOX_ERROR_GENERIC;
- }
- }
+ nsAutoString rulePath(*sBinDir);
+ rulePath.Append(u"\\*"_ns);
return aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
- sInstallDir->get());
+ rulePath.get());
}
static sandbox::ResultCode AddCigToPolicy(
@@ -1084,6 +1071,10 @@ void SandboxBroker::SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) {
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*"));
+ // Add rule to allow read access to installation directory.
+ AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_READONLY,
+ sBinDir, u"\\*"_ns);
+
// The GPU process needs to write to a shader cache for performance reasons
if (sProfileDir) {
AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
@@ -1833,8 +1824,6 @@ void SandboxBroker::ApplyLoggingPolicy() {
L"HKEY_CURRENT_USER\\dummy");
mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SYNC,
sandbox::TargetPolicy::EVENTS_ALLOW_READONLY, L"dummy");
- mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
- sandbox::TargetPolicy::HANDLES_DUP_BROKER, L"dummy");
}
SandboxBroker::~SandboxBroker() {
diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
index 45a0cbb38b..40b3cf1501 100644
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
@@ -75,7 +75,8 @@ class SandboxBroker : public AbstractSandboxBroker {
public:
SandboxBroker();
- static void Initialize(sandbox::BrokerServices* aBrokerServices);
+ static void Initialize(sandbox::BrokerServices* aBrokerServices,
+ const nsAString& aBinDir);
static void EnsureLpacPermsissionsOnDir(const nsString& aDir);