mirror of
https://github.com/google/nsjail.git
synced 2026-08-30 18:41:30 -07:00
Merge branch 'master' of github.com:google/nsjail
This commit is contained in:
27
contain.cc
27
contain.cc
@@ -26,6 +26,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
@@ -95,11 +96,31 @@ static bool containDropPrivs(nsj_t* nsj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool containPrepareEnv(nsj_t* nsj) {
|
||||
bool setupParentDeathSignal(int parent_fd, pid_t expected_parent) {
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) == -1) {
|
||||
PLOG_E("prctl(PR_SET_PDEATHSIG, SIGKILL)");
|
||||
return false;
|
||||
}
|
||||
if (parent_fd != -1) {
|
||||
struct pollfd pfd = {.fd = parent_fd, .events = POLLIN, .revents = 0};
|
||||
if (poll(&pfd, 1, 0) == -1) {
|
||||
PLOG_E("poll(parent_fd=%d)", parent_fd);
|
||||
return false;
|
||||
}
|
||||
if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
|
||||
LOG_E("Parent process exited before PR_SET_PDEATHSIG was installed");
|
||||
return false;
|
||||
}
|
||||
} else if (getppid() != expected_parent) {
|
||||
LOG_E("Parent process changed before PR_SET_PDEATHSIG was installed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool containPrepareEnv(nsj_t* nsj, int parent_fd, pid_t expected_parent) {
|
||||
/* Effective UID/GID changes clear PDEATHSIG, so restore it after containUserNs(). */
|
||||
RETURN_ON_FAILURE(setupParentDeathSignal(parent_fd, expected_parent));
|
||||
unsigned long personality = 0;
|
||||
if (nsj->njc.persona_addr_compat_layout()) {
|
||||
personality |= ADDR_COMPAT_LAYOUT;
|
||||
@@ -409,7 +430,7 @@ bool setupFD(nsj_t* nsj, int fd_in, int fd_out, int fd_err) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool containProc(nsj_t* nsj) {
|
||||
bool containProc(nsj_t* nsj, int parent_fd, pid_t expected_parent) {
|
||||
RETURN_ON_FAILURE(containUserNs(nsj));
|
||||
RETURN_ON_FAILURE(containInitPidNs(nsj));
|
||||
RETURN_ON_FAILURE(containInitMountNs(nsj));
|
||||
@@ -424,7 +445,7 @@ bool containProc(nsj_t* nsj) {
|
||||
RETURN_ON_FAILURE(containCoreSched(nsj));
|
||||
RETURN_ON_FAILURE(containTSC(nsj));
|
||||
RETURN_ON_FAILURE(containSetLimits(nsj));
|
||||
RETURN_ON_FAILURE(containPrepareEnv(nsj));
|
||||
RETURN_ON_FAILURE(containPrepareEnv(nsj, parent_fd, expected_parent));
|
||||
RETURN_ON_FAILURE(containMakeFdsCOE(nsj));
|
||||
|
||||
return true;
|
||||
|
||||
@@ -23,13 +23,15 @@
|
||||
#define NS_CONTAIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "nsjail.h"
|
||||
|
||||
namespace contain {
|
||||
|
||||
bool setupFD(nsj_t* nsj, int fd_in, int fd_out, int fd_err);
|
||||
bool containProc(nsj_t* nsj);
|
||||
bool setupParentDeathSignal(int parent_fd, pid_t expected_parent);
|
||||
bool containProc(nsj_t* nsj, int parent_fd, pid_t expected_parent);
|
||||
|
||||
} // namespace contain
|
||||
|
||||
|
||||
14
subproc.cc
14
subproc.cc
@@ -161,7 +161,12 @@ static const std::string concatArgs(const std::vector<const char*>& argv) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void newProc(nsj_t* nsj, int netfd, int fd_in, int fd_out, int fd_err, int pipefd) {
|
||||
static void newProc(
|
||||
nsj_t* nsj, int netfd, int fd_in, int fd_out, int fd_err, int pipefd, pid_t expected_parent) {
|
||||
/* Arm before setup begins; containProc() re-arms after changing credentials. */
|
||||
if (!contain::setupParentDeathSignal(pipefd, expected_parent)) {
|
||||
return;
|
||||
}
|
||||
if (nsj->njc.has_oom_score_adj()) {
|
||||
std::string score = std::to_string(nsj->njc.oom_score_adj());
|
||||
if (!util::writeBufToFile(
|
||||
@@ -206,7 +211,7 @@ static void newProc(nsj_t* nsj, int netfd, int fd_in, int fd_out, int fd_err, in
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!contain::containProc(nsj)) {
|
||||
if (!contain::containProc(nsj, pipefd, expected_parent)) {
|
||||
return;
|
||||
}
|
||||
if (!nsj->njc.keep_env()) {
|
||||
@@ -528,11 +533,12 @@ pid_t runChild(nsj_t* nsj, int netfd, int fd_in, int fd_out, int fd_err) {
|
||||
flags |= (nsj->njc.clone_newtime() ? CLONE_NEWTIME : 0);
|
||||
|
||||
if (nsj->njc.mode() == nsjail::Mode::EXECVE) {
|
||||
const pid_t expected_parent = getppid();
|
||||
LOG_D("unshare(flags: %s)", cloneFlagsToStr(flags).c_str());
|
||||
if (unshare(flags) == -1) {
|
||||
PLOG_F("unshare(%s)", cloneFlagsToStr(flags).c_str());
|
||||
}
|
||||
newProc(nsj, netfd, fd_in, fd_out, fd_err, -1);
|
||||
newProc(nsj, netfd, fd_in, fd_out, fd_err, -1, expected_parent);
|
||||
LOG_F("Launching new process failed");
|
||||
}
|
||||
|
||||
@@ -550,7 +556,7 @@ pid_t runChild(nsj_t* nsj, int netfd, int fd_in, int fd_out, int fd_err) {
|
||||
pid_t pid = cloneProc(flags, SIGCHLD);
|
||||
if (pid == 0) {
|
||||
close(parent_fd);
|
||||
newProc(nsj, netfd, fd_in, fd_out, fd_err, child_fd);
|
||||
newProc(nsj, netfd, fd_in, fd_out, fd_err, child_fd, 0);
|
||||
util::writeToFd(child_fd, &kSubprocErrorChar, sizeof(kSubprocErrorChar));
|
||||
LOG_F("Launching child process failed");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user