diff --git a/cmdline.c b/cmdline.c index e7f0490..c245f06 100644 --- a/cmdline.c +++ b/cmdline.c @@ -275,7 +275,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) .is_root_rw = false, .is_silent = false, .skip_setsid = false, - .iface = NULL, .inside_uid = getuid(), .inside_gid = getgid(), .outside_uid = getuid(), @@ -283,6 +282,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) .max_conns_per_ip = 0, .tmpfs_size = 4 * (1024 * 1024), .mount_proc = true, + .iface = NULL, + .iface_lo_up = false, .sbinip_fd = -1, }; /* *INDENT-OFF* */ @@ -346,6 +347,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) {{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"}, {{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"}, {{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVTAP) and put inside the subprocess' namespace"}, + {{"iface_lo_up", no_argument, NULL, 0x700}, "Bring up the 'lo' interface"}, {{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"}, {{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"}, {{0, 0, 0, 0}, NULL}, @@ -555,6 +557,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) case 'I': nsjconf->iface = optarg; break; + case 0x700: + nsjconf->iface_lo_up = true; + break; default: cmdlineUsage(argv[0], custom_opts); return false; diff --git a/common.h b/common.h index 0664538..311cba7 100644 --- a/common.h +++ b/common.h @@ -91,7 +91,6 @@ struct nsjconf_t { bool is_root_rw; bool is_silent; bool skip_setsid; - char *iface; uid_t outside_uid; gid_t outside_gid; uid_t inside_uid; @@ -99,6 +98,8 @@ struct nsjconf_t { unsigned int max_conns_per_ip; size_t tmpfs_size; bool mount_proc; + char *iface; + bool iface_lo_up; int sbinip_fd; TAILQ_HEAD(envlist, charptr_t) envs; TAILQ_HEAD(pidslist, pids_t) pids; diff --git a/contain.c b/contain.c index bd9718c..082f414 100644 --- a/contain.c +++ b/contain.c @@ -43,8 +43,19 @@ #include #include "log.h" +#include "net.h" #include "util.h" +bool containInitNetNs(struct nsjconf_t * nsjconf) +{ + if (nsjconf->iface_lo_up) { + if (netIfaceUp("lo") == false) { + return false; + } + } + return true; +} + static bool containSetGroups(pid_t pid) { /* diff --git a/contain.h b/contain.h index d288f07..2a7ad87 100644 --- a/contain.h +++ b/contain.h @@ -27,6 +27,7 @@ #include "common.h" bool containInitUserNs(struct nsjconf_t *nsjconf, pid_t pid); +bool containInitNetNs(struct nsjconf_t *nsjconf); bool containDropPrivs(struct nsjconf_t *nsjconf); bool containPrepareEnv(struct nsjconf_t *nsjconf); bool containMountFS(struct nsjconf_t *nsjconf); diff --git a/net.c b/net.c index 4638f36..9b76a86 100644 --- a/net.c +++ b/net.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,8 +41,14 @@ #include "log.h" -bool netSystemSbinIp(struct nsjconf_t *nsjconf, char *const *argv) +static bool netSystemSbinIp(struct nsjconf_t *nsjconf, char *const *argv) { + if (nsjconf->clone_newnet == false) { + LOG_W + ("CLONE_NEWNET not enabled. All changes would affect the global networking namespace"); + return false; + } + int pid = fork(); if (pid == -1) { PLOG_E("fork()"); @@ -67,7 +74,7 @@ bool netSystemSbinIp(struct nsjconf_t *nsjconf, char *const *argv) LOG_W("'/sbin/ip' killed with signal: %d", WTERMSIG(status)); return false; } - LOG_E("Unknown exit status for '/sbin/ip' (pid=%d): %d", pid, status); + LOG_W("Unknown exit status for '/sbin/ip' (pid=%d): %d", pid, status); kill(pid, SIGKILL); } } @@ -78,7 +85,7 @@ bool netCloneMacVtapAndNS(struct nsjconf_t * nsjconf, int pid) return true; } - char iface[IFNAMSIZ]; + char iface[IF_NAMESIZE]; snprintf(iface, sizeof(iface), "NS.TAP.%d", pid); char *const argv_add[] = @@ -248,3 +255,32 @@ void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6 snprintf(buf, s, "[%s]:%hu", tmp, ntohs(addr.sin6_port)); return; } + +bool netIfaceUp(const char *ifacename) +{ + int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (sock == -1) { + PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)"); + return false; + } + + struct ifreq ifr; + snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename); + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { + PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP", ifacename); + close(sock); + return false; + } + + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); + + if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { + PLOG_E("ioctl(iface='%s', SIOCSIFFLAGS, IFF_UP", ifacename); + close(sock); + return false; + } + + close(sock); + return true; +} diff --git a/net.h b/net.h index 76121cc..77b1df4 100644 --- a/net.h +++ b/net.h @@ -26,11 +26,11 @@ #include "common.h" -bool netSystemSbinIp(struct nsjconf_t *nsjconf, char *const *argv); bool netCloneMacVtapAndNS(struct nsjconf_t *nsjconf, int pid); bool netLimitConns(struct nsjconf_t *nsjconf, int connsock); int netGetRecvSocket(const char *bindhost, int port); int netAcceptConn(int listenfd); void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6 *addr_or_null); +bool netIfaceUp(const char *ifacename); #endif /* _NET_H */ diff --git a/subproc.c b/subproc.c index 87fd941..a151fc2 100644 --- a/subproc.c +++ b/subproc.c @@ -66,6 +66,9 @@ static int subprocNewProc(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int if (containMountFS(nsjconf) == false) { exit(1); } + if (containInitNetNs(nsjconf) == false) { + exit(1); + } if (containDropPrivs(nsjconf) == false) { exit(1); }