1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132

content / browser / utility_sandbox_delegate_unittest.cc [blame]

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/utility_sandbox_delegate.h"

#include <memory>

#include "base/environment.h"
#include "base/test/scoped_feature_list.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "sandbox/policy/features.h"
#include "sandbox/policy/mojom/sandbox.mojom.h"
#include "sandbox/policy/sandbox_type.h"
#include "sandbox/policy/switches.h"
#include "sandbox/policy/win/sandbox_win.h"
#include "sandbox/win/src/app_container_base.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_policy_base.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

class UtilitySandboxDelegateWinTest
    : public ::testing::Test,
      public ::testing::WithParamInterface<
          std::tuple</*AppContainerDisabled=*/bool,
                     /*kPrintCompositorLPAC=*/bool>> {
 public:
  UtilitySandboxDelegateWinTest() = default;

  void SetUp() override {
    scoped_feature_list_.InitWithFeatureState(
        sandbox::policy::features::kPrintCompositorLPAC,
        IsLPACFeatureEnabledForTest());
  }

 protected:
  static bool IsAppContainerDisabledForTest() {
    return std::get<0>(GetParam());
  }
  static bool IsLPACFeatureEnabledForTest() { return std::get<1>(GetParam()); }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

TEST_P(UtilitySandboxDelegateWinTest, IsAppContainerDisabled) {
  class MaybeDisableAppCongtainerBrowserClient : public ContentBrowserClient {
    bool IsAppContainerDisabled(sandbox::mojom::Sandbox sandbox_type) override {
      return IsAppContainerDisabledForTest();
    }
  } test_browser_client;

  auto* old_browser_client = SetBrowserClientForTesting(&test_browser_client);

  // Print compositor is chosen as a sandbox type, because it is a utility
  // process that has App Container enabled by default.
  constexpr auto kSandboxType = sandbox::mojom::Sandbox::kPrintCompositor;

  auto cmd_line = base::CommandLine(
      ChildProcessHost::GetChildPath(ChildProcessHost::CHILD_NORMAL));
  cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess);
  sandbox::policy::SetCommandLineFlagsForSandboxType(&cmd_line, kSandboxType);

  base::EnvironmentMap env;
  auto utility_delegate =
      std::make_unique<UtilitySandboxedProcessLauncherDelegate>(kSandboxType,
                                                                env, cmd_line);
  base::HandlesToInheritVector handles_to_inherit;
  sandbox::BrokerServices* broker =
      sandbox::SandboxFactory::GetBrokerServices();
  auto policy = broker->CreatePolicy();

  sandbox::ResultCode result =
      sandbox::policy::SandboxWin::GeneratePolicyForSandboxedProcess(
          cmd_line, handles_to_inherit, utility_delegate.get(), policy.get());
  ASSERT_EQ(sandbox::ResultCode::SBOX_ALL_OK, result);
  SetBrowserClientForTesting(old_browser_client);

  bool expected_app_container_enabled = IsLPACFeatureEnabledForTest();

  // The content client can override the state to disable it, but not to enable
  // it if the feature is disabled.
  if (IsAppContainerDisabledForTest()) {
    expected_app_container_enabled = false;
  }

  if (expected_app_container_enabled) {
    EXPECT_TRUE(policy->GetConfig()->GetAppContainer());
    EXPECT_EQ(policy->GetConfig()->GetIntegrityLevel(),
              sandbox::IntegrityLevel::INTEGRITY_LEVEL_LAST);
    EXPECT_EQ(policy->GetConfig()->GetInitialTokenLevel(),
              sandbox::TokenLevel::USER_UNPROTECTED);
    EXPECT_EQ(policy->GetConfig()->GetLockdownTokenLevel(),
              sandbox::TokenLevel::USER_UNPROTECTED);
  } else {
    EXPECT_FALSE(policy->GetConfig()->GetAppContainer());
    EXPECT_EQ(policy->GetConfig()->GetIntegrityLevel(),
              sandbox::IntegrityLevel::INTEGRITY_LEVEL_LOW);
    EXPECT_EQ(policy->GetConfig()->GetInitialTokenLevel(),
              sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS);
    EXPECT_EQ(policy->GetConfig()->GetLockdownTokenLevel(),
              sandbox::TokenLevel::USER_LOCKDOWN);
  }
}

INSTANTIATE_TEST_SUITE_P(
    /* no prefix */,
    UtilitySandboxDelegateWinTest,
// TODO(crbug.com/353583970):  Enable `kPrintCompositorLPAC` for ARM when
// flakiness is resolved.
#if defined(ARCH_CPU_ARM_FAMILY)
    ::testing::Combine(/*AppContainerDisabled=*/::testing::Bool(),
                       /*kPrintCompositorLPAC=*/::testing::Values(false)),
#else
    ::testing::Combine(/*AppContainerDisabled=*/::testing::Bool(),
                       /*kPrintCompositorLPAC=*/::testing::Bool()),
#endif
    [](const auto& info) {
      return base::StrCat(
          {std::get<0>(info.param) ? "ACDisabled" : "ACEnabled",
           std::get<1>(info.param) ? "FeatureEnabled" : "FeatureDisabled"});
    });

}  // namespace content