diff --git a/sandboxed_api/sandbox2/BUILD.bazel b/sandboxed_api/sandbox2/BUILD.bazel index 3e3671a..aa073fa 100644 --- a/sandboxed_api/sandbox2/BUILD.bazel +++ b/sandboxed_api/sandbox2/BUILD.bazel @@ -249,6 +249,7 @@ cc_library( copts = sapi_platform_copts(), visibility = ["//visibility:public"], deps = [ + ":fork_client", ":global_forkserver", "@com_google_absl//absl/base:core_headers", ], diff --git a/sandboxed_api/sandbox2/CMakeLists.txt b/sandboxed_api/sandbox2/CMakeLists.txt index 283b5d7..4ddde85 100644 --- a/sandboxed_api/sandbox2/CMakeLists.txt +++ b/sandboxed_api/sandbox2/CMakeLists.txt @@ -260,6 +260,7 @@ add_library(sandbox2::start_global_forkserver_lib_constructor ALIAS target_link_libraries(sandbox2_start_global_forkserver_lib_constructor PRIVATE absl::core_headers sapi::base + sandbox2::fork_client sandbox2::global_forkserver ) diff --git a/sandboxed_api/sandbox2/global_forkclient.cc b/sandboxed_api/sandbox2/global_forkclient.cc index 61eeb0a..60d91ed 100644 --- a/sandboxed_api/sandbox2/global_forkclient.cc +++ b/sandboxed_api/sandbox2/global_forkclient.cc @@ -116,20 +116,6 @@ GlobalForkserverStartModeSet GetForkserverStartMode() { } std::unique_ptr StartGlobalForkServer() { - if (getenv(kForkServerDisableEnv)) { - SAPI_RAW_VLOG(1, - "Start of the Global Fork-Server prevented by the '%s' " - "environment variable present", - kForkServerDisableEnv); - return {}; - } - - if (GetForkserverStartMode().empty()) { - SAPI_RAW_VLOG( - 1, "Start of the Global Fork-Server prevented by commandline flag"); - return {}; - } - file_util::fileops::FDCloser exec_fd( sapi::EmbedFile::GetEmbedFileSingleton()->GetFdForFileToc( forkserver_bin_embed_create())); @@ -167,10 +153,31 @@ std::unique_ptr StartGlobalForkServer() { absl::Mutex GlobalForkClient::instance_mutex_(absl::kConstInit); GlobalForkClient* GlobalForkClient::instance_ = nullptr; -void GlobalForkClient::EnsureStarted() { +void GlobalForkClient::EnsureStarted(GlobalForkserverStartMode mode) { + absl::MutexLock lock(&instance_mutex_); + EnsureStartedLocked(mode); +} + +void GlobalForkClient::EnsureStartedLocked(GlobalForkserverStartMode mode) { + if (!instance_) { + SAPI_RAW_CHECK(!getenv(kForkServerDisableEnv), + "Start of the Global Fork-Server prevented by the '%s' " + "environment variable present", + kForkServerDisableEnv); + SAPI_RAW_CHECK( + GetForkserverStartMode().contains(mode), + "Start of the Global Fork-Server prevented by commandline flag"); + instance_ = StartGlobalForkServer().release(); + } + SAPI_RAW_CHECK(instance_ != nullptr, "global fork client not initialized"); +} + +void GlobalForkClient::ForceStart() { absl::MutexLock lock(&GlobalForkClient::instance_mutex_); - EnsureStartedLocked( - GetForkserverStartMode().contains(GlobalForkserverStartMode::kOnDemand)); + SAPI_RAW_CHECK(instance_ == nullptr, + "A force start requested when the Global Fork-Server was " + "already running"); + instance_ = StartGlobalForkServer().release(); } void GlobalForkClient::Shutdown() { @@ -179,19 +186,11 @@ void GlobalForkClient::Shutdown() { instance_ = nullptr; } -void GlobalForkClient::EnsureStartedLocked(bool start_if_needed) { - if (!instance_ && start_if_needed) { - instance_ = StartGlobalForkServer().release(); - } - SAPI_RAW_CHECK(instance_ != nullptr, "global fork client not initialized"); -} - pid_t GlobalForkClient::SendRequest(const ForkRequest& request, int exec_fd, int comms_fd, int user_ns_fd, pid_t* init_pid) { absl::MutexLock lock(&GlobalForkClient::instance_mutex_); - EnsureStartedLocked( - GetForkserverStartMode().contains(GlobalForkserverStartMode::kOnDemand)); + EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand); pid_t pid = instance_->fork_client_.SendRequest(request, exec_fd, comms_fd, user_ns_fd, init_pid); if (instance_->comms_.IsTerminated()) { @@ -202,9 +201,7 @@ pid_t GlobalForkClient::SendRequest(const ForkRequest& request, int exec_fd, pid_t GlobalForkClient::GetPid() { absl::MutexLock lock(&instance_mutex_); - EnsureStartedLocked( - GetForkserverStartMode().contains(GlobalForkserverStartMode::kOnDemand)); - SAPI_RAW_CHECK(instance_ != nullptr, "global fork client not initialized"); + EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand); return instance_->fork_client_.pid(); } } // namespace sandbox2 diff --git a/sandboxed_api/sandbox2/global_forkclient.h b/sandboxed_api/sandbox2/global_forkclient.h index 5551155..99054c9 100644 --- a/sandboxed_api/sandbox2/global_forkclient.h +++ b/sandboxed_api/sandbox2/global_forkclient.h @@ -33,6 +33,12 @@ namespace sandbox2 { +enum class GlobalForkserverStartMode { + kOnDemand, + // MUST be the last element + kNumGlobalForkserverStartModes, +}; + class GlobalForkClient { public: GlobalForkClient(int fd, pid_t pid) @@ -44,26 +50,27 @@ class GlobalForkClient { ABSL_LOCKS_EXCLUDED(instance_mutex_); static pid_t GetPid() ABSL_LOCKS_EXCLUDED(instance_mutex_); - static void EnsureStarted() ABSL_LOCKS_EXCLUDED(instance_mutex_); + static void EnsureStarted() ABSL_LOCKS_EXCLUDED(instance_mutex_) { + EnsureStarted(GlobalForkserverStartMode::kOnDemand); + } static void Shutdown() ABSL_LOCKS_EXCLUDED(instance_mutex_); private: + friend void StartGlobalForkserverFromLibCtor(); + + static void ForceStart() ABSL_LOCKS_EXCLUDED(instance_mutex_); + static void EnsureStarted(GlobalForkserverStartMode mode) + ABSL_LOCKS_EXCLUDED(instance_mutex_); + static void EnsureStartedLocked(GlobalForkserverStartMode mode) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(instance_mutex_); + static absl::Mutex instance_mutex_; static GlobalForkClient* instance_ ABSL_GUARDED_BY(instance_mutex_); - static void EnsureStartedLocked(bool start_if_needed = true) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(instance_mutex_); - Comms comms_; ForkClient fork_client_; }; -enum class GlobalForkserverStartMode { - kOnDemand, - // MUST be the last element - kNumGlobalForkserverStartModes, -}; - class GlobalForkserverStartModeSet { public: static constexpr size_t kSize = static_cast( diff --git a/sandboxed_api/sandbox2/global_forkclient_lib_ctor.cc b/sandboxed_api/sandbox2/global_forkclient_lib_ctor.cc index 98e064c..5446b75 100644 --- a/sandboxed_api/sandbox2/global_forkclient_lib_ctor.cc +++ b/sandboxed_api/sandbox2/global_forkclient_lib_ctor.cc @@ -12,14 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "absl/base/attributes.h" +#include "sandboxed_api/sandbox2/fork_client.h" #include "sandboxed_api/sandbox2/global_forkclient.h" +namespace sandbox2 { +void StartGlobalForkserverFromLibCtor() { + if (!getenv(sandbox2::kForkServerDisableEnv)) { + GlobalForkClient::ForceStart(); + } +} +} // namespace sandbox2 + // Run the ForkServer from the constructor, when no other threads are present. // Because it's possible to start thread-inducing initializers before // RunInitializers() (base/googleinit.h) it's not enough to just register // a 0000_ initializer instead. ABSL_ATTRIBUTE_UNUSED __attribute__((constructor)) static void StartSandbox2Forkserver() { - sandbox2::GlobalForkClient::EnsureStarted(); + sandbox2::StartGlobalForkserverFromLibCtor(); }