Do not fail-hard in global forkserver startup

PiperOrigin-RevId: 389816114
Change-Id: Icd672028ff224cf01095d6590fe1cc2adb312316
This commit is contained in:
Wiktor Garbacz 2021-08-10 00:33:04 -07:00 committed by Copybara-Service
parent 165c155a08
commit 773dc6b18b
3 changed files with 46 additions and 19 deletions

View File

@ -228,7 +228,7 @@ cc_library(
"//sandboxed_api:embed_file", "//sandboxed_api:embed_file",
"//sandboxed_api/util:flags", "//sandboxed_api/util:flags",
"//sandboxed_api/util:raw_logging", "//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:strerror", "//sandboxed_api/util:status",
"@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/memory", "@com_google_absl//absl/memory",
"@com_google_absl//absl/strings", "@com_google_absl//absl/strings",

View File

@ -232,6 +232,7 @@ target_link_libraries(sandbox2_global_forkserver
sapi::base sapi::base
sapi::embed_file sapi::embed_file
sapi::raw_logging sapi::raw_logging
sapi::status
PUBLIC absl::core_headers PUBLIC absl::core_headers
absl::synchronization absl::synchronization
sandbox2::comms sandbox2::comms

View File

@ -43,8 +43,8 @@
#include "sandboxed_api/sandbox2/fork_client.h" #include "sandboxed_api/sandbox2/fork_client.h"
#include "sandboxed_api/sandbox2/forkserver_bin_embed.h" #include "sandboxed_api/sandbox2/forkserver_bin_embed.h"
#include "sandboxed_api/sandbox2/util.h" #include "sandboxed_api/sandbox2/util.h"
#include "sandboxed_api/util/os_error.h"
#include "sandboxed_api/util/raw_logging.h" #include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/strerror.h"
namespace sandbox2 { namespace sandbox2 {
@ -118,21 +118,28 @@ GlobalForkserverStartModeSet GetForkserverStartMode() {
return rv; return rv;
} }
std::unique_ptr<GlobalForkClient> StartGlobalForkServer() { absl::StatusOr<std::unique_ptr<GlobalForkClient>> StartGlobalForkServer() {
// The fd is owned by EmbedFile // The fd is owned by EmbedFile
int exec_fd = sapi::EmbedFile::instance()->GetFdForFileToc( int exec_fd = sapi::EmbedFile::instance()->GetFdForFileToc(
forkserver_bin_embed_create()); forkserver_bin_embed_create());
SAPI_RAW_CHECK(exec_fd >= 0, "Getting FD for init binary failed"); if (exec_fd < 0) {
return absl::InternalError("Getting FD for init binary failed");
}
std::string proc_name = "S2-FORK-SERV"; std::string proc_name = "S2-FORK-SERV";
int sv[2]; int sv[2];
SAPI_RAW_CHECK(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) != -1, if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) == -1) {
"creating socket pair"); return absl::InternalError(
sapi::OsErrorMessage(errno, "Creating socket pair failed"));
}
// Fork the fork-server, and clean-up the resources (close remote sockets). // Fork the fork-server, and clean-up the resources (close remote sockets).
pid_t pid = util::ForkWithFlags(SIGCHLD); pid_t pid = util::ForkWithFlags(SIGCHLD);
SAPI_RAW_PCHECK(pid != -1, "during fork"); if (pid == -1) {
return absl::InternalError(
sapi::OsErrorMessage(errno, "Forking forkserver process failed"));
}
// Child. // Child.
if (pid == 0) { if (pid == 0) {
@ -178,18 +185,28 @@ void GlobalForkClient::EnsureStarted(GlobalForkserverStartMode mode) {
} }
void GlobalForkClient::EnsureStartedLocked(GlobalForkserverStartMode mode) { void GlobalForkClient::EnsureStartedLocked(GlobalForkserverStartMode mode) {
if (!instance_) { if (instance_) {
SAPI_RAW_CHECK( return;
!getenv(kForkServerDisableEnv),
absl::StrCat("Start of the Global Fork-Server prevented by the '",
kForkServerDisableEnv, "' environment variable present")
.c_str());
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"); if (getenv(kForkServerDisableEnv)) {
SAPI_RAW_LOG(ERROR,
"Start of the Global Fork-Server prevented by the %s "
"environment variable present",
kForkServerDisableEnv);
return;
}
if (!GetForkserverStartMode().contains(mode)) {
SAPI_RAW_LOG(
ERROR, "Start of the Global Fork-Server prevented by commandline flag");
return;
}
absl::StatusOr<std::unique_ptr<GlobalForkClient>> forkserver =
StartGlobalForkServer();
if (!forkserver.ok()) {
SAPI_RAW_LOG(ERROR, "Starting forkserver failed: %s",
forkserver.status().message().data());
}
instance_ = forkserver->release();
} }
void GlobalForkClient::ForceStart() { void GlobalForkClient::ForceStart() {
@ -197,7 +214,10 @@ void GlobalForkClient::ForceStart() {
SAPI_RAW_CHECK(instance_ == nullptr, SAPI_RAW_CHECK(instance_ == nullptr,
"A force start requested when the Global Fork-Server was " "A force start requested when the Global Fork-Server was "
"already running"); "already running");
instance_ = StartGlobalForkServer().release(); absl::StatusOr<std::unique_ptr<GlobalForkClient>> forkserver =
StartGlobalForkServer();
SAPI_RAW_CHECK(forkserver.ok(), forkserver.status().message().data());
instance_ = forkserver->release();
} }
void GlobalForkClient::Shutdown() { void GlobalForkClient::Shutdown() {
@ -220,6 +240,9 @@ pid_t GlobalForkClient::SendRequest(const ForkRequest& request, int exec_fd,
pid_t* init_pid) { pid_t* init_pid) {
absl::ReleasableMutexLock lock(&GlobalForkClient::instance_mutex_); absl::ReleasableMutexLock lock(&GlobalForkClient::instance_mutex_);
EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand); EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand);
if (!instance_) {
return -1;
}
pid_t pid = instance_->fork_client_.SendRequest(request, exec_fd, comms_fd, pid_t pid = instance_->fork_client_.SendRequest(request, exec_fd, comms_fd,
user_ns_fd, init_pid); user_ns_fd, init_pid);
if (instance_->comms_.IsTerminated()) { if (instance_->comms_.IsTerminated()) {
@ -238,6 +261,9 @@ pid_t GlobalForkClient::SendRequest(const ForkRequest& request, int exec_fd,
pid_t GlobalForkClient::GetPid() { pid_t GlobalForkClient::GetPid() {
absl::MutexLock lock(&instance_mutex_); absl::MutexLock lock(&instance_mutex_);
EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand); EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand);
if (!instance_) {
return -1;
}
return instance_->fork_client_.pid(); return instance_->fork_client_.pid();
} }