mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Fix possible crash when multiple termination conditions occur simultaneously
E.g. a failed `KillSandboxee` for a timeout would already set the exit status code while there could be an external kill pending at the same time which would try to `KillSandboxee` again and thus set exit status code again. PiperOrigin-RevId: 448464765 Change-Id: Ic5744a576c4255504bfb1d5c4f33253b5bb32b6f
This commit is contained in:
parent
5e61ce0853
commit
88b0a9e2e5
|
@ -406,19 +406,23 @@ void Monitor::SetAdditionalResultInfo(std::unique_ptr<Regs> regs) {
|
||||||
LOG(INFO) << "]";
|
LOG(INFO) << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::KillSandboxee() {
|
bool Monitor::KillSandboxee() {
|
||||||
VLOG(1) << "Sending SIGKILL to the PID: " << pid_;
|
VLOG(1) << "Sending SIGKILL to the PID: " << pid_;
|
||||||
if (kill(pid_, SIGKILL) != 0) {
|
if (kill(pid_, SIGKILL) != 0) {
|
||||||
PLOG(ERROR) << "Could not send SIGKILL to PID " << pid_;
|
PLOG(ERROR) << "Could not send SIGKILL to PID " << pid_;
|
||||||
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_KILL);
|
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_KILL);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::InterruptSandboxee() {
|
bool Monitor::InterruptSandboxee() {
|
||||||
if (ptrace(PTRACE_INTERRUPT, pid_, 0, 0) == -1) {
|
if (ptrace(PTRACE_INTERRUPT, pid_, 0, 0) == -1) {
|
||||||
PLOG(ERROR) << "Could not send interrupt to pid=" << pid_;
|
PLOG(ERROR) << "Could not send interrupt to pid=" << pid_;
|
||||||
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_INTERRUPT);
|
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_INTERRUPT);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not defined in glibc.
|
// Not defined in glibc.
|
||||||
|
@ -429,22 +433,28 @@ void Monitor::MainLoop(sigset_t* sset) {
|
||||||
int status;
|
int status;
|
||||||
// All possible still running children of main process, will be killed due to
|
// All possible still running children of main process, will be killed due to
|
||||||
// PTRACE_O_EXITKILL ptrace() flag.
|
// PTRACE_O_EXITKILL ptrace() flag.
|
||||||
for (;;) {
|
while (result_.final_status() == Result::UNSET) {
|
||||||
int64_t deadline = deadline_millis_.load(std::memory_order_relaxed);
|
int64_t deadline = deadline_millis_.load(std::memory_order_relaxed);
|
||||||
if (deadline != 0 && absl::Now() >= absl::FromUnixMillis(deadline)) {
|
if (deadline != 0 && absl::Now() >= absl::FromUnixMillis(deadline)) {
|
||||||
VLOG(1) << "Sandbox process hit timeout due to the walltime timer";
|
VLOG(1) << "Sandbox process hit timeout due to the walltime timer";
|
||||||
timed_out_ = true;
|
timed_out_ = true;
|
||||||
KillSandboxee();
|
if (!KillSandboxee()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dump_stack_request_flag_.test_and_set(std::memory_order_relaxed)) {
|
if (!dump_stack_request_flag_.test_and_set(std::memory_order_relaxed)) {
|
||||||
should_dump_stack_ = true;
|
should_dump_stack_ = true;
|
||||||
InterruptSandboxee();
|
if (!InterruptSandboxee()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!external_kill_request_flag_.test_and_set(std::memory_order_relaxed)) {
|
if (!external_kill_request_flag_.test_and_set(std::memory_order_relaxed)) {
|
||||||
external_kill_ = true;
|
external_kill_ = true;
|
||||||
KillSandboxee();
|
if (!KillSandboxee()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network_proxy_server_ &&
|
if (network_proxy_server_ &&
|
||||||
|
@ -452,11 +462,9 @@ void Monitor::MainLoop(sigset_t* sset) {
|
||||||
std::memory_order_acquire) &&
|
std::memory_order_acquire) &&
|
||||||
!network_violation_) {
|
!network_violation_) {
|
||||||
network_violation_ = true;
|
network_violation_ = true;
|
||||||
KillSandboxee();
|
if (!KillSandboxee()) {
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
if (result_.final_status() != Result::UNSET) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// It should be a non-blocking operation (hence WNOHANG), so this function
|
// It should be a non-blocking operation (hence WNOHANG), so this function
|
||||||
|
|
|
@ -97,10 +97,12 @@ class Monitor final {
|
||||||
bool InitApplyLimit(pid_t pid, int resource, const rlimit64& rlim) const;
|
bool InitApplyLimit(pid_t pid, int resource, const rlimit64& rlim) const;
|
||||||
|
|
||||||
// Kills the main traced PID with PTRACE_KILL.
|
// Kills the main traced PID with PTRACE_KILL.
|
||||||
void KillSandboxee();
|
// Returns false if an error occured and process could not be killed.
|
||||||
|
bool KillSandboxee();
|
||||||
|
|
||||||
// Interrupts the main traced PID with PTRACE_INTERRUPT.
|
// Interrupts the main traced PID with PTRACE_INTERRUPT.
|
||||||
void InterruptSandboxee();
|
// Returns false if an error occured and process could not be interrupted.
|
||||||
|
bool InterruptSandboxee();
|
||||||
|
|
||||||
// Waits for events from monitored clients and signals from the main process.
|
// Waits for events from monitored clients and signals from the main process.
|
||||||
void MainLoop(sigset_t* sset);
|
void MainLoop(sigset_t* sset);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user