nsjail: move pids queue to a vector

This commit is contained in:
Robert Swiecki 2018-02-10 05:13:25 +01:00
parent 5f3267e745
commit 381e6a1af7
4 changed files with 34 additions and 46 deletions

View File

@ -388,7 +388,6 @@ std::unique_ptr<struct nsjconf_t> parseArgs(int argc, char* argv[]) {
nsjconf->openfds.push_back(STDOUT_FILENO); nsjconf->openfds.push_back(STDOUT_FILENO);
nsjconf->openfds.push_back(STDERR_FILENO); nsjconf->openfds.push_back(STDERR_FILENO);
TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts); TAILQ_INIT(&nsjconf->mountpts);
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304"; static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";

10
net.cc
View File

@ -164,15 +164,13 @@ bool limitConns(struct nsjconf_t* nsjconf, int connsock) {
char cs_addr[64]; char cs_addr[64];
connToText(connsock, true /* remote */, cs_addr, sizeof(cs_addr), &addr); connToText(connsock, true /* remote */, cs_addr, sizeof(cs_addr), &addr);
unsigned int cnt = 0; unsigned cnt = 0;
struct pids_t* p; for (const auto& pid : nsjconf->pids) {
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { if (memcmp(addr.sin6_addr.s6_addr, pid.remote_addr.sin6_addr.s6_addr,
if (memcmp(addr.sin6_addr.s6_addr, p->remote_addr.sin6_addr.s6_addr, sizeof(pid.remote_addr.sin6_addr.s6_addr)) == 0) {
sizeof(p->remote_addr.sin6_addr.s6_addr)) == 0) {
cnt++; cnt++;
} }
} }
if (cnt >= nsjconf->max_conns_per_ip) { if (cnt >= nsjconf->max_conns_per_ip) {
LOG_W("Rejecting connection from '%s', max_conns_per_ip limit reached: %u", cs_addr, LOG_W("Rejecting connection from '%s', max_conns_per_ip limit reached: %u", cs_addr,
nsjconf->max_conns_per_ip); nsjconf->max_conns_per_ip);

View File

@ -173,10 +173,9 @@ struct nsjconf_t {
struct sock_fprog seccomp_fprog; struct sock_fprog seccomp_fprog;
long num_cpus; long num_cpus;
uid_t orig_uid; uid_t orig_uid;
TAILQ_HEAD(pidslist, pids_t)
pids;
TAILQ_HEAD(mountptslist, mounts_t) TAILQ_HEAD(mountptslist, mounts_t)
mountpts; mountpts;
std::vector<pids_t> pids;
std::vector<idmap_t> uids; std::vector<idmap_t> uids;
std::vector<idmap_t> gids; std::vector<idmap_t> gids;
std::vector<std::string> envs; std::vector<std::string> envs;

View File

@ -197,61 +197,53 @@ static int subprocNewProc(
} }
static void addProc(struct nsjconf_t* nsjconf, pid_t pid, int sock) { static void addProc(struct nsjconf_t* nsjconf, pid_t pid, int sock) {
struct pids_t* p = reinterpret_cast<struct pids_t*>(util::memAlloc(sizeof(struct pids_t))); struct pids_t p;
p->pid = pid; p.pid = pid;
p->start = time(NULL); p.start = time(NULL);
net::connToText( net::connToText(
sock, true /* remote */, p->remote_txt, sizeof(p->remote_txt), &p->remote_addr); sock, true /* remote */, p.remote_txt, sizeof(p.remote_txt), &p.remote_addr);
char fname[PATH_MAX]; char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/syscall", (int)pid); snprintf(fname, sizeof(fname), "/proc/%d/syscall", (int)pid);
p->pid_syscall_fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); p.pid_syscall_fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
TAILQ_INSERT_HEAD(&nsjconf->pids, p, pointers); nsjconf->pids.push_back(p);
LOG_D("Added pid '%d' with start time '%u' to the queue for IP: '%s'", pid, LOG_D("Added pid '%d' with start time '%u' to the queue for IP: '%s'", p.pid,
(unsigned int)p->start, p->remote_txt); (unsigned int)p.start, p.remote_txt);
} }
static void removeProc(struct nsjconf_t* nsjconf, pid_t pid) { static void removeProc(struct nsjconf_t* nsjconf, pid_t pid) {
struct pids_t* p; for (auto p = nsjconf->pids.begin(); p != nsjconf->pids.end(); ++p) {
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
if (p->pid == pid) { if (p->pid == pid) {
LOG_D("Removing pid '%d' from the queue (IP:'%s', start time:'%s')", p->pid, LOG_D("Removing pid '%d' from the queue (IP:'%s', start time:'%s')", p->pid,
p->remote_txt, util::timeToStr(p->start)); p->remote_txt, util::timeToStr(p->start));
close(p->pid_syscall_fd); close(p->pid_syscall_fd);
TAILQ_REMOVE(&nsjconf->pids, p, pointers); nsjconf->pids.erase(p);
free(p);
return; return;
} }
} }
LOG_W("PID: %d not found (?)", pid); LOG_W("PID: %d not found (?)", pid);
} }
int countProc(struct nsjconf_t* nsjconf) { int countProc(struct nsjconf_t* nsjconf) { return nsjconf->pids.size(); }
int cnt = 0;
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { cnt++; }
return cnt;
}
void displayProc(struct nsjconf_t* nsjconf) { void displayProc(struct nsjconf_t* nsjconf) {
LOG_I("Total number of spawned namespaces: %d", countProc(nsjconf)); LOG_I("Total number of spawned namespaces: %d", countProc(nsjconf));
time_t now = time(NULL); time_t now = time(NULL);
struct pids_t* p; for (const auto& pid : nsjconf->pids) {
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { time_t diff = now - pid.start;
time_t diff = now - p->start;
time_t left = nsjconf->tlimit ? nsjconf->tlimit - diff : 0; time_t left = nsjconf->tlimit ? nsjconf->tlimit - diff : 0;
LOG_I("PID: %d, Remote host: %s, Run time: %ld sec. (time left: %ld sec.)", p->pid, LOG_I("PID: %d, Remote host: %s, Run time: %ld sec. (time left: %ld sec.)", pid.pid,
p->remote_txt, (long)diff, (long)left); pid.remote_txt, (long)diff, (long)left);
} }
} }
static struct pids_t* getPidElem(struct nsjconf_t* nsjconf, pid_t pid) { static const struct pids_t* getPidElem(struct nsjconf_t* nsjconf, pid_t pid) {
struct pids_t* p; for (const auto& p : nsjconf->pids) {
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { if (p.pid == pid) {
if (p->pid == pid) { return &p;
return p;
} }
} }
return NULL; return NULL;
@ -260,7 +252,7 @@ static struct pids_t* getPidElem(struct nsjconf_t* nsjconf, pid_t pid) {
static void seccompViolation(struct nsjconf_t* nsjconf, siginfo_t* si) { static void seccompViolation(struct nsjconf_t* nsjconf, siginfo_t* si) {
LOG_W("PID: %d commited a syscall/seccomp violation and exited with SIGSYS", si->si_pid); LOG_W("PID: %d commited a syscall/seccomp violation and exited with SIGSYS", si->si_pid);
struct pids_t* p = getPidElem(nsjconf, si->si_pid); const struct pids_t* p = getPidElem(nsjconf, si->si_pid);
if (p == NULL) { if (p == NULL) {
LOG_W("PID:%d SiSyscall: %d, SiCode: %d, SiErrno: %d", (int)si->si_pid, LOG_W("PID:%d SiSyscall: %d, SiCode: %d, SiErrno: %d", (int)si->si_pid,
si->si_syscall, si->si_code, si->si_errno); si->si_syscall, si->si_code, si->si_errno);
@ -317,7 +309,7 @@ int reapProc(struct nsjconf_t* nsjconf) {
cgroup::finishFromParent(nsjconf, si.si_pid); cgroup::finishFromParent(nsjconf, si.si_pid);
const char* remote_txt = "[UNKNOWN]"; const char* remote_txt = "[UNKNOWN]";
struct pids_t* elem = getPidElem(nsjconf, si.si_pid); const struct pids_t* elem = getPidElem(nsjconf, si.si_pid);
if (elem) { if (elem) {
remote_txt = elem->remote_txt; remote_txt = elem->remote_txt;
} }
@ -344,16 +336,15 @@ int reapProc(struct nsjconf_t* nsjconf) {
} }
time_t now = time(NULL); time_t now = time(NULL);
struct pids_t* p; for (const auto& p : nsjconf->pids) {
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
if (nsjconf->tlimit == 0) { if (nsjconf->tlimit == 0) {
continue; continue;
} }
pid_t pid = p->pid; pid_t pid = p.pid;
time_t diff = now - p->start; time_t diff = now - p.start;
if (diff >= nsjconf->tlimit) { if (diff >= nsjconf->tlimit) {
LOG_I("PID: %d run time >= time limit (%ld >= %ld) (%s). Killing it", pid, LOG_I("PID: %d run time >= time limit (%ld >= %ld) (%s). Killing it", pid,
(long)diff, (long)nsjconf->tlimit, p->remote_txt); (long)diff, (long)nsjconf->tlimit, p.remote_txt);
/* /*
* Probably a kernel bug - some processes cannot be killed with KILL if * Probably a kernel bug - some processes cannot be killed with KILL if
* they're namespaced, and in a stopped state * they're namespaced, and in a stopped state
@ -368,8 +359,9 @@ int reapProc(struct nsjconf_t* nsjconf) {
} }
void killAll(struct nsjconf_t* nsjconf) { void killAll(struct nsjconf_t* nsjconf) {
struct pids_t* p; for (const auto& p : nsjconf->pids) {
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { kill(p->pid, SIGKILL); } kill(p.pid, SIGKILL);
}
} }
static bool initParent(struct nsjconf_t* nsjconf, pid_t pid, int pipefd) { static bool initParent(struct nsjconf_t* nsjconf, pid_t pid, int pipefd) {