mount: more extensive search for suitable root dir
authorRobert Swiecki <robert@swiecki.net>
Wed, 21 Jun 2017 17:18:02 +0000 (19:18 +0200)
committerRobert Swiecki <robert@swiecki.net>
Wed, 21 Jun 2017 17:18:02 +0000 (19:18 +0200)
contain.c
mount.c
util.c

index 938fd1826a7e86ed63f6c93c7a6c226b0a9dcaf5..fc0a5304e37012bcd9dcab951f6b918315b7b995 100644 (file)
--- a/contain.c
+++ b/contain.c
@@ -357,9 +357,6 @@ bool containSetupFD(struct nsjconf_t * nsjconf, int fd_in, int fd_out, int fd_er
 
 bool containContain(struct nsjconf_t * nsjconf)
 {
-       if (containCPU(nsjconf) == false) {
-               return false;
-       }
        if (containUserNs(nsjconf) == false) {
                return false;
        }
@@ -383,6 +380,9 @@ bool containContain(struct nsjconf_t * nsjconf)
        }
        /* */
        /* As non-root */
+       if (containCPU(nsjconf) == false) {
+               return false;
+       }
        if (containSetLimits(nsjconf) == false) {
                return false;
        }
diff --git a/mount.c b/mount.c
index 296b50bea48f3c167cb3f2704e4b5889381c5be2..75b2706128d70c459e3663102fe8f9c568d97661 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -234,6 +234,49 @@ static bool mountRemountRO(struct mounts_t *mpt)
        return true;
 }
 
+static bool mountMkdirAndTest(const char *dir)
+{
+       if (mkdir(dir, 0755) == -1 && errno != EEXIST) {
+               PLOG_W("Couldn't create '%s' directory", dir);
+               return false;
+       }
+       if (access(dir, R_OK) == -1) {
+               PLOG_W("access('%s', R_OK)", dir);
+               return false;
+       }
+       LOG_D("Created accessible directory in '%s'", dir);
+       return true;
+}
+
+static bool mountGetDirs(struct nsjconf_t *nsjconf, char *destdir, char *tmpdir)
+{
+       snprintf(destdir, PATH_MAX, "/tmp/nsjail.root.%d", (int)nsjconf->orig_euid);
+       if (!mountMkdirAndTest(destdir)) {
+               snprintf(destdir, PATH_MAX, "/tmp/nsjail.root");
+               if (!mountMkdirAndTest(destdir)) {
+                       snprintf(destdir, PATH_MAX, "/tmp/nsjail.root.%" PRIx64, utilRnd64());
+                       if (!mountMkdirAndTest(destdir)) {
+                               LOG_E("Couldn't create directory for ROOT fs");
+                               return false;
+                       }
+               }
+       }
+
+       snprintf(tmpdir, PATH_MAX, "/tmp/nsjail.tmp.%d", (int)nsjconf->orig_euid);
+       if (!mountMkdirAndTest(tmpdir)) {
+               snprintf(tmpdir, PATH_MAX, "/tmp/nsjail.tmp");
+               if (!mountMkdirAndTest(tmpdir)) {
+                       snprintf(tmpdir, PATH_MAX, "/tmp/nsjail.tmp.%" PRIx64, utilRnd64());
+                       if (!mountMkdirAndTest(tmpdir)) {
+                               LOG_E("Couldn't create a directory for TMP files");
+                               return false;
+                       }
+               }
+       }
+
+       return true;
+}
+
 static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
 {
        if (nsjconf->clone_newns == false) {
@@ -255,22 +298,17 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
        }
 
        char destdir[PATH_MAX];
-       snprintf(destdir, sizeof(destdir), "/tmp/nsjail.root.%d", (int)nsjconf->orig_euid);
-       if (mkdir(destdir, 0755) == -1 && errno != EEXIST) {
-               PLOG_E("Couldn't create '%s' directory. Maybe remove it?", destdir);
+       char tmpdir[PATH_MAX];
+       if (mountGetDirs(nsjconf, destdir, tmpdir) == false) {
+               LOG_E("Couldn't obtain temporary mount directories");
                return false;
        }
+
        if (mount(NULL, destdir, "tmpfs", 0, "size=16777216") == -1) {
                PLOG_E("mount('%s', 'tmpfs')", destdir);
                return false;
        }
 
-       char tmpdir[PATH_MAX];
-       snprintf(tmpdir, sizeof(tmpdir), "/tmp/nsjail.tmp.%d", (int)nsjconf->orig_euid);
-       if (mkdir(tmpdir, 0755) == -1 && errno != EEXIST) {
-               PLOG_E("Couldn't create '%s' directory. Maybe remove it?", tmpdir);
-               return false;
-       }
        if (mount(NULL, tmpdir, "tmpfs", 0, "size=16777216") == -1) {
                PLOG_E("mount('%s', 'tmpfs')", tmpdir);
                return false;
diff --git a/util.c b/util.c
index 58c7c93ebbfc4f285d211dc6186ce99162a0a25b..390c4cfeeb78c6c4dbd5be1ed2408cdccf45626a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <time.h>
 
@@ -226,9 +227,18 @@ static const uint64_t c = 1442695040888963407ULL;
 
 static void utilRndInitThread(void)
 {
+#if defined(__NR_getrandom)
+       if (syscall(__NR_getrandom, &rndX, sizeof(rndX), 0) == sizeof(rndX)) {
+               return;
+       }
+#endif                         /* defined(__NR_getrandom) */
        int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
        if (fd == -1) {
-               PLOG_F("Couldn't open /dev/urandom for reading");
+               PLOG_D("Couldn't open /dev/urandom for reading");
+               struct timeval tv;
+               gettimeofday(&tv, NULL);
+               rndX = tv.tv_usec + ((uint64_t) tv.tv_sec << 32);
+               return;
        }
        if (utilReadFromFd(fd, (uint8_t *) & rndX, sizeof(rndX)) != sizeof(rndX)) {
                PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));