// Copyright 2017 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/policy/sandbox.h" #include "base/command_line.h" #include "build/build_config.h" #include "sandbox/policy/mojom/sandbox.mojom.h" #include "sandbox/policy/switches.h" #if BUILDFLAG(IS_ANDROID) #include "base/android/jni_android.h" #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "sandbox/policy/linux/sandbox_linux.h" #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_MAC) #include "sandbox/mac/seatbelt.h" #endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_WIN) #include "base/process/process_info.h" #include "sandbox/policy/win/sandbox_win.h" #include "sandbox/win/src/sandbox.h" #endif // BUILDFLAG(IS_WIN) namespace sandbox { namespace policy { #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) bool Sandbox::Initialize(sandbox::mojom::Sandbox sandbox_type, SandboxLinux::PreSandboxHook hook, const SandboxLinux::Options& options) { return SandboxLinux::GetInstance()->InitializeSandbox( sandbox_type, std::move(hook), options); } #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_WIN) bool Sandbox::Initialize(sandbox::mojom::Sandbox sandbox_type, SandboxInterfaceInfo* sandbox_info) { BrokerServices* broker_services = sandbox_info->broker_services; if (broker_services) { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); if (!SandboxWin::InitBrokerServices(broker_services)) return false; // Only pre-create alternate desktop if there will be sandboxed processes in // the future. if (!command_line.HasSwitch(switches::kNoSandbox)) { // IMPORTANT: This piece of code needs to run as early as possible in the // process because it will initialize the sandbox broker, which requires // the process to swap its window station. During this time all the UI // will be broken. This has to run before threads and windows are created. ResultCode result = broker_services->CreatePolicy()->CreateAlternateDesktop(true); CHECK(SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result); } return true; } return IsUnsandboxedSandboxType(sandbox_type) || SandboxWin::InitTargetServices(sandbox_info->target_services); } #endif // BUILDFLAG(IS_WIN) // static bool Sandbox::IsProcessSandboxed() { auto* command_line = base::CommandLine::ForCurrentProcess(); bool is_browser = !command_line->HasSwitch(switches::kProcessType); if (!is_browser && base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox)) { // When running with --no-sandbox, unconditionally report the process as // sandboxed. This lets code write |DCHECK(IsProcessSandboxed())| and not // break when testing with the --no-sandbox switch. return true; } #if BUILDFLAG(IS_ANDROID) // Note that this does not check the status of the Seccomp sandbox. Call // https://developer.android.com/reference/android/os/Process#isIsolated(). JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef process_class = base::android::GetClass(env, "android/os/Process"); jmethodID is_isolated = base::android::MethodID::Get( env, process_class.obj(), "isIsolated", "()Z"); return env->CallStaticBooleanMethod(process_class.obj(), is_isolated); #elif BUILDFLAG(IS_FUCHSIA) // TODO(https://crbug.com/1071420): Figure out what to do here. Process // launching controls the sandbox and there are no ambient capabilities, so // basically everything but the browser is considered sandboxed. return !is_browser; #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) int status = SandboxLinux::GetInstance()->GetStatus(); constexpr int kLayer1Flags = SandboxLinux::Status::kSUID | SandboxLinux::Status::kPIDNS | SandboxLinux::Status::kUserNS; constexpr int kLayer2Flags = SandboxLinux::Status::kSeccompBPF | SandboxLinux::Status::kSeccompTSYNC; return (status & kLayer1Flags) != 0 && (status & kLayer2Flags) != 0; #elif BUILDFLAG(IS_MAC) return Seatbelt::IsSandboxed(); #elif BUILDFLAG(IS_WIN) return base::GetCurrentProcessIntegrityLevel() < base::MEDIUM_INTEGRITY; #else return false; #endif } } // namespace policy } // namespace sandbox