diff --git a/configure.ac b/configure.ac index da6bf73f..87a9306a 100644 --- a/configure.ac +++ b/configure.ac @@ -278,6 +278,28 @@ AC_LIB_HAVE_LINKFLAGS(seccomp,, [#include ], [seccomp_init(0);]) fi fi +AC_ARG_ENABLE(linux-namespaces, + AS_HELP_STRING([--disable-linux-namespaces], [disable support for different namespaces in Linux]), + linux_ns_enabled=$enableval, linux_ns_enabled=yes) + +if [ test "$linux_ns_enabled" = "yes" ];then +AC_MSG_CHECKING([for Linux namespaces]) +dnl We use Linux namespaces only in the platforms clone() works as expected +AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include ],[ + #if defined(__i386__) || defined(__arm__) || defined(__x86_64__) || defined(__mips__) + unshare(CLONE_NEWPID|CLONE_NEWIPC); + #else + # error 1 + #endif])], + [AC_MSG_RESULT(yes) + AC_DEFINE([ENABLE_LINUX_NS], 1, [Enable Linux namespaces support]) + linux_ns_enabled=yes], + [AC_MSG_RESULT(no) + linux_ns_enabled=no +]) +fi + AC_ARG_ENABLE(systemd, AS_HELP_STRING([--disable-systemd], [disable systemd support]), systemd_enabled=$enableval, systemd_enabled=yes) @@ -429,6 +451,7 @@ AC_MSG_NOTICE([ Experimental options: seccomp: ${seccomp_enabled} + Linux namespaces: ${linux_ns_enabled} Anyconnect compat: ${anyconnect_enabled} ]) diff --git a/src/config.c b/src/config.c index 0c330656..c2bca6ba 100644 --- a/src/config.c +++ b/src/config.c @@ -937,6 +937,9 @@ void print_version(tOptions *opts, tOptDesc *desc) #ifdef HAVE_LIBSECCOMP fprintf(stderr, "seccomp, "); #endif +#ifdef ENABLE_LINUX_NS + fprintf(stderr, "Linux-NS, "); +#endif #ifdef HAVE_LIBWRAP fprintf(stderr, "tcp-wrappers, "); #endif diff --git a/src/main.c b/src/main.c index 27da4ac5..b5238f63 100644 --- a/src/main.c +++ b/src/main.c @@ -1122,7 +1122,7 @@ int main(int argc, char** argv) break; } - pid = fork(); + pid = safe_fork(); if (pid == 0) { /* child */ /* close any open descriptors, and erase * sensitive data before running the worker @@ -1168,6 +1168,7 @@ int main(int argc, char** argv) exit(0); } else if (pid == -1) { fork_failed: + mslog(s, NULL, LOG_ERR, "fork failed"); close(cmd_fd[0]); } else { /* parent */ /* add_proc */ diff --git a/src/system.c b/src/system.c index bf9c800c..6bae46d7 100644 --- a/src/system.c +++ b/src/system.c @@ -21,6 +21,8 @@ #include #ifdef __linux__ # include +# include +# include #endif #include #include @@ -49,6 +51,20 @@ void pr_set_undumpable(const char *mod) #endif } +pid_t safe_fork(void) +{ +#if defined(__linux__) && defined(ENABLE_LINUX_NS) + long ret; + int flags = SIGCHLD|CLONE_NEWPID|CLONE_NEWNET|CLONE_NEWIPC; + ret = syscall(SYS_clone, flags, 0, 0, 0); + if (ret == 0 && syscall(SYS_getpid)!= 1) + return -1; + return ret; +#else + return fork(); +#endif +} + SIGHANDLER_T ocsignal(int signum, SIGHANDLER_T handler) { struct sigaction new_action, old_action; diff --git a/src/system.h b/src/system.h index dbe532e0..b21da8df 100644 --- a/src/system.h +++ b/src/system.h @@ -36,6 +36,7 @@ typedef void (*sighandler_t)(int); # define SIGHANDLER_T sighandler_t #endif +pid_t safe_fork(void); void pr_set_undumpable(const char* mod); void kill_on_parent_kill(int sig);