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(STDERR_FILENO);
TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts);
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];
connToText(connsock, true /* remote */, cs_addr, sizeof(cs_addr), &addr);
unsigned int cnt = 0;
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
if (memcmp(addr.sin6_addr.s6_addr, p->remote_addr.sin6_addr.s6_addr,
sizeof(p->remote_addr.sin6_addr.s6_addr)) == 0) {
unsigned cnt = 0;
for (const auto& pid : nsjconf->pids) {
if (memcmp(addr.sin6_addr.s6_addr, pid.remote_addr.sin6_addr.s6_addr,
sizeof(pid.remote_addr.sin6_addr.s6_addr)) == 0) {
cnt++;
}
}
if (cnt >= nsjconf->max_conns_per_ip) {
LOG_W("Rejecting connection from '%s', max_conns_per_ip limit reached: %u", cs_addr,
nsjconf->max_conns_per_ip);

View File

@ -173,10 +173,9 @@ struct nsjconf_t {
struct sock_fprog seccomp_fprog;
long num_cpus;
uid_t orig_uid;
TAILQ_HEAD(pidslist, pids_t)
pids;
TAILQ_HEAD(mountptslist, mounts_t)
mountpts;
std::vector<pids_t> pids;
std::vector<idmap_t> uids;
std::vector<idmap_t> gids;
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) {
struct pids_t* p = reinterpret_cast<struct pids_t*>(util::memAlloc(sizeof(struct pids_t)));
p->pid = pid;
p->start = time(NULL);
struct pids_t p;
p.pid = pid;
p.start = time(NULL);
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];
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,
(unsigned int)p->start, p->remote_txt);
LOG_D("Added pid '%d' with start time '%u' to the queue for IP: '%s'", p.pid,
(unsigned int)p.start, p.remote_txt);
}
static void removeProc(struct nsjconf_t* nsjconf, pid_t pid) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
for (auto p = nsjconf->pids.begin(); p != nsjconf->pids.end(); ++p) {
if (p->pid == pid) {
LOG_D("Removing pid '%d' from the queue (IP:'%s', start time:'%s')", p->pid,
p->remote_txt, util::timeToStr(p->start));
close(p->pid_syscall_fd);
TAILQ_REMOVE(&nsjconf->pids, p, pointers);
free(p);
nsjconf->pids.erase(p);
return;
}
}
LOG_W("PID: %d not found (?)", pid);
}
int countProc(struct nsjconf_t* nsjconf) {
int cnt = 0;
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { cnt++; }
return cnt;
}
int countProc(struct nsjconf_t* nsjconf) { return nsjconf->pids.size(); }
void displayProc(struct nsjconf_t* nsjconf) {
LOG_I("Total number of spawned namespaces: %d", countProc(nsjconf));
time_t now = time(NULL);
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
time_t diff = now - p->start;
for (const auto& pid : nsjconf->pids) {
time_t diff = now - pid.start;
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,
p->remote_txt, (long)diff, (long)left);
LOG_I("PID: %d, Remote host: %s, Run time: %ld sec. (time left: %ld sec.)", pid.pid,
pid.remote_txt, (long)diff, (long)left);
}
}
static struct pids_t* getPidElem(struct nsjconf_t* nsjconf, pid_t pid) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
if (p->pid == pid) {
return p;
static const struct pids_t* getPidElem(struct nsjconf_t* nsjconf, pid_t pid) {
for (const auto& p : nsjconf->pids) {
if (p.pid == pid) {
return &p;
}
}
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) {
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) {
LOG_W("PID:%d SiSyscall: %d, SiCode: %d, SiErrno: %d", (int)si->si_pid,
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);
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) {
remote_txt = elem->remote_txt;
}
@ -344,16 +336,15 @@ int reapProc(struct nsjconf_t* nsjconf) {
}
time_t now = time(NULL);
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
for (const auto& p : nsjconf->pids) {
if (nsjconf->tlimit == 0) {
continue;
}
pid_t pid = p->pid;
time_t diff = now - p->start;
pid_t pid = p.pid;
time_t diff = now - p.start;
if (diff >= nsjconf->tlimit) {
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
* they're namespaced, and in a stopped state
@ -368,8 +359,9 @@ int reapProc(struct nsjconf_t* nsjconf) {
}
void killAll(struct nsjconf_t* nsjconf) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) { kill(p->pid, SIGKILL); }
for (const auto& p : nsjconf->pids) {
kill(p.pid, SIGKILL);
}
}
static bool initParent(struct nsjconf_t* nsjconf, pid_t pid, int pipefd) {