diff --git a/log.c b/log.c index 1117152..3df66ce 100644 --- a/log.c +++ b/log.c @@ -103,8 +103,8 @@ void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt dprintf(log_fd, "%s", logLevels[ll].prefix); } if (logLevels[ll].print_funcline) { - dprintf(log_fd, "[%s][%s][%ld] %s():%d ", timestr, logLevels[ll].descr, - syscall(__NR_getpid), fn, ln); + dprintf(log_fd, "[%s][%s][%d] %s():%d ", timestr, logLevels[ll].descr, + (int)getpid(), fn, ln); } va_list args; diff --git a/pid.c b/pid.c index c53e581..191c076 100644 --- a/pid.c +++ b/pid.c @@ -29,6 +29,7 @@ #include #include "log.h" +#include "subproc.h" bool pidInitNs(struct nsjconf_t *nsjconf) { @@ -38,7 +39,7 @@ bool pidInitNs(struct nsjconf_t *nsjconf) LOG_D("Creating a dummy 'init' process"); - pid_t pid = syscall(__NR_clone, (uintptr_t) CLONE_FS, NULL, NULL, NULL, (uintptr_t) 0); + pid_t pid = subprocClone(CLONE_FS); if (pid == -1) { PLOG_E("Couldn't create a dummy init process"); return false; diff --git a/subproc.c b/subproc.c index b93d968..5f6bbce 100644 --- a/subproc.c +++ b/subproc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -58,11 +59,11 @@ static int subprocNewProc(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int } if (pipefd == -1) { - if (userInitNsFromParent(nsjconf, syscall(__NR_getpid)) == false) { + if (userInitNsFromParent(nsjconf, getpid()) == false) { LOG_E("Couldn't initialize net user namespace"); exit(1); } - if (cgroupInitNsFromParent(nsjconf, syscall(__NR_getpid)) == false) { + if (cgroupInitNsFromParent(nsjconf, getpid()) == false) { LOG_E("Couldn't initialize net user namespace"); exit(1); } @@ -289,6 +290,32 @@ static bool subprocInitParent(struct nsjconf_t *nsjconf, pid_t pid, int pipefd) return true; } +static uint8_t subprocCloneStack[PTHREAD_STACK_MIN * 2]; + +static int subproccloneFunc(void *arg) +{ + jmp_buf *env_ptr = (jmp_buf *) arg; + longjmp(*env_ptr, 1); +} + +// Avoid problem with caching of PID/TID in glibc +pid_t subprocClone(uintptr_t flags) +{ + if (flags & CLONE_VM) { + LOG_E("Cannot use clone(flags & CLONE_VM)"); + return -1; + } + + jmp_buf env; + if (setjmp(env) == 0) { + void *stack_mid = &subprocCloneStack[sizeof(subprocCloneStack) / 2]; + // Parent + return clone(subproccloneFunc, stack_mid, flags, &env, NULL, NULL); + } + // Child + return 0; +} + void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err) { if (netLimitConns(nsjconf, fd_in) == false) { @@ -326,7 +353,7 @@ void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_er int child_fd = sv[0]; int parent_fd = sv[1]; - pid_t pid = syscall(__NR_clone, (uintptr_t) flags, NULL, NULL, NULL, (uintptr_t) 0); + pid_t pid = subprocClone(flags); if (pid == 0) { close(parent_fd); subprocNewProc(nsjconf, fd_in, fd_out, fd_err, child_fd); diff --git a/subproc.h b/subproc.h index fa2d61a..6607b76 100644 --- a/subproc.h +++ b/subproc.h @@ -24,11 +24,15 @@ #include "common.h" +#include +#include + void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err); int subprocCount(struct nsjconf_t *nsjconf); void subprocDisplay(struct nsjconf_t *nsjconf); void subprocKillAll(struct nsjconf_t *nsjconf); int subprocSystem(const char **argv, char **env); +pid_t subprocClone(uintptr_t flags); /* Returns the exit code of the first failing subprocess, or 0 if none fail */ int subprocReap(struct nsjconf_t *nsjconf);