mount: nonmandatory mounts

This commit is contained in:
Robert Swiecki 2017-05-27 15:17:11 +02:00
parent f0cb243a89
commit ec50c1346d
8 changed files with 114 additions and 45 deletions

View File

@ -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);
}

View File

@ -71,6 +71,7 @@ struct mounts_t {
const char *options;
uintptr_t flags;
bool isDir;
bool mandatory;
TAILQ_ENTRY(mounts_t) pointers;
};

View File

@ -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'",

View 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,

View 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;

View 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 */

View 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 {

13
mount.c
View File

@ -159,14 +159,17 @@ 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 true;
}
@ -193,9 +196,11 @@ 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));
PLOG_W("mount('%s', flags:%s)", mpt->dst, mountFlagsToStr(new_flags));
if (mpt->mandatory) {
return false;
}
}
return true;
}