const char *target;
const char *filesystemtype;
unsigned long mountflags;
+ unsigned long propflags;
const char *optstr;
int error;
bool inner;
}
static int do_mount(const char *root, const char *orig_source, const char *target, const char *filesystemtype,
- unsigned long orig_mountflags, const char *optstr, int error, bool inner)
+ unsigned long orig_mountflags, unsigned long propflags, const char *optstr, int error, bool inner)
{
struct stat s;
char new[PATH_MAX];
DEBUG("mount %s%s %s (%s)\n", (mountflags & MS_BIND)?"-B ":"", source, new,
(mountflags & MS_RDONLY)?"ro":"rw");
+ if (propflags && mount(NULL, new, NULL, propflags, NULL)) {
+ if (error)
+ ERROR("failed to mount --make-... %s \n", new);
+
+ if (inner)
+ free(source);
+
+ return error;
+ }
+
if (inner)
free(source);
}
static int _add_mount(const char *source, const char *target, const char *filesystemtype,
- unsigned long mountflags, const char *optstr, int error, bool inner)
+ unsigned long mountflags, unsigned long propflags, const char *optstr,
+ int error, bool inner)
{
assert(target != NULL);
m->optstr = strdup(optstr);
m->mountflags = mountflags;
+ m->propflags = propflags;
m->error = error;
m->inner = inner;
}
int add_mount(const char *source, const char *target, const char *filesystemtype,
- unsigned long mountflags, const char *optstr, int error)
+ unsigned long mountflags, unsigned long propflags, const char *optstr, int error)
{
- return _add_mount(source, target, filesystemtype, mountflags, optstr, error, false);
+ return _add_mount(source, target, filesystemtype, mountflags, propflags, optstr, error, false);
}
int add_mount_inner(const char *source, const char *target, const char *filesystemtype,
- unsigned long mountflags, const char *optstr, int error)
+ unsigned long mountflags, unsigned long propflags, const char *optstr, int error)
{
- return _add_mount(source, target, filesystemtype, mountflags, optstr, error, true);
+ return _add_mount(source, target, filesystemtype, mountflags, propflags, optstr, error, true);
}
int add_mount_bind(const char *path, int readonly, int error)
if (readonly)
mountflags |= MS_RDONLY;
- return add_mount(path, path, NULL, mountflags, NULL, error);
+ return add_mount(path, path, NULL, mountflags, 0, NULL, error);
}
enum {
#define MS_LAZYTIME (1 << 25)
#endif
-static int parseOCImountopts(struct blob_attr *msg, unsigned long *mount_flags, char **mount_data, int *error)
+static int parseOCImountopts(struct blob_attr *msg, unsigned long *mount_flags, unsigned long *propagation_flags, char **mount_data, int *error)
{
struct blob_attr *cur;
int rem;
unsigned long mf = 0;
+ unsigned long pf = 0;
char *tmp;
struct list_head fsopts = LIST_HEAD_INIT(fsopts);
size_t len = 0;
mf |= MS_NOSUID;
else if (!strcmp("remount", tmp))
mf |= MS_REMOUNT;
+ /* propagation flags */
+ else if (!strcmp("private", tmp))
+ pf |= MS_PRIVATE;
+ else if (!strcmp("rprivate", tmp))
+ pf |= MS_PRIVATE | MS_REC;
+ else if (!strcmp("slave", tmp))
+ pf |= MS_SLAVE;
+ else if (!strcmp("rslave", tmp))
+ pf |= MS_SLAVE | MS_REC;
+ else if (!strcmp("shared", tmp))
+ pf |= MS_SHARED;
+ else if (!strcmp("rshared", tmp))
+ pf |= MS_SHARED | MS_REC;
+ else if (!strcmp("unbindable", tmp))
+ pf |= MS_UNBINDABLE;
+ else if (!strcmp("runbindable", tmp))
+ pf |= MS_UNBINDABLE | MS_REC;
+ /* special case: 'nofail' */
else if(!strcmp("nofail", tmp))
*error = 0;
else if (!strcmp("auto", tmp) ||
};
*mount_flags = mf;
+ *propagation_flags = pf;
list_for_each_entry(opt, &fsopts, list) {
if (len)
len += strlen(opt->optstr);
};
- if (!len)
- return 0;
-
- *mount_data = calloc(len + 1, sizeof(char));
- if (!mount_data)
- return ENOMEM;
+ if (len) {
+ *mount_data = calloc(len + 1, sizeof(char));
+ if (!mount_data)
+ return ENOMEM;
- len = 0;
- list_for_each_entry(opt, &fsopts, list) {
- if (len)
- strcat(*mount_data, ",");
+ len = 0;
+ list_for_each_entry(opt, &fsopts, list) {
+ if (len)
+ strcat(*mount_data, ",");
- strcat(*mount_data, opt->optstr);
- ++len;
- };
+ strcat(*mount_data, opt->optstr);
+ ++len;
+ };
- list_del(&fsopts);
+ list_del(&fsopts);
+ }
- DEBUG("mount flags(%08lx) fsopts(\"%s\")\n", mf, *mount_data?:"");
+ DEBUG("mount flags(%08lx) propagation(%08lx) fsopts(\"%s\")\n", mf, pf, *mount_data?:"");
return 0;
}
{
struct blob_attr *tb[__OCI_MOUNT_MAX];
unsigned long mount_flags = 0;
+ unsigned long propagation_flags = 0;
char *mount_data = NULL;
int ret, err = -1;
return EINVAL;
if (tb[OCI_MOUNT_OPTIONS]) {
- ret = parseOCImountopts(tb[OCI_MOUNT_OPTIONS], &mount_flags, &mount_data, &err);
+ ret = parseOCImountopts(tb[OCI_MOUNT_OPTIONS], &mount_flags, &propagation_flags, &mount_data, &err);
if (ret)
return ret;
}
ret = add_mount(tb[OCI_MOUNT_SOURCE] ? blobmsg_get_string(tb[OCI_MOUNT_SOURCE]) : NULL,
blobmsg_get_string(tb[OCI_MOUNT_DESTINATION]),
tb[OCI_MOUNT_TYPE] ? blobmsg_get_string(tb[OCI_MOUNT_TYPE]) : NULL,
- mount_flags, mount_data, err);
+ mount_flags, propagation_flags, mount_data, err);
if (mount_data)
free(mount_data);
add_mount_bind(l->path, 1, -1);
avl_for_each_element(&mounts, m, avl)
- if (do_mount(jailroot, m->source, m->target, m->filesystemtype, m->mountflags, m->optstr, m->error, m->inner))
+ if (do_mount(jailroot, m->source, m->target, m->filesystemtype, m->mountflags,
+ m->propflags, m->optstr, m->error, m->inner))
return -1;
return 0;
if (tb[OCI_LINUX_READONLYPATHS]) {
blobmsg_for_each_attr(cur, tb[OCI_LINUX_READONLYPATHS], rem) {
- res = add_mount(NULL, blobmsg_get_string(cur), NULL, MS_BIND | MS_REC | MS_RDONLY, NULL, 0);
+ res = add_mount(NULL, blobmsg_get_string(cur), NULL, MS_BIND | MS_REC | MS_RDONLY, 0, NULL, 0);
if (res)
return res;
}
if (tb[OCI_LINUX_MASKEDPATHS]) {
blobmsg_for_each_attr(cur, tb[OCI_LINUX_MASKEDPATHS], rem) {
- res = add_mount((void *)(-1), blobmsg_get_string(cur), NULL, 0, NULL, 1);
+ res = add_mount((void *)(-1), blobmsg_get_string(cur), NULL, 0, 0, NULL, 1);
if (res)
return res;
}
snprintf(hostdir, PATH_MAX, "/tmp/resolv.conf-%s.d", opts.name);
mkdir_p(hostdir, 0755);
- add_mount(hostdir, "/dev/resolv.conf.d", NULL, MS_BIND | MS_NOEXEC | MS_NOATIME | MS_NOSUID | MS_NODEV | MS_RDONLY, NULL, -1);
+ add_mount(hostdir, "/dev/resolv.conf.d", NULL, MS_BIND | MS_NOEXEC | MS_NOATIME | MS_NOSUID | MS_NODEV | MS_RDONLY, 0, NULL, -1);
}
/* default mounts */
- add_mount(NULL, "/dev", "tmpfs", MS_NOATIME | MS_NOEXEC | MS_NOSUID, "size=1M", -1);
- add_mount(NULL, "/dev/pts", "devpts", MS_NOATIME | MS_NOEXEC | MS_NOSUID, "newinstance,ptmxmode=0666,mode=0620,gid=5", 0);
+ add_mount(NULL, "/dev", "tmpfs", MS_NOATIME | MS_NOEXEC | MS_NOSUID, 0, "size=1M", -1);
+ add_mount(NULL, "/dev/pts", "devpts", MS_NOATIME | MS_NOEXEC | MS_NOSUID, 0, "newinstance,ptmxmode=0666,mode=0620,gid=5", 0);
if (opts.procfs || opts.ocibundle) {
- add_mount("proc", "/proc", "proc", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, NULL, -1);
+ add_mount("proc", "/proc", "proc", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0, NULL, -1);
/*
* hack to make /proc/sys/net read-write while the rest of /proc/sys is read-only
* move-mount of /proc/sys/net follows because 'e' preceeds 'y' in the ASCII
* table (and in the alphabet).
*/
- if (!add_mount(NULL, "/proc/sys", NULL, MS_BIND | MS_RDONLY, NULL, -1))
+ if (!add_mount(NULL, "/proc/sys", NULL, MS_BIND | MS_RDONLY, 0, NULL, -1))
if (opts.namespace & CLONE_NEWNET)
- if (!add_mount_inner("/proc/self/net", "/proc/sys/net", NULL, MS_MOVE, NULL, -1))
- add_mount_inner("/proc/sys/net", "/proc/self/net", NULL, MS_BIND, NULL, -1);
+ if (!add_mount_inner("/proc/self/net", "/proc/sys/net", NULL, MS_MOVE, 0, NULL, -1))
+ add_mount_inner("/proc/sys/net", "/proc/self/net", NULL, MS_BIND, 0, NULL, -1);
}
if (opts.sysfs || opts.ocibundle)
- add_mount("sysfs", "/sys", "sysfs", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RDONLY, NULL, -1);
+ add_mount("sysfs", "/sys", "sysfs", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RDONLY, 0, NULL, -1);
if (opts.ocibundle)
- add_mount("shm", "/dev/shm", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, "mode=1777", -1);
+ add_mount("shm", "/dev/shm", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, 0, "mode=1777", -1);
}