mount: nonmandatory mounts
authorRobert Swiecki <robert@swiecki.net>
Sat, 27 May 2017 13:17:11 +0000 (15:17 +0200)
committerRobert Swiecki <robert@swiecki.net>
Sat, 27 May 2017 13:17:11 +0000 (15:17 +0200)
cmdline.c
common.h
config.c
config.pb-c.c
config.pb-c.h
config.proto
configs/config1.example
mount.c

index 85bca46cc4fadcd1499cd7431def7e5ed6de4490..0b6bbaa453b393af7ce534f2c391bf8a4c65f449 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -226,10 +226,10 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
                struct mounts_t *p;
                TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
                        LOG_I
-                           ("Mount point: src:'%s' dst:'%s' type:'%s' flags:%s options:'%s' isDir:%s",
+                           ("Mount point: src:'%s' dst:'%s' type:'%s' flags:%s options:'%s' isDir:%s mandatory:%s",
                             p->src ? p->src : "[NULL]", p->dst, p->fs_type ? p->fs_type : "[NULL]",
                             mountFlagsToStr(p->flags), p->options ? p->options : "[NULL]",
-                            p->isDir ? "True" : "False");
+                            p->isDir ? "true" : "false", p->mandatory ? "true" : "false");
                }
        }
        {
@@ -644,6 +644,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                p->options = "";
                                p->fs_type = "";
                                p->isDir = mountIsDir(optarg);
+                               p->mandatory = true;
                                TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
                        } break;
                case 'B':{
@@ -654,6 +655,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                p->options = "";
                                p->fs_type = "";
                                p->isDir = mountIsDir(optarg);
+                               p->mandatory = true;
                                TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
                        } break;
                case 'T':{
@@ -664,6 +666,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                p->options = cmdlineTmpfsSz;
                                p->fs_type = "tmpfs";
                                p->isDir = true;
+                               p->mandatory = true;
                                TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
                        } break;
                case 'M':
@@ -749,6 +752,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                p->options = "";
                p->fs_type = "proc";
                p->isDir = true;
+               p->mandatory = true;
                TAILQ_INSERT_HEAD(&nsjconf->mountpts, p, pointers);
        }
        if (nsjconf->chroot != NULL) {
@@ -756,24 +760,26 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                p->src = nsjconf->chroot;
                p->dst = "/";
                p->flags = MS_BIND | MS_REC;
-               p->options = "";
-               p->fs_type = "";
-               p->isDir = true;
                if (nsjconf->is_root_rw == false) {
                        p->flags |= MS_RDONLY;
                }
+               p->options = "";
+               p->fs_type = "";
+               p->isDir = true;
+               p->mandatory = true;
                TAILQ_INSERT_HEAD(&nsjconf->mountpts, p, pointers);
        } else {
                struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
                p->src = NULL;
                p->dst = "/";
                p->flags = 0;
-               p->options = "";
-               p->fs_type = "tmpfs";
-               p->isDir = true;
                if (nsjconf->is_root_rw == false) {
                        p->flags |= MS_RDONLY;
                }
+               p->options = "";
+               p->fs_type = "tmpfs";
+               p->isDir = true;
+               p->mandatory = true;
                TAILQ_INSERT_HEAD(&nsjconf->mountpts, p, pointers);
        }
 
index 3ab86ed7e05c90e8eb1911ce398649275b9f95b7..6fb1ab29f6b65bf2bb26a15866ab0e18e076e1c5 100644 (file)
--- a/common.h
+++ b/common.h
@@ -71,6 +71,7 @@ struct mounts_t {
        const char *options;
        uintptr_t flags;
        bool isDir;
+       bool mandatory;
         TAILQ_ENTRY(mounts_t) pointers;
 };
 
index c6932be663896273f868526b0826c51af54f54f2..ea8cd6f6cce3f5589b100dfee4d9a05addfaf7bf 100644 (file)
--- a/config.c
+++ b/config.c
@@ -181,6 +181,7 @@ static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig
                }
        }
 
+       nsjconf->mount_proc = njc->mount_proc;
        for (size_t i = 0; i < njc->n_mount; i++) {
                struct mounts_t *p = utilCalloc(sizeof(struct mounts_t));
                p->src = utilStrDup(njc->mount[i]->src);
@@ -200,11 +201,10 @@ static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig
                                p->isDir = true;
                        }
                }
+               p->mandatory = njc->mount[i]->mandatory;
                TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
        }
 
-       nsjconf->mount_proc = njc->mount_proc;
-
        if (njc->seccomp_policy_file) {
                if ((nsjconf->kafel_file = fopen(njc->seccomp_policy_file, "rb")) == NULL) {
                        PLOG_W("Couldn't open file with seccomp policy '%s'",
index 26fba15aec033416dfef15153018b595e349039e..2fe2fe66ec0fb33a5081c6a9f9b012896936a8bb 100644 (file)
@@ -7,22 +7,26 @@
 #endif
 
 #include "config.pb-c.h"
-void nsjail__id_map__init(Nsjail__IdMap * message) {
+void nsjail__id_map__init(Nsjail__IdMap * message)
+{
        static Nsjail__IdMap init_value = NSJAIL__ID_MAP__INIT;
        *message = init_value;
 }
 
-size_t nsjail__id_map__get_packed_size(const Nsjail__IdMap * message) {
+size_t nsjail__id_map__get_packed_size(const Nsjail__IdMap * message)
+{
        assert(message->base.descriptor == &nsjail__id_map__descriptor);
        return protobuf_c_message_get_packed_size((const ProtobufCMessage *)(message));
 }
 
-size_t nsjail__id_map__pack(const Nsjail__IdMap * message, uint8_t * out) {
+size_t nsjail__id_map__pack(const Nsjail__IdMap * message, uint8_t * out)
+{
        assert(message->base.descriptor == &nsjail__id_map__descriptor);
        return protobuf_c_message_pack((const ProtobufCMessage *)message, out);
 }
 
-size_t nsjail__id_map__pack_to_buffer(const Nsjail__IdMap * message, ProtobufCBuffer * buffer) {
+size_t nsjail__id_map__pack_to_buffer(const Nsjail__IdMap * message, ProtobufCBuffer * buffer)
+{
        assert(message->base.descriptor == &nsjail__id_map__descriptor);
        return protobuf_c_message_pack_to_buffer((const ProtobufCMessage *)message, buffer);
 }
@@ -33,27 +37,32 @@ Nsjail__IdMap *nsjail__id_map__unpack
            protobuf_c_message_unpack(&nsjail__id_map__descriptor, allocator, len, data);
 }
 
-void nsjail__id_map__free_unpacked(Nsjail__IdMap * message, ProtobufCAllocator * allocator) {
+void nsjail__id_map__free_unpacked(Nsjail__IdMap * message, ProtobufCAllocator * allocator)
+{
        assert(message->base.descriptor == &nsjail__id_map__descriptor);
        protobuf_c_message_free_unpacked((ProtobufCMessage *) message, allocator);
 }
 
-void nsjail__mount_pt__init(Nsjail__MountPt * message) {
+void nsjail__mount_pt__init(Nsjail__MountPt * message)
+{
        static Nsjail__MountPt init_value = NSJAIL__MOUNT_PT__INIT;
        *message = init_value;
 }
 
-size_t nsjail__mount_pt__get_packed_size(const Nsjail__MountPt * message) {
+size_t nsjail__mount_pt__get_packed_size(const Nsjail__MountPt * message)
+{
        assert(message->base.descriptor == &nsjail__mount_pt__descriptor);
        return protobuf_c_message_get_packed_size((const ProtobufCMessage *)(message));
 }
 
-size_t nsjail__mount_pt__pack(const Nsjail__MountPt * message, uint8_t * out) {
+size_t nsjail__mount_pt__pack(const Nsjail__MountPt * message, uint8_t * out)
+{
        assert(message->base.descriptor == &nsjail__mount_pt__descriptor);
        return protobuf_c_message_pack((const ProtobufCMessage *)message, out);
 }
 
-size_t nsjail__mount_pt__pack_to_buffer(const Nsjail__MountPt * message, ProtobufCBuffer * buffer) {
+size_t nsjail__mount_pt__pack_to_buffer(const Nsjail__MountPt * message, ProtobufCBuffer * buffer)
+{
        assert(message->base.descriptor == &nsjail__mount_pt__descriptor);
        return protobuf_c_message_pack_to_buffer((const ProtobufCMessage *)message, buffer);
 }
@@ -64,52 +73,62 @@ Nsjail__MountPt *nsjail__mount_pt__unpack
            protobuf_c_message_unpack(&nsjail__mount_pt__descriptor, allocator, len, data);
 }
 
-void nsjail__mount_pt__free_unpacked(Nsjail__MountPt * message, ProtobufCAllocator * allocator) {
+void nsjail__mount_pt__free_unpacked(Nsjail__MountPt * message, ProtobufCAllocator * allocator)
+{
        assert(message->base.descriptor == &nsjail__mount_pt__descriptor);
        protobuf_c_message_free_unpacked((ProtobufCMessage *) message, allocator);
 }
 
-void nsjail__exe__init(Nsjail__Exe * message) {
+void nsjail__exe__init(Nsjail__Exe * message)
+{
        static Nsjail__Exe init_value = NSJAIL__EXE__INIT;
        *message = init_value;
 }
 
-size_t nsjail__exe__get_packed_size(const Nsjail__Exe * message) {
+size_t nsjail__exe__get_packed_size(const Nsjail__Exe * message)
+{
        assert(message->base.descriptor == &nsjail__exe__descriptor);
        return protobuf_c_message_get_packed_size((const ProtobufCMessage *)(message));
 }
 
-size_t nsjail__exe__pack(const Nsjail__Exe * message, uint8_t * out) {
+size_t nsjail__exe__pack(const Nsjail__Exe * message, uint8_t * out)
+{
        assert(message->base.descriptor == &nsjail__exe__descriptor);
        return protobuf_c_message_pack((const ProtobufCMessage *)message, out);
 }
 
-size_t nsjail__exe__pack_to_buffer(const Nsjail__Exe * message, ProtobufCBuffer * buffer) {
+size_t nsjail__exe__pack_to_buffer(const Nsjail__Exe * message, ProtobufCBuffer * buffer)
+{
        assert(message->base.descriptor == &nsjail__exe__descriptor);
        return protobuf_c_message_pack_to_buffer((const ProtobufCMessage *)message, buffer);
 }
 
-Nsjail__Exe *nsjail__exe__unpack(ProtobufCAllocator * allocator, size_t len, const uint8_t * data) {
+Nsjail__Exe *nsjail__exe__unpack(ProtobufCAllocator * allocator, size_t len, const uint8_t * data)
+{
        return (Nsjail__Exe *)
            protobuf_c_message_unpack(&nsjail__exe__descriptor, allocator, len, data);
 }
 
-void nsjail__exe__free_unpacked(Nsjail__Exe * message, ProtobufCAllocator * allocator) {
+void nsjail__exe__free_unpacked(Nsjail__Exe * message, ProtobufCAllocator * allocator)
+{
        assert(message->base.descriptor == &nsjail__exe__descriptor);
        protobuf_c_message_free_unpacked((ProtobufCMessage *) message, allocator);
 }
 
-void nsjail__ns_jail_config__init(Nsjail__NsJailConfig * message) {
+void nsjail__ns_jail_config__init(Nsjail__NsJailConfig * message)
+{
        static Nsjail__NsJailConfig init_value = NSJAIL__NS_JAIL_CONFIG__INIT;
        *message = init_value;
 }
 
-size_t nsjail__ns_jail_config__get_packed_size(const Nsjail__NsJailConfig * message) {
+size_t nsjail__ns_jail_config__get_packed_size(const Nsjail__NsJailConfig * message)
+{
        assert(message->base.descriptor == &nsjail__ns_jail_config__descriptor);
        return protobuf_c_message_get_packed_size((const ProtobufCMessage *)(message));
 }
 
-size_t nsjail__ns_jail_config__pack(const Nsjail__NsJailConfig * message, uint8_t * out) {
+size_t nsjail__ns_jail_config__pack(const Nsjail__NsJailConfig * message, uint8_t * out)
+{
        assert(message->base.descriptor == &nsjail__ns_jail_config__descriptor);
        return protobuf_c_message_pack((const ProtobufCMessage *)message, out);
 }
@@ -214,10 +233,12 @@ const ProtobufCMessageDescriptor nsjail__id_map__descriptor = {
        NULL, NULL, NULL        /* reserved[123] */
 };
 
+char nsjail__mount_pt__fstype__default_value[] = "";
 char nsjail__mount_pt__options__default_value[] = "";
 static const protobuf_c_boolean nsjail__mount_pt__is_bind__default_value = 0;
 static const protobuf_c_boolean nsjail__mount_pt__is_ro__default_value = 0;
-static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[7] = {
+static const protobuf_c_boolean nsjail__mount_pt__mandatory__default_value = 1;
+static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[8] = {
        {
         "src",
         1,
@@ -250,7 +271,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[7] = {
         0,                     /* quantifier_offset */
         offsetof(Nsjail__MountPt, fstype),
         NULL,
-        NULL,
+        &nsjail__mount_pt__fstype__default_value,
         0,                     /* flags */
         0, NULL, NULL          /* reserved1,reserved2, etc */
         },
@@ -302,6 +323,18 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[7] = {
         0,                     /* flags */
         0, NULL, NULL          /* reserved1,reserved2, etc */
         },
+       {
+        "mandatory",
+        8,
+        PROTOBUF_C_LABEL_REQUIRED,
+        PROTOBUF_C_TYPE_BOOL,
+        0,                     /* quantifier_offset */
+        offsetof(Nsjail__MountPt, mandatory),
+        NULL,
+        &nsjail__mount_pt__mandatory__default_value,
+        0,                     /* flags */
+        0, NULL, NULL          /* reserved1,reserved2, etc */
+        },
 };
 
 static const unsigned nsjail__mount_pt__field_indices_by_name[] = {
@@ -310,13 +343,14 @@ static const unsigned nsjail__mount_pt__field_indices_by_name[] = {
        4,                      /* field[4] = is_bind */
        6,                      /* field[6] = is_dir */
        5,                      /* field[5] = is_ro */
+       7,                      /* field[7] = mandatory */
        3,                      /* field[3] = options */
        0,                      /* field[0] = src */
 };
 
 static const ProtobufCIntRange nsjail__mount_pt__number_ranges[1 + 1] = {
        {1, 0},
-       {0, 7}
+       {0, 8}
 };
 
 const ProtobufCMessageDescriptor nsjail__mount_pt__descriptor = {
@@ -326,7 +360,7 @@ const ProtobufCMessageDescriptor nsjail__mount_pt__descriptor = {
        "Nsjail__MountPt",
        "nsjail",
        sizeof(Nsjail__MountPt),
-       7,
+       8,
        nsjail__mount_pt__field_descriptors,
        nsjail__mount_pt__field_indices_by_name,
        1, nsjail__mount_pt__number_ranges,
index 302aa387085634ff771a3ccb655ad7995fb20518..35a549ecc054e44e14d8d27496207ac8791035fb 100644 (file)
@@ -101,11 +101,16 @@ struct _Nsjail__MountPt {
         */
        protobuf_c_boolean has_is_dir;
        protobuf_c_boolean is_dir;
+       /*
+        * Should the sandboxing fail if we cannot mount this resource? 
+        */
+       protobuf_c_boolean mandatory;
 };
+extern char nsjail__mount_pt__fstype__default_value[];
 extern char nsjail__mount_pt__options__default_value[];
 #define NSJAIL__MOUNT_PT__INIT \
  { PROTOBUF_C_MESSAGE_INIT (&nsjail__mount_pt__descriptor) \
-    , NULL, NULL, NULL, nsjail__mount_pt__options__default_value, 0, 0, 0,0 }
+    , NULL, NULL, nsjail__mount_pt__fstype__default_value, nsjail__mount_pt__options__default_value, 0, 0, 0,0, 1 }
 
 struct _Nsjail__Exe {
        ProtobufCMessage base;
index 6f9286709777a3f51b303ea5d8b2319306ad75f2..53d6a897fcea65d2962b4034065b9d08149e0c53 100644 (file)
@@ -41,6 +41,8 @@ message MountPt
     /* Is it directory? If not specified an internal
         * heuristics will be used to determine that */
     optional bool is_dir = 7;
+       /* Should the sandboxing fail if we cannot mount this resource? */
+       required bool mandatory = 8 [default = true];
 }
 message Exe
 {
@@ -132,11 +134,11 @@ message NsJailConfig
     repeated IdMap uidmap = 41;
     repeated IdMap gidmap = 42;
 
+    /* Should /proc be mounted? One can also force this in the 'mount' */
+    required bool mount_proc = 43 [ default = true ];
     /* Mount points inside the jail. See the description for 'msg MountPt'
           for more */
-    repeated MountPt mount = 43;
-    /* Should /proc be mounted? One can also force this in the 'mount' */
-    required bool mount_proc = 44 [ default = true ];
+    repeated MountPt mount = 44;
 
     /* Kafel seccomp policy file or string.
           Homepage of the project: https://github.com/google/kafel */
index 096b29bb89a8718e8fdbe21cd46db17601b32553..5077ddb9f41c0e295fa69cc30cbf9b3b8845e714 100644 (file)
@@ -25,7 +25,7 @@ rlimit_as: 128
 rlimit_core: 0
 rlimit_cpu: 10
 rlimit_fsize: 0
-rlimit_nofile: 5
+rlimit_nofile: 32
 rlimit_stack: 1
 
 persona_addr_compat_layout: false
@@ -54,6 +54,8 @@ gidmap {
        count: 1
 }
 
+mount_proc: false
+
 mount {
        src: "/lib"
        dst: "/lib"
@@ -94,6 +96,15 @@ mount {
        dst: "/lib64"
        is_bind: true
        is_ro: true
+       mandatory: false
+}
+
+mount {
+       src: "/lib32"
+       dst: "/lib32"
+       is_bind: true
+       is_ro: true
+       mandatory: false
 }
 
 mount {
@@ -124,7 +135,12 @@ mount {
        is_ro: true
 }
 
-mount_proc: false
+mount {
+       src: "/nonexistent_777"
+       dst: "/nonexistent_777"
+       is_bind: true
+       mandatory: false
+}
 
 seccomp_string: "
        POLICY example {
diff --git a/mount.c b/mount.c
index 2fe5891d7d3d96426da1827414ce82f62623faf5..6421fdb7e3cea7250a82e6a7ebaa1bb09f8b1ab7 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -159,13 +159,16 @@ static bool mountMount(struct nsjconf_t *nsjconf, struct mounts_t *mpt, const ch
        unsigned long flags = mpt->flags & ~(MS_RDONLY);
        if (mount(srcpath, dst, mpt->fs_type, flags, mpt->options) == -1) {
                if (errno == EACCES) {
-                       PLOG_E
+                       PLOG_W
                            ("mount('%s', '%s', type='%s') failed. Try fixing this problem by applying 'chmod o+x' to the '%s' directory and its ancestors",
-                            srcpath, dst, mpt->fs_type, nsjconf->chroot);
+                            srcpath, dst, mpt->fs_type ? mpt->fs_type : "[NULL]", nsjconf->chroot);
                } else {
-                       PLOG_E("mount('%s', '%s', type='%s') failed", srcpath, dst, mpt->fs_type);
+                       PLOG_W("mount('%s', '%s', type='%s') failed", srcpath, dst,
+                              mpt->fs_type ? mpt->fs_type : "[NULL]");
+               }
+               if (mpt->mandatory) {
+                       return false;
                }
-               return false;
        }
        return true;
 }
@@ -193,8 +196,10 @@ static bool mountRemountRO(struct mounts_t *mpt)
              mountFlagsToStr(vfs.f_flag), mountFlagsToStr(new_flags));
 
        if (mount(mpt->dst, mpt->dst, NULL, new_flags, 0) == -1) {
-               PLOG_E("mount('%s', flags:%s)", mpt->dst, mountFlagsToStr(new_flags));
-               return false;
+               PLOG_W("mount('%s', flags:%s)", mpt->dst, mountFlagsToStr(new_flags));
+               if (mpt->mandatory) {
+                       return false;
+               }
        }
 
        return true;