Add --iface_lo_up
authorJagger <robert@swiecki.net>
Sun, 28 Feb 2016 23:14:36 +0000 (00:14 +0100)
committerJagger <robert@swiecki.net>
Sun, 28 Feb 2016 23:14:36 +0000 (00:14 +0100)
cmdline.c
common.h
contain.c
contain.h
net.c
net.h
subproc.c

index e7f0490bd923bcbc00400d108d725e6208080585..c245f068e482ab07d59eec5b92a390ea75f2ce64 100644 (file)
--- 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;
index 066453890179c1c8f4f3e6456542ecc7abebfbfe..311cba71bc54045649679b709c664694a602a73f 100644 (file)
--- 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;
index bd9718cf2a92f86c550f6b9aba7f11ab4367d517..082f41424f5e705ed63bcb101f91b9d189e11a63 100644 (file)
--- a/contain.c
+++ b/contain.c
 #include <unistd.h>
 
 #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)
 {
        /*
index d288f07c23ce88b2dac1306079b0cdb906af2417..2a7ad87a59f167af72da99bd539877f76cac88f9 100644 (file)
--- 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 4638f36016ce647dc49df33ec48f9e344c2b5d96..9b76a865686a1d298d677bc3996fffd67ac9afad 100644 (file)
--- a/net.c
+++ b/net.c
@@ -22,7 +22,7 @@
 
 #include <arpa/inet.h>
 #include <errno.h>
-#include <linux/if.h>
+#include <net/if.h>
 #include <sched.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -31,6 +31,7 @@
 #include <strings.h>
 #include <netinet/ip6.h>
 #include <netinet/tcp.h>
+#include <sys/ioctl.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 
 #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 76121cc50b1debacaf5e2d8a0bfc7b1f05231414..77b1df4bdbe89a8516eeadb6f2576284890f86c1 100644 (file)
--- a/net.h
+++ b/net.h
 
 #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 */
index 87fd9412b8f036fd23677c54ced814ac9d24a3f7..a151fc280761b3e342f62905d735fdcb9af92b85 100644 (file)
--- 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);
        }