Source code

Revision control

Copy as Markdown

Other Tools

# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1584045580 0
# Thu Mar 12 20:39:40 2020 +0000
# Node ID c996dbc3e3663fb372feb8e171562e86b09583b6
# Parent f96efa1d9f5c676c0ee8fd80044a494258eff3d3
Bug 1557282 Part 1: Take chromium commit c1ce57ea5d31208af589b4839390a44ab20b0c8f. r=handyman,gcp
This adds AddRestrictingRandomSid feature, which fixes our issues with
SetLockdownDefaultDacl, apart from when we are running from a network drive.
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token.cc
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token.cc
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token.cc
@@ -141,16 +141,24 @@ DWORD RestrictedToken::GetRestrictedToke
} else {
// Modify the default dacl on the token to contain Restricted.
if (!AddSidToDefaultDacl(new_token.Get(), WinRestrictedCodeSid,
GRANT_ACCESS, GENERIC_ALL)) {
return ::GetLastError();
}
}
+ for (const auto& default_dacl_sid : sids_for_default_dacl_) {
+ if (!AddSidToDefaultDacl(new_token.Get(), std::get<0>(default_dacl_sid),
+ std::get<1>(default_dacl_sid),
+ std::get<2>(default_dacl_sid))) {
+ return ::GetLastError();
+ }
+ }
+
// Add user to default dacl.
if (!AddUserSidToDefaultDacl(new_token.Get(), GENERIC_ALL))
return ::GetLastError();
DWORD error = SetTokenIntegrityLevel(new_token.Get(), integrity_level_);
if (ERROR_SUCCESS != error)
return error;
@@ -405,9 +413,20 @@ DWORD RestrictedToken::SetIntegrityLevel
integrity_level_ = integrity_level;
return ERROR_SUCCESS;
}
void RestrictedToken::SetLockdownDefaultDacl() {
lockdown_default_dacl_ = true;
}
+DWORD RestrictedToken::AddDefaultDaclSid(const Sid& sid,
+ ACCESS_MODE access_mode,
+ ACCESS_MASK access) {
+ DCHECK(init_);
+ if (!init_)
+ return ERROR_NO_TOKEN;
+
+ sids_for_default_dacl_.push_back(std::make_tuple(sid, access_mode, access));
+ return ERROR_SUCCESS;
+}
+
} // namespace sandbox
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token.h b/security/sandbox/chromium/sandbox/win/src/restricted_token.h
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token.h
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token.h
@@ -2,16 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_SRC_RESTRICTED_TOKEN_H_
#define SANDBOX_SRC_RESTRICTED_TOKEN_H_
#include <windows.h>
+#include <tuple>
#include <vector>
#include <string>
#include "base/macros.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/security_level.h"
@@ -169,23 +170,31 @@ class RestrictedToken {
// Sets the token integrity level. This is only valid on Vista. The integrity
// level cannot be higher than your current integrity level.
DWORD SetIntegrityLevel(IntegrityLevel integrity_level);
// Set a flag which indicates the created token should have a locked down
// default DACL when created.
void SetLockdownDefaultDacl();
+ // Add a SID to the default DACL. These SIDs are added regardless of the
+ // SetLockdownDefaultDacl state.
+ DWORD AddDefaultDaclSid(const Sid& sid,
+ ACCESS_MODE access_mode,
+ ACCESS_MASK access);
+
private:
// The list of restricting sids in the restricted token.
std::vector<Sid> sids_to_restrict_;
// The list of privileges to remove in the restricted token.
std::vector<LUID> privileges_to_disable_;
// The list of sids to mark as Deny Only in the restricted token.
std::vector<Sid> sids_for_deny_only_;
+ // The list of sids to add to the default DACL of the restricted token.
+ std::vector<std::tuple<Sid, ACCESS_MODE, ACCESS_MASK>> sids_for_default_dacl_;
// The token to restrict. Can only be set in a constructor.
base::win::ScopedHandle effective_token_;
// The token integrity level. Only valid on Vista.
IntegrityLevel integrity_level_;
// Tells if the object is initialized or not (if Init() has been called)
bool init_;
// Lockdown the default DACL when creating new tokens.
bool lockdown_default_dacl_;
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
@@ -51,22 +51,29 @@ DWORD GetObjectSecurityDescriptor(HANDLE
} // namespace
DWORD CreateRestrictedToken(HANDLE effective_token,
TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
bool lockdown_default_dacl,
+ PSID unique_restricted_sid,
bool use_restricting_sids,
base::win::ScopedHandle* token) {
RestrictedToken restricted_token;
restricted_token.Init(effective_token);
if (lockdown_default_dacl)
restricted_token.SetLockdownDefaultDacl();
+ if (unique_restricted_sid) {
+ restricted_token.AddDefaultDaclSid(Sid(unique_restricted_sid), GRANT_ACCESS,
+ GENERIC_ALL);
+ restricted_token.AddDefaultDaclSid(Sid(WinCreatorOwnerRightsSid),
+ GRANT_ACCESS, READ_CONTROL);
+ }
std::vector<std::wstring> privilege_exceptions;
std::vector<Sid> sid_exceptions;
bool deny_sids = true;
bool remove_privileges = true;
switch (security_level) {
@@ -118,50 +125,60 @@ DWORD CreateRestrictedToken(HANDLE effec
sid_exceptions.push_back(WinAuthenticatedUserSid);
privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
restricted_token.AddRestrictingSid(WinWorldSid);
restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
restricted_token.AddRestrictingSidCurrentUser();
restricted_token.AddRestrictingSidLogonSession();
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
}
break;
}
case USER_LIMITED: {
sid_exceptions.push_back(WinBuiltinUsersSid);
sid_exceptions.push_back(WinWorldSid);
sid_exceptions.push_back(WinInteractiveSid);
privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
restricted_token.AddRestrictingSid(WinWorldSid);
restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
// This token has to be able to create objects in BNO.
// Unfortunately, on Vista+, it needs the current logon sid
// in the token to achieve this. You should also set the process to be
// low integrity level so it can't access object created by other
// processes.
restricted_token.AddRestrictingSidLogonSession();
+ } else {
+ restricted_token.AddUserSidForDenyOnly();
}
break;
}
case USER_RESTRICTED: {
privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
restricted_token.AddUserSidForDenyOnly();
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
}
break;
}
case USER_LOCKDOWN: {
restricted_token.AddUserSidForDenyOnly();
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinNullSid);
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
}
break;
}
default: { return ERROR_BAD_ARGUMENTS; }
}
DWORD err_code = ERROR_SUCCESS;
if (deny_sids) {
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
@@ -33,16 +33,17 @@ enum TokenType { IMPERSONATION = 0, PRIM
// If the function succeeds, the return value is ERROR_SUCCESS. If the
// function fails, the return value is the win32 error code corresponding to
// the error.
DWORD CreateRestrictedToken(HANDLE effective_token,
TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
bool lockdown_default_dacl,
+ PSID unique_restricted_sid,
bool use_restricting_sids,
base::win::ScopedHandle* token);
// Sets the integrity label on a object handle.
DWORD SetObjectIntegrityLabel(HANDLE handle,
SE_OBJECT_TYPE type,
const wchar_t* ace_access,
const wchar_t* integrity_level_sid);
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
@@ -256,16 +256,20 @@ class TargetPolicy {
// ownership of the handle.
virtual void AddHandleToShare(HANDLE handle) = 0;
// Locks down the default DACL of the created lockdown and initial tokens
// to restrict what other processes are allowed to access a process' kernel
// resources.
virtual void SetLockdownDefaultDacl() = 0;
+ // Adds a restricting random SID to the restricted SIDs list as well as
+ // the default DACL.
+ virtual void AddRestrictingRandomSid() = 0;
+
// Enable OPM API redirection when in Win32k lockdown.
virtual void SetEnableOPMRedirection() = 0;
// Enable OPM API emulation when in Win32k lockdown.
virtual bool GetEnableOPMRedirection() = 0;
// Configure policy to use an AppContainer profile. |package_name| is the
// name of the profile to use. Specifying True for |create_profile| ensures
// the profile exists, if set to False process creation will fail if the
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
@@ -105,16 +105,17 @@ PolicyBase::PolicyBase()
delayed_integrity_level_(INTEGRITY_LEVEL_LAST),
mitigations_(0),
delayed_mitigations_(0),
is_csrss_connected_(true),
policy_maker_(nullptr),
policy_(nullptr),
lowbox_sid_(nullptr),
lockdown_default_dacl_(false),
+ add_restricting_random_sid_(false),
enable_opm_redirection_(false),
effective_token_(nullptr) {
::InitializeCriticalSection(&lock_);
dispatcher_.reset(new TopLevelDispatcher(this));
}
PolicyBase::~PolicyBase() {
TargetSet::iterator it;
@@ -389,16 +390,20 @@ void PolicyBase::AddHandleToShare(HANDLE
handles_to_share_.push_back(handle);
}
void PolicyBase::SetLockdownDefaultDacl() {
lockdown_default_dacl_ = true;
}
+void PolicyBase::AddRestrictingRandomSid() {
+ add_restricting_random_sid_ = true;
+}
+
const base::HandlesToInheritVector& PolicyBase::GetHandlesBeingShared() {
return handles_to_share_;
}
ResultCode PolicyBase::MakeJobObject(base::win::ScopedHandle* job) {
if (job_level_ == JOB_NONE) {
job->Close();
return SBOX_ALL_OK;
@@ -413,22 +418,26 @@ ResultCode PolicyBase::MakeJobObject(bas
*job = job_obj.Take();
return SBOX_ALL_OK;
}
ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial,
base::win::ScopedHandle* lockdown,
base::win::ScopedHandle* lowbox) {
+ Sid random_sid = Sid::GenerateRandomSid();
+ PSID random_sid_ptr = nullptr;
+ if (add_restricting_random_sid_)
+ random_sid_ptr = random_sid.GetPSID();
+
// Create the 'naked' token. This will be the permanent token associated
// with the process and therefore with any thread that is not impersonating.
- DWORD result =
- CreateRestrictedToken(effective_token_, lockdown_level_, integrity_level_,
- PRIMARY, lockdown_default_dacl_,
- use_restricting_sids_, lockdown);
+ DWORD result = CreateRestrictedToken(
+ effective_token_, lockdown_level_, integrity_level_, PRIMARY,
+ lockdown_default_dacl_, random_sid_ptr, use_restricting_sids_, lockdown);
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN;
// If we're launching on the alternate desktop we need to make sure the
// integrity label on the object is no higher than the sandboxed process's
// integrity level. So, we lower the label on the desktop process if it's
// not already low enough for our process.
if (use_alternate_desktop_ && integrity_level_ != INTEGRITY_LEVEL_LAST) {
@@ -485,20 +494,19 @@ ResultCode PolicyBase::MakeTokens(base::
TOKEN_ALL_ACCESS)) {
return SBOX_ERROR_CANNOT_MODIFY_LOWBOX_TOKEN_DACL;
}
}
// Create the 'better' token. We use this token as the one that the main
// thread uses when booting up the process. It should contain most of
// what we need (before reaching main( ))
- result =
- CreateRestrictedToken(effective_token_, initial_level_, integrity_level_,
- IMPERSONATION, lockdown_default_dacl_,
- use_restricting_sids_, initial);
+ result = CreateRestrictedToken(
+ effective_token_, initial_level_, integrity_level_, IMPERSONATION,
+ lockdown_default_dacl_, random_sid_ptr, use_restricting_sids_, initial);
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN;
return SBOX_ALL_OK;
}
PSID PolicyBase::GetLowBoxSid() const {
return lowbox_sid_;
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
@@ -69,16 +69,17 @@ class PolicyBase final : public TargetPo
ResultCode AddRule(SubSystem subsystem,
Semantics semantics,
const wchar_t* pattern) override;
ResultCode AddDllToUnload(const wchar_t* dll_name) override;
ResultCode AddKernelObjectToClose(const wchar_t* handle_type,
const wchar_t* handle_name) override;
void AddHandleToShare(HANDLE handle) override;
void SetLockdownDefaultDacl() override;
+ void AddRestrictingRandomSid() override;
void SetEnableOPMRedirection() override;
bool GetEnableOPMRedirection() override;
ResultCode AddAppContainerProfile(const wchar_t* package_name,
bool create_profile) override;
scoped_refptr<AppContainerProfile> GetAppContainerProfile() override;
void SetEffectiveToken(HANDLE token) override;
// Get the AppContainer profile as its internal type.
@@ -165,16 +166,17 @@ class PolicyBase final : public TargetPo
// This is a map of handle-types to names that we need to close in the
// target process. A null set means we need to close all handles of the
// given type.
HandleCloser handle_closer_;
PSID lowbox_sid_;
base::win::ScopedHandle lowbox_directory_;
std::unique_ptr<Dispatcher> dispatcher_;
bool lockdown_default_dacl_;
+ bool add_restricting_random_sid_;
static HDESK alternate_desktop_handle_;
static HWINSTA alternate_winstation_handle_;
static HDESK alternate_desktop_local_winstation_handle_;
static IntegrityLevel alternate_desktop_integrity_level_label_;
static IntegrityLevel
alternate_desktop_local_winstation_integrity_level_label_;
diff --git a/security/sandbox/chromium/sandbox/win/src/sid.cc b/security/sandbox/chromium/sandbox/win/src/sid.cc
--- a/security/sandbox/chromium/sandbox/win/src/sid.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sid.cc
@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/sid.h"
#include <memory>
#include <sddl.h>
+#include <stdlib.h>
#include "base/logging.h"
+#include "base/rand_util.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/win_utils.h"
namespace sandbox {
namespace {
DWORD WellKnownCapabilityToRid(WellKnownCapabilities capability) {
@@ -127,16 +129,24 @@ Sid Sid::FromSubAuthorities(PSID_IDENTIF
Sid Sid::AllRestrictedApplicationPackages() {
SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_APP_PACKAGE_AUTHORITY};
DWORD sub_authorities[] = {SECURITY_APP_PACKAGE_BASE_RID,
SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE};
return FromSubAuthorities(&package_authority, 2, sub_authorities);
}
+Sid Sid::GenerateRandomSid() {
+ SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_NULL_SID_AUTHORITY};
+ DWORD sub_authorities[4] = {};
+ base::RandBytes(&sub_authorities, sizeof(sub_authorities));
+ return FromSubAuthorities(&package_authority, _countof(sub_authorities),
+ sub_authorities);
+}
+
PSID Sid::GetPSID() const {
return const_cast<BYTE*>(sid_);
}
bool Sid::IsValid() const {
return !!::IsValidSid(GetPSID());
}
diff --git a/security/sandbox/chromium/sandbox/win/src/sid.h b/security/sandbox/chromium/sandbox/win/src/sid.h
--- a/security/sandbox/chromium/sandbox/win/src/sid.h
+++ b/security/sandbox/chromium/sandbox/win/src/sid.h
@@ -47,16 +47,18 @@ class Sid {
// Create a Sid from a SDDL format string, such as S-1-1-0.
static Sid FromSddlString(const wchar_t* sddl_sid);
// Create a Sid from a set of sub authorities.
static Sid FromSubAuthorities(PSID_IDENTIFIER_AUTHORITY identifier_authority,
BYTE sub_authority_count,
PDWORD sub_authorities);
// Create the restricted all application packages sid.
static Sid AllRestrictedApplicationPackages();
+ // Generate a random SID value.
+ static Sid GenerateRandomSid();
// Returns sid_.
PSID GetPSID() const;
// Gets whether the sid is valid.
bool IsValid() const;
// Converts the SID to a SDDL format string.