# 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:
https://hg.mozilla.org/mozilla-central/rev/14374cd9497a

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
 
 std::optional<base::win::AccessToken> CreateRestrictedToken(
     TokenLevel security_level,
     IntegrityLevel integrity_level,
     TokenType token_type,
     bool lockdown_default_dacl,
-    const std::optional<base::win::Sid>& unique_restricted_sid) {
+    const std::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 std::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
@@ -33,17 +33,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.
 std::optional<base::win::AccessToken> CreateRestrictedToken(
     TokenLevel security_level,
     IntegrityLevel integrity_level,
     TokenType token_type,
     bool lockdown_default_dacl,
-    const std::optional<base::win::Sid>& unique_restricted_sid);
+    const std::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
@@ -90,16 +90,24 @@ class TargetPolicy {
                                                  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
@@ -408,16 +408,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_;
@@ -593,17 +601,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.
   std::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.
@@ -620,17 +628,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( ))
   std::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
@@ -49,16 +49,18 @@ class ConfigBase final : public TargetCo
   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 AllowExtraDll(const wchar_t* path) override;
   ResultCode SetFakeGdiInit() override;
   void AddDllToUnload(const wchar_t* dll_name) override;
@@ -128,16 +130,17 @@ class ConfigBase final : public TargetCo
   size_t memory_limit() { return memory_limit_; }
   uint32_t ui_exceptions() { return ui_exceptions_; }
   Desktop desktop() { return desktop_; }
   const HandleCloserConfig& handle_closer() { return handle_closer_; }
   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_;
