mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-24 22:56:47 +00:00
Automatic mounts: improvements for /proc and /sys
Improve lxc.mount.auto code: allow the user to specify whether to mount certain things read-only or read-write. Also make the code much more easily extensible for the future. Signed-off-by: Christian Seiler <christian@iwakd.de> Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
211e51e81e
commit
b06b851168
146
src/lxc/conf.c
146
src/lxc/conf.c
@ -740,85 +740,85 @@ int pin_rootfs(const char *rootfs)
|
||||
|
||||
static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct cgroup_process_info *cgroup_info)
|
||||
{
|
||||
char *path = NULL;
|
||||
char *dev_null = NULL;
|
||||
int r;
|
||||
|
||||
dev_null = lxc_append_paths(conf->rootfs.mount, "/dev/null");
|
||||
if (!dev_null) {
|
||||
SYSERROR("memory allocation error");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (flags & LXC_AUTO_PROC) {
|
||||
path = lxc_append_paths(conf->rootfs.mount, "/proc");
|
||||
if (!path) {
|
||||
SYSERROR("memory allocation error trying to automatically mount /proc");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = mount("proc", path, "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL);
|
||||
if (r < 0) {
|
||||
SYSERROR("error mounting /proc");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
if (flags & LXC_AUTO_PROC_SYSRQ) {
|
||||
path = lxc_append_paths(conf->rootfs.mount, "/proc/sysrq-trigger");
|
||||
if (!path) {
|
||||
SYSERROR("memory allocation error trying to automatically mount /proc");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* safety measure, mount /dev/null over /proc/sysrq-trigger,
|
||||
* otherwise, a container may trigger a host reboot or such
|
||||
size_t i;
|
||||
static struct {
|
||||
int match_mask;
|
||||
int match_flag;
|
||||
const char *source;
|
||||
const char *destination;
|
||||
const char *fstype;
|
||||
unsigned long flags;
|
||||
const char *options;
|
||||
} default_mounts[] = {
|
||||
/* Read-only bind-mounting... In older kernels, doing that required
|
||||
* to do one MS_BIND mount and then MS_REMOUNT|MS_RDONLY the same
|
||||
* one. According to mount(2) manpage, MS_BIND honors MS_RDONLY from
|
||||
* kernel 2.6.26 onwards. However, this apparently does not work on
|
||||
* kernel 3.8. Unfortunately, on that very same kernel, doing the
|
||||
* same trick as above doesn't seem to work either, there one needs
|
||||
* to ALSO specify MS_BIND for the remount, otherwise the entire
|
||||
* fs is remounted read-only or the mount fails because it's busy...
|
||||
* MS_REMOUNT|MS_BIND|MS_RDONLY seems to work for kernels as low as
|
||||
* 2.6.32...
|
||||
*/
|
||||
r = mount(dev_null, path, NULL, MS_BIND, NULL);
|
||||
if (r < 0)
|
||||
WARN("error mounting /dev/null over /proc/sysrq-trigger: %s", strerror(errno));
|
||||
{ LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL },
|
||||
{ LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys", "%r/proc/sys", NULL, MS_BIND, NULL },
|
||||
{ LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sys", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL },
|
||||
{ LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sysrq-trigger", "%r/proc/sysrq-trigger", NULL, MS_BIND, NULL },
|
||||
{ LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sysrq-trigger", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL },
|
||||
{ LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL },
|
||||
{ LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW, "sysfs", "%r/sys", "sysfs", 0, NULL },
|
||||
{ LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO, "sysfs", "%r/sys", "sysfs", MS_RDONLY, NULL },
|
||||
{ 0, 0, NULL, NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
free(path);
|
||||
path = NULL;
|
||||
for (i = 0; default_mounts[i].match_mask; i++) {
|
||||
if ((flags & default_mounts[i].match_mask) == default_mounts[i].match_flag) {
|
||||
char *source = NULL;
|
||||
char *destination = NULL;
|
||||
int saved_errno;
|
||||
|
||||
if (default_mounts[i].source) {
|
||||
/* will act like strdup if %r is not present */
|
||||
source = lxc_string_replace("%r", conf->rootfs.mount, default_mounts[i].source);
|
||||
if (!source) {
|
||||
SYSERROR("memory allocation error");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (default_mounts[i].destination) {
|
||||
/* will act like strdup if %r is not present */
|
||||
destination = lxc_string_replace("%r", conf->rootfs.mount, default_mounts[i].destination);
|
||||
if (!destination) {
|
||||
saved_errno = errno;
|
||||
SYSERROR("memory allocation error");
|
||||
free(source);
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
r = mount(source, destination, default_mounts[i].fstype, default_mounts[i].flags, default_mounts[i].options);
|
||||
saved_errno = errno;
|
||||
free(source);
|
||||
free(destination);
|
||||
if (r < 0) {
|
||||
SYSERROR("error mounting %s", default_mounts[i].destination);
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & LXC_AUTO_SYS) {
|
||||
path = lxc_append_paths(conf->rootfs.mount, "/sys");
|
||||
if (!path) {
|
||||
SYSERROR("memory allocation error trying to automatically mount /sys");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = mount("sysfs", path, "sysfs", MS_RDONLY, NULL);
|
||||
if (r < 0) {
|
||||
SYSERROR("error mounting /sys");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
if (flags & LXC_AUTO_CGROUP) {
|
||||
if (flags & LXC_AUTO_CGROUP_MASK) {
|
||||
r = lxc_setup_mount_cgroup(conf->rootfs.mount, cgroup_info);
|
||||
if (r < 0) {
|
||||
SYSERROR("error mounting /sys/fs/cgroup");
|
||||
goto cleanup;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(dev_null);
|
||||
free(path);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
free(dev_null);
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mount_rootfs(const char *rootfs, const char *target)
|
||||
@ -3067,7 +3067,7 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath,
|
||||
/* do automatic mounts (mainly /proc and /sys), but exclude
|
||||
* those that need to wait until other stuff has finished
|
||||
*/
|
||||
if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP & ~LXC_AUTO_PROC_SYSRQ, cgroup_info) < 0) {
|
||||
if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, cgroup_info) < 0) {
|
||||
ERROR("failed to setup the automatic mounts for '%s'", name);
|
||||
return -1;
|
||||
}
|
||||
@ -3086,7 +3086,7 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath,
|
||||
* before, /sys could not have been mounted
|
||||
* (is either mounted automatically or via fstab entries)
|
||||
*/
|
||||
if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP, cgroup_info) < 0) {
|
||||
if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, cgroup_info) < 0) {
|
||||
ERROR("failed to setup the automatic mounts for '%s'", name);
|
||||
return -1;
|
||||
}
|
||||
@ -3107,14 +3107,6 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath,
|
||||
}
|
||||
}
|
||||
|
||||
/* over-mount /proc/sysrq-trigger with /dev/null now, if wanted;
|
||||
* before /dev/null did not necessarily exist
|
||||
*/
|
||||
if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_PROC_SYSRQ, cgroup_info) < 0) {
|
||||
ERROR("failed to setup the automatic mounts for '%s'", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!lxc_conf->is_execute && setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
|
||||
ERROR("failed to setup the console for '%s'", name);
|
||||
return -1;
|
||||
|
@ -225,10 +225,23 @@ struct lxc_rootfs {
|
||||
* Automatic mounts for LXC to perform inside the container
|
||||
*/
|
||||
enum {
|
||||
LXC_AUTO_PROC = 0x01, /* /proc */
|
||||
LXC_AUTO_SYS = 0x02, /* /sys*/
|
||||
LXC_AUTO_CGROUP = 0x04, /* /sys/fs/cgroup */
|
||||
LXC_AUTO_PROC_SYSRQ = 0x08, /* /proc/sysrq-trigger over-bind-mounted with /dev/null */
|
||||
LXC_AUTO_PROC_RW = 0x001, /* /proc read-write */
|
||||
LXC_AUTO_PROC_MIXED = 0x002, /* /proc/sys and /proc/sysrq-trigger read-only */
|
||||
LXC_AUTO_PROC_MASK = 0x003,
|
||||
|
||||
LXC_AUTO_SYS_RW = 0x004, /* /sys */
|
||||
LXC_AUTO_SYS_RO = 0x008, /* /sys read-only */
|
||||
LXC_AUTO_SYS_MASK = 0x00C,
|
||||
|
||||
LXC_AUTO_CGROUP_RO = 0x010, /* /sys/fs/cgroup (partial mount, read-only) */
|
||||
LXC_AUTO_CGROUP_RW = 0x020, /* /sys/fs/cgroup (partial mount, read-write) */
|
||||
LXC_AUTO_CGROUP_MIXED = 0x030, /* /sys/fs/cgroup (partial mount, paths r/o, cgroup r/w) */
|
||||
LXC_AUTO_CGROUP_FULL_RO = 0x040, /* /sys/fs/cgroup (full mount, read-only) */
|
||||
LXC_AUTO_CGROUP_FULL_RW = 0x050, /* /sys/fs/cgroup (full mount, read-write) */
|
||||
LXC_AUTO_CGROUP_FULL_MIXED = 0x060, /* /sys/fs/cgroup (full mount, parent r/o, own r/w) */
|
||||
LXC_AUTO_CGROUP_MASK = 0x070,
|
||||
|
||||
LXC_AUTO_ALL_MASK = 0x07F, /* all known settings */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1255,11 +1255,25 @@ static int config_mount_auto(const char *key, const char *value,
|
||||
struct lxc_conf *lxc_conf)
|
||||
{
|
||||
char *autos, *autoptr, *sptr, *token;
|
||||
static struct { const char *token; int flag; } allowed_auto_mounts[] = {
|
||||
{ "proc", LXC_AUTO_PROC },
|
||||
{ "sysrq", LXC_AUTO_PROC_SYSRQ },
|
||||
{ "sys", LXC_AUTO_SYS },
|
||||
{ "cgroup", LXC_AUTO_CGROUP },
|
||||
static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
|
||||
{ "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
|
||||
{ "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
|
||||
{ "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
|
||||
{ "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
|
||||
{ "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
|
||||
{ "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
|
||||
{ "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
|
||||
{ "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
|
||||
{ "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
|
||||
{ "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
|
||||
{ "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
|
||||
{ "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
|
||||
{ "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
|
||||
{ "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
|
||||
/* NB: For adding anything that ist just a single on/off, but has
|
||||
* no options: keep mask and flag identical and just define the
|
||||
* enum value as an unused bit so far
|
||||
*/
|
||||
{ NULL, 0 }
|
||||
};
|
||||
int i;
|
||||
@ -1291,6 +1305,7 @@ static int config_mount_auto(const char *key, const char *value,
|
||||
break;
|
||||
}
|
||||
|
||||
lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
|
||||
lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user