Source code

Revision control

Copy as Markdown

Other Tools

# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1499762660 -3600
# Tue Jul 11 09:44:20 2017 +0100
# Node ID 4fb5bb81a2626a6262813bb556e2e059c2323562
# Parent 45f3ef4037e040c820c0dd8eec6cff9d0745ae41
Bug 1366701 - Add option to Windows chromium sandbox policy to not use restricting SIDs. r=jimm
This originally landed in changeset:
diff --git a/sandbox/win/src/restricted_token_utils.cc b/sandbox/win/src/restricted_token_utils.cc
--- a/sandbox/win/src/restricted_token_utils.cc
+++ b/sandbox/win/src/restricted_token_utils.cc
@@ -29,17 +29,18 @@ DWORD GetObjectSecurityDescriptor(HANDLE
} // namespace
absl::optional<base::win::AccessToken> CreateRestrictedToken(
TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
bool lockdown_default_dacl,
- const absl::optional<base::win::Sid>& unique_restricted_sid) {
+ const absl::optional<base::win::Sid>& unique_restricted_sid,
+ bool use_restricting_sids) {
RestrictedToken restricted_token;
if (lockdown_default_dacl) {
restricted_token.SetLockdownDefaultDacl();
}
if (unique_restricted_sid) {
restricted_token.AddDefaultDaclSid(*unique_restricted_sid,
base::win::SecurityAccessMode::kGrant,
GENERIC_ALL);
@@ -58,82 +59,100 @@ DWORD CreateRestrictedToken(HANDLE effec
switch (security_level) {
case USER_UNPROTECTED:
deny_sids = false;
remove_privileges = false;
break;
case USER_RESTRICTED_SAME_ACCESS:
deny_sids = false;
remove_privileges = false;
- restricted_token.AddRestrictingSidAllSids();
+ if (use_restricting_sids) {
+ restricted_token.AddRestrictingSidAllSids();
+ }
break;
case USER_RESTRICTED_NON_ADMIN:
AddSidException(sid_exceptions, base::win::WellKnownSid::kBuiltinUsers);
AddSidException(sid_exceptions, base::win::WellKnownSid::kWorld);
AddSidException(sid_exceptions, base::win::WellKnownSid::kInteractive);
AddSidException(sid_exceptions,
base::win::WellKnownSid::kAuthenticatedUser);
- restricted_token.AddRestrictingSid(
- base::win::WellKnownSid::kBuiltinUsers);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kInteractive);
- restricted_token.AddRestrictingSid(
- base::win::WellKnownSid::kAuthenticatedUser);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted);
- restricted_token.AddRestrictingSidCurrentUser();
- restricted_token.AddRestrictingSidLogonSession();
- if (unique_restricted_sid) {
- restricted_token.AddRestrictingSid(*unique_restricted_sid);
- }
+ if (use_restricting_sids) {
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kBuiltinUsers);
+ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kInteractive);
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kAuthenticatedUser);
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kRestricted);
+ restricted_token.AddRestrictingSidCurrentUser();
+ restricted_token.AddRestrictingSidLogonSession();
+ if (unique_restricted_sid) {
+ restricted_token.AddRestrictingSid(*unique_restricted_sid);
+ }
+ }
break;
case USER_INTERACTIVE:
AddSidException(sid_exceptions, base::win::WellKnownSid::kBuiltinUsers);
AddSidException(sid_exceptions, base::win::WellKnownSid::kWorld);
AddSidException(sid_exceptions, base::win::WellKnownSid::kInteractive);
AddSidException(sid_exceptions,
base::win::WellKnownSid::kAuthenticatedUser);
- restricted_token.AddRestrictingSid(
- base::win::WellKnownSid::kBuiltinUsers);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted);
- restricted_token.AddRestrictingSidCurrentUser();
- restricted_token.AddRestrictingSidLogonSession();
- if (unique_restricted_sid) {
- restricted_token.AddRestrictingSid(*unique_restricted_sid);
- }
+ if (use_restricting_sids) {
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kBuiltinUsers);
+ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kRestricted);
+ restricted_token.AddRestrictingSidCurrentUser();
+ restricted_token.AddRestrictingSidLogonSession();
+ if (unique_restricted_sid) {
+ restricted_token.AddRestrictingSid(*unique_restricted_sid);
+ }
+ }
break;
case USER_LIMITED:
AddSidException(sid_exceptions, base::win::WellKnownSid::kBuiltinUsers);
AddSidException(sid_exceptions, base::win::WellKnownSid::kWorld);
AddSidException(sid_exceptions, base::win::WellKnownSid::kInteractive);
- restricted_token.AddRestrictingSid(
- base::win::WellKnownSid::kBuiltinUsers);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted);
- if (unique_restricted_sid) {
- restricted_token.AddRestrictingSid(*unique_restricted_sid);
- }
- // This token has to be able to create objects in BNO, 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();
+ if (use_restricting_sids) {
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kBuiltinUsers);
+ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
+ restricted_token.AddRestrictingSid(
+ base::win::WellKnownSid::kRestricted);
+ if (unique_restricted_sid) {
+ restricted_token.AddRestrictingSid(*unique_restricted_sid);
+ }
+ // This token has to be able to create objects in BNO, 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:
restricted_token.AddUserSidForDenyOnly();
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted);
- if (unique_restricted_sid) {
- restricted_token.AddRestrictingSid(*unique_restricted_sid);
- }
+ if (use_restricting_sids) {
+ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted);
+ if (unique_restricted_sid) {
+ restricted_token.AddRestrictingSid(*unique_restricted_sid);
+ }
+ }
break;
case USER_LOCKDOWN:
remove_traverse_privilege = true;
restricted_token.AddUserSidForDenyOnly();
- restricted_token.AddRestrictingSid(base::win::WellKnownSid::kNull);
- if (unique_restricted_sid) {
- restricted_token.AddRestrictingSid(*unique_restricted_sid);
- }
+ if (use_restricting_sids) {
+ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kNull);
+ if (unique_restricted_sid) {
+ restricted_token.AddRestrictingSid(*unique_restricted_sid);
+ }
+ }
break;
case USER_LAST:
return absl::nullopt;
}
if (deny_sids) {
restricted_token.AddAllSidsForDenyOnly(sid_exceptions);
}
diff --git a/sandbox/win/src/restricted_token_utils.h b/sandbox/win/src/restricted_token_utils.h
--- a/sandbox/win/src/restricted_token_utils.h
+++ b/sandbox/win/src/restricted_token_utils.h
@@ -34,17 +34,18 @@ enum TokenType { IMPERSONATION = 0, PRIM
// other sandboxed processes at the same security level.
// If the function succeeds, the return value is the restricted token. If it
// fails then the return value is empty.
absl::optional<base::win::AccessToken> CreateRestrictedToken(
TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
bool lockdown_default_dacl,
- const absl::optional<base::win::Sid>& unique_restricted_sid);
+ const absl::optional<base::win::Sid>& unique_restricted_sid,
+ bool use_restricting_sids);
// Hardens the integrity level policy on a token. Specifically it sets the
// policy to block read and execute so that a lower privileged process cannot
// open the token for impersonate or duplicate permissions. This should limit
// potential security holes.
// `token` must be a token with READ_CONTROL and WRITE_OWNER access.
// If the function succeeds, the return value is ERROR_SUCCESS. If the
// function fails, the return value is the win32 error code corresponding to
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -101,16 +101,24 @@ class TargetPolicy {
virtual ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) = 0;
// Returns the initial token level.
virtual TokenLevel GetInitialTokenLevel() const = 0;
// Returns the lockdown token level.
virtual TokenLevel GetLockdownTokenLevel() const = 0;
+ // Sets that we should not use restricting SIDs in the access tokens. We need
+ // to do this in some circumstances even though it weakens the sandbox.
+ // The default is to use them.
+ virtual void SetDoNotUseRestrictingSIDs() = 0;
+
+ // Returns whether we are using restricting SIDs.
+ virtual bool GetUseRestrictingSIDs() = 0;
+
// Sets the security level of the Job Object to which the target process will
// belong. This setting is permanent and cannot be changed once the target
// process is spawned. The job controls the global security settings which
// can not be specified in the token security profile.
// job_level: the security level for the job. See the explanation of each
// level in the JobLevel definition.
// ui_exceptions: specify what specific rights that are disabled in the
// chosen job_level that need to be granted. Use this parameter to avoid
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -416,16 +416,24 @@ ResultCode PolicyBase::SetTokenLevel(Tok
TokenLevel ConfigBase::GetInitialTokenLevel() const {
return initial_level_;
}
TokenLevel ConfigBase::GetLockdownTokenLevel() const {
return lockdown_level_;
}
+void ConfigBase::SetDoNotUseRestrictingSIDs() {
+ use_restricting_sids_ = false;
+}
+
+bool ConfigBase::GetUseRestrictingSIDs() {
+ return use_restricting_sids_;
+}
+
ResultCode ConfigBase::SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) {
job_level_ = job_level;
ui_exceptions_ = ui_exceptions;
return SBOX_ALL_OK;
}
JobLevel ConfigBase::GetJobLevel() const {
return job_level_;
@@ -600,17 +608,17 @@ ResultCode PolicyBase::MakeTokens(
}
IntegrityLevel integrity_level = config()->integrity_level();
bool lockdown_default_dacl = config()->lockdown_default_dacl();
// Create the 'naked' token. This will be the permanent token associated
// with the process and therefore with any thread that is not impersonating.
absl::optional<base::win::AccessToken> primary = CreateRestrictedToken(
config()->GetLockdownTokenLevel(), integrity_level, TokenType::kPrimary,
- lockdown_default_dacl, random_sid);
+ lockdown_default_dacl, random_sid, config()->GetUseRestrictingSIDs());
if (!primary) {
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN;
}
AppContainerBase* app_container = config()->app_container();
if (app_container &&
app_container->GetAppContainerType() == AppContainerType::kLowbox) {
// Build the lowbox lockdown (primary) token.
@@ -627,17 +635,18 @@ ResultCode PolicyBase::MakeTokens(
lockdown = std::move(*primary);
// 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( ))
absl::optional<base::win::AccessToken> impersonation = CreateRestrictedToken(
config()->GetInitialTokenLevel(), integrity_level,
- TokenType::kImpersonation, lockdown_default_dacl, random_sid);
+ TokenType::kImpersonation, lockdown_default_dacl, random_sid,
+ config()->GetUseRestrictingSIDs());
if (!impersonation) {
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN;
}
if (app_container) {
impersonation = app_container->BuildImpersonationToken(*impersonation);
if (!impersonation) {
return SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN;
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h
--- a/sandbox/win/src/sandbox_policy_base.h
+++ b/sandbox/win/src/sandbox_policy_base.h
@@ -52,16 +52,18 @@ class PolicyBase final : public TargetPo
ConfigBase(const ConfigBase&) = delete;
ConfigBase& operator=(const ConfigBase&) = delete;
bool IsConfigured() const override;
ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) override;
TokenLevel GetInitialTokenLevel() const override;
TokenLevel GetLockdownTokenLevel() const override;
+ void SetDoNotUseRestrictingSIDs() final;
+ bool GetUseRestrictingSIDs() final;
ResultCode SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) override;
JobLevel GetJobLevel() const override;
void SetJobMemoryLimit(size_t memory_limit) override;
ResultCode AllowFileAccess(FileSemantics semantics,
const wchar_t* pattern) override;
ResultCode AllowNamedPipes(const wchar_t* pattern) override;
ResultCode AllowExtraDlls(const wchar_t* pattern) override;
ResultCode SetFakeGdiInit() override;
@@ -133,16 +135,17 @@ class PolicyBase final : public TargetPo
Desktop desktop() { return desktop_; }
// nullptr if no objects have been added via AddKernelObjectToClose().
HandleCloser* handle_closer() { return handle_closer_.get(); }
bool zero_appshim() { return zero_appshim_; }
TokenLevel lockdown_level_;
TokenLevel initial_level_;
+ bool use_restricting_sids_ = true;
JobLevel job_level_;
IntegrityLevel integrity_level_;
IntegrityLevel delayed_integrity_level_;
MitigationFlags mitigations_;
MitigationFlags delayed_mitigations_;
bool add_restricting_random_sid_;
bool lockdown_default_dacl_;
bool is_csrss_connected_;