Unverified Commit 9ddc6b44 by Christian Brauner Committed by GitHub

Merge pull request #2300 from LizaTretyakova/mount_injection

Mount injection API
parents a633a1ed 54fc984b
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h" #include "config.h"
#include "confile.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <dirent.h> #include <dirent.h>
...@@ -647,6 +648,23 @@ unsigned long add_required_remount_flags(const char *s, const char *d, ...@@ -647,6 +648,23 @@ unsigned long add_required_remount_flags(const char *s, const char *d,
#endif #endif
} }
static int add_shmount_to_list(struct lxc_conf *conf)
{
char new_mount[MAXPATHLEN];
/* Offset for the leading '/' since the path_cont
* is absolute inside the container.
*/
int offset = 1, ret = -1;
ret = snprintf(new_mount, sizeof(new_mount),
"%s %s none bind,create=dir 0 0", conf->shmount.path_host,
conf->shmount.path_cont + offset);
if (ret < 0 || (size_t)ret >= sizeof(new_mount))
return -1;
return add_elem_to_mount_list(new_mount, conf);
}
static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_handler *handler) static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_handler *handler)
{ {
int i, r; int i, r;
...@@ -783,6 +801,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha ...@@ -783,6 +801,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
} }
} }
if (flags & LXC_AUTO_SHMOUNTS_MASK) {
int ret = add_shmount_to_list(conf);
if (ret < 0) {
ERROR("Failed to add shmount entry to container config");
return -1;
}
}
return 0; return 0;
} }
...@@ -2714,6 +2740,9 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2714,6 +2740,9 @@ struct lxc_conf *lxc_conf_init(void)
new->lsm_aa_profile = NULL; new->lsm_aa_profile = NULL;
new->lsm_se_context = NULL; new->lsm_se_context = NULL;
new->tmp_umount_proc = false; new->tmp_umount_proc = false;
new->tmp_umount_proc = 0;
new->shmount.path_host = NULL;
new->shmount.path_cont = NULL;
/* if running in a new user namespace, init and COMMAND /* if running in a new user namespace, init and COMMAND
* default to running as UID/GID 0 when using lxc-execute */ * default to running as UID/GID 0 when using lxc-execute */
...@@ -4041,6 +4070,8 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -4041,6 +4070,8 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_procs(conf, "lxc.proc"); lxc_clear_procs(conf, "lxc.proc");
free(conf->cgroup_meta.dir); free(conf->cgroup_meta.dir);
free(conf->cgroup_meta.controllers); free(conf->cgroup_meta.controllers);
free(conf->shmount.path_host);
free(conf->shmount.path_cont);
free(conf); free(conf);
} }
......
...@@ -189,6 +189,9 @@ enum { ...@@ -189,6 +189,9 @@ enum {
LXC_AUTO_CGROUP_FULL_NOSPEC = 0x0E0, /* /sys/fs/cgroup (full mount, r/w or mixed, depending on caps) */ LXC_AUTO_CGROUP_FULL_NOSPEC = 0x0E0, /* /sys/fs/cgroup (full mount, r/w or mixed, depending on caps) */
LXC_AUTO_CGROUP_FORCE = 0x100, /* mount cgroups even when cgroup namespaces are supported */ LXC_AUTO_CGROUP_FORCE = 0x100, /* mount cgroups even when cgroup namespaces are supported */
LXC_AUTO_CGROUP_MASK = 0x1F0, /* all known cgroup options, doe not contain LXC_AUTO_CGROUP_FORCE */ LXC_AUTO_CGROUP_MASK = 0x1F0, /* all known cgroup options, doe not contain LXC_AUTO_CGROUP_FORCE */
LXC_AUTO_SHMOUNTS = 0x200, /* shared mount point */
LXC_AUTO_SHMOUNTS_MASK = 0x200, /* shared mount point mask */
LXC_AUTO_ALL_MASK = 0x1FF, /* all known settings */ LXC_AUTO_ALL_MASK = 0x1FF, /* all known settings */
}; };
...@@ -367,6 +370,13 @@ struct lxc_conf { ...@@ -367,6 +370,13 @@ struct lxc_conf {
/* procs */ /* procs */
struct lxc_list procs; struct lxc_list procs;
struct shmount {
/* Absolute path to the shared mount point on the host */
char *path_host;
/* Absolute path (in the container) to the shared mount point */
char *path_cont;
} shmount;
}; };
extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
......
...@@ -1659,6 +1659,7 @@ static int set_config_mount_auto(const char *key, const char *value, ...@@ -1659,6 +1659,7 @@ static int set_config_mount_auto(const char *key, const char *value,
{ "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE }, { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE },
{ "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE }, { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE },
{ "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE }, { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE },
{ "shmounts:", LXC_AUTO_SHMOUNTS_MASK, LXC_AUTO_SHMOUNTS },
/* For adding anything that is just a single on/off, but has no /* For adding anything that is just a single on/off, but has no
* options: keep mask and flag identical and just define the enum * options: keep mask and flag identical and just define the enum
* value as an unused bit so far * value as an unused bit so far
...@@ -1676,6 +1677,8 @@ static int set_config_mount_auto(const char *key, const char *value, ...@@ -1676,6 +1677,8 @@ static int set_config_mount_auto(const char *key, const char *value,
return -1; return -1;
for (autoptr = autos;; autoptr = NULL) { for (autoptr = autos;; autoptr = NULL) {
bool is_shmounts = false;
token = strtok_r(autoptr, " \t", &sptr); token = strtok_r(autoptr, " \t", &sptr);
if (!token) { if (!token) {
ret = 0; ret = 0;
...@@ -1685,6 +1688,12 @@ static int set_config_mount_auto(const char *key, const char *value, ...@@ -1685,6 +1688,12 @@ static int set_config_mount_auto(const char *key, const char *value,
for (i = 0; allowed_auto_mounts[i].token; i++) { for (i = 0; allowed_auto_mounts[i].token; i++) {
if (!strcmp(allowed_auto_mounts[i].token, token)) if (!strcmp(allowed_auto_mounts[i].token, token))
break; break;
if (strcmp("shmounts:", allowed_auto_mounts[i].token) == 0 &&
strncmp("shmounts:", token, sizeof("shmounts:") - 1) == 0) {
is_shmounts = true;
break;
}
} }
if (!allowed_auto_mounts[i].token) { if (!allowed_auto_mounts[i].token) {
...@@ -1694,6 +1703,24 @@ static int set_config_mount_auto(const char *key, const char *value, ...@@ -1694,6 +1703,24 @@ static int set_config_mount_auto(const char *key, const char *value,
lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask; lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag; lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
if (is_shmounts) {
lxc_conf->shmount.path_host = strdup(token + (sizeof("shmounts:") - 1));
if (!lxc_conf->shmount.path_host) {
SYSERROR("Failed to copy shmounts host path");
break;
}
if (strcmp(lxc_conf->shmount.path_host, "") == 0) {
ERROR("Invalid shmounts path: empty");
break;
}
lxc_conf->shmount.path_cont = strdup("/dev/.lxc-mounts");
if(!lxc_conf->shmount.path_cont) {
SYSERROR("Failed to copy shmounts container path");
break;
}
}
} }
free(autos); free(autos);
...@@ -1725,6 +1752,10 @@ static int set_config_mount(const char *key, const char *value, ...@@ -1725,6 +1752,10 @@ static int set_config_mount(const char *key, const char *value,
return 0; return 0;
} }
int add_elem_to_mount_list(const char *value, struct lxc_conf *lxc_conf) {
return set_config_mount(NULL, value, lxc_conf, NULL);
}
static int set_config_cap_keep(const char *key, const char *value, static int set_config_cap_keep(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
......
...@@ -28,7 +28,9 @@ ...@@ -28,7 +28,9 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <lxc/attach_options.h> #include <lxc/attach_options.h>
#include <lxc/lxccontainer.h>
struct lxc_conf; struct lxc_conf;
struct lxc_list; struct lxc_list;
...@@ -121,4 +123,6 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, ...@@ -121,4 +123,6 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
extern bool network_new_hwaddrs(struct lxc_conf *conf); extern bool network_new_hwaddrs(struct lxc_conf *conf);
extern int add_elem_to_mount_list(const char *value, struct lxc_conf *lxc_conf);
#endif /* __LXC_CONFILE_H */ #endif /* __LXC_CONFILE_H */
...@@ -30,9 +30,11 @@ ...@@ -30,9 +30,11 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <sys/file.h> #include <sys/file.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -460,6 +462,25 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3) \ ...@@ -460,6 +462,25 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3) \
return ret; \ return ret; \
} }
#define WRAP_API_6(rettype, fnname, t1, t2, t3, t4, t5, t6) \
static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3, \
t4 a4, t5 a5, t6 a6) \
{ \
rettype ret; \
bool reset_config = false; \
\
if (!current_config && c && c->lxc_conf) { \
current_config = c->lxc_conf; \
reset_config = true; \
} \
\
ret = do_##fnname(c, a1, a2, a3, a4, a5, a6); \
if (reset_config) \
current_config = NULL; \
\
return ret; \
}
WRAP_API(bool, lxcapi_is_defined) WRAP_API(bool, lxcapi_is_defined)
static const char *do_lxcapi_state(struct lxc_container *c) static const char *do_lxcapi_state(struct lxc_container *c)
...@@ -4893,6 +4914,234 @@ static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool ver ...@@ -4893,6 +4914,234 @@ static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool ver
WRAP_API_2(bool, lxcapi_restore, char *, bool) WRAP_API_2(bool, lxcapi_restore, char *, bool)
/* @st_mode is the st_mode field of the stat(source) return struct */
static int create_mount_target(const char *dest, mode_t st_mode)
{
char *dirdup, *destdirname;
int ret;
dirdup = strdup(dest);
if (!dirdup) {
SYSERROR("Failed to duplicate target name \"%s\"", dest);
return -1;
}
destdirname = dirname(dirdup);
ret = mkdir_p(destdirname, 0755);
if (ret < 0) {
SYSERROR("Failed to create \"%s\"", destdirname);
free(dirdup);
return ret;
}
free(dirdup);
(void)remove(dest);
if (S_ISDIR(st_mode))
ret = mkdir(dest, 0000);
else
ret = mknod(dest, S_IFREG | 0000, 0);
if (ret < 0) {
SYSERROR("Failed to create mount target \"%s\"", dest);
return -1;
}
return 0;
}
static int do_lxcapi_mount(struct lxc_container *c, const char *source,
const char *target, const char *filesystemtype,
unsigned long mountflags, const void *data,
struct lxc_mount *mnt)
{
char *suff, *sret;
char template[MAXPATHLEN], path[MAXPATHLEN];
pid_t pid, init_pid;
struct stat sb;
int ret = -1, fd = -EBADF;
if (!c || !c->lxc_conf) {
ERROR("Container or configuration is NULL");
return -EINVAL;
}
if (!c->lxc_conf->shmount.path_host) {
ERROR("Host path to shared mountpoint must be specified in the config\n");
return -EINVAL;
}
ret = snprintf(template, sizeof(template), "%s/.lxcmount_XXXXXX", c->lxc_conf->shmount.path_host);
if (ret < 0 || (size_t)ret >= sizeof(template)) {
SYSERROR("Error writing shmounts tempdir name");
goto out;
}
/* Create a temporary file / dir under the shared mountpoint */
if (!source || strcmp(source, "") == 0) {
/* If source is not specified, maybe we want to mount a filesystem? */
sb.st_mode = S_IFDIR;
} else {
ret = stat(source, &sb);
if (ret < 0) {
SYSERROR("Error getting stat info about the source \"%s\"", source);
goto out;
}
}
if (S_ISDIR(sb.st_mode)) {
sret = mkdtemp(template);
if (!sret) {
SYSERROR("Could not create shmounts temporary dir");
goto out;
}
} else {
fd = lxc_make_tmpfile(template, false);
if (fd < 0) {
SYSERROR("Could not create shmounts temporary file");
goto out;
}
}
/* Do the fork */
pid = fork();
if (pid < 0) {
SYSERROR("Could not fork");
goto out;
}
if (pid == 0) {
/* Do the mount */
ret = mount(source, template, filesystemtype, mountflags, data);
if (ret < 0) {
SYSERROR("Failed to mount onto \"%s\"", template);
_exit(EXIT_FAILURE);
}
TRACE("Mounted \"%s\" onto \"%s\"", source, template);
init_pid = do_lxcapi_init_pid(c);
if (init_pid < 0) {
ERROR("Failed to obtain container's init pid");
_exit(EXIT_FAILURE);
}
/* Enter the container namespaces */
if (!lxc_list_empty(&c->lxc_conf->id_map)) {
if (!switch_to_ns(init_pid, "user")){
ERROR("Failed to enter user namespace");
_exit(EXIT_FAILURE);
}
}
if (!switch_to_ns(init_pid, "mnt")) {
ERROR("Failed to enter mount namespace");
_exit(EXIT_FAILURE);
}
ret = create_mount_target(target, sb.st_mode);
if (ret < 0)
_exit(EXIT_FAILURE);
TRACE("Created mount target \"%s\"", target);
suff = strrchr(template, '/');
if (!suff)
_exit(EXIT_FAILURE);
ret = snprintf(path, sizeof(path), "%s%s", c->lxc_conf->shmount.path_cont, suff);
if (ret < 0 || (size_t)ret >= sizeof(path)) {
SYSERROR("Error writing container mountpoint name");
_exit(EXIT_FAILURE);
}
ret = mount(path, target, NULL, MS_MOVE | MS_REC, NULL);
if (ret < 0) {
SYSERROR("Failed to move the mount from \"%s\" to \"%s\"", path, target);
_exit(EXIT_FAILURE);
}
TRACE("Moved mount from \"%s\" to \"%s\"", path, target);
_exit(EXIT_SUCCESS);
}
ret = wait_for_pid(pid);
if (ret < 0) {
SYSERROR("Wait for the child with pid %ld failed", (long) pid);
goto out;
}
ret = 0;
(void)umount2(template, MNT_DETACH);
(void)unlink(template);
out:
if (fd >= 0)
close(fd);
return ret;
}
WRAP_API_6(int, lxcapi_mount, const char *, const char *, const char *,
unsigned long, const void *, struct lxc_mount *)
static int do_lxcapi_umount(struct lxc_container *c, const char *target,
unsigned long flags, struct lxc_mount *mnt)
{
pid_t pid, init_pid;
int ret = -1;
if (!c || !c->lxc_conf) {
ERROR("Container or configuration is NULL");
return -EINVAL;
}
/* Do the fork */
pid = fork();
if (pid < 0) {
SYSERROR("Could not fork");
return -1;
}
if (pid == 0) {
init_pid = do_lxcapi_init_pid(c);
if (init_pid < 0) {
ERROR("Failed to obtain container's init pid");
_exit(EXIT_FAILURE);
}
/* Enter the container namespaces */
if (!lxc_list_empty(&c->lxc_conf->id_map)) {
if (!switch_to_ns(init_pid, "user")) {
ERROR("Failed to enter user namespace");
_exit(EXIT_FAILURE);
}
}
if (!switch_to_ns(init_pid, "mnt")) {
ERROR("Failed to enter mount namespace");
_exit(EXIT_FAILURE);
}
/* Do the unmount */
ret = umount2(target, flags);
if (ret < 0) {
SYSERROR("Failed to umount \"%s\"", target);
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
ret = wait_for_pid(pid);
if (ret < 0) {
SYSERROR("Wait for the child with pid %ld failed", (long)pid);
return -ret;
}
return 0;
}
WRAP_API_3(int, lxcapi_umount, const char *, unsigned long, struct lxc_mount*)
static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...) static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
{ {
va_list ap; va_list ap;
...@@ -5045,6 +5294,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath ...@@ -5045,6 +5294,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c->restore = lxcapi_restore; c->restore = lxcapi_restore;
c->migrate = lxcapi_migrate; c->migrate = lxcapi_migrate;
c->console_log = lxcapi_console_log; c->console_log = lxcapi_console_log;
c->mount = lxcapi_mount;
c->umount = lxcapi_umount;
return c; return c;
......
...@@ -42,6 +42,7 @@ extern "C" { ...@@ -42,6 +42,7 @@ extern "C" {
#define LXC_CLONE_MAXFLAGS (1 << 5) /*!< Number of \c LXC_CLONE_* flags */ #define LXC_CLONE_MAXFLAGS (1 << 5) /*!< Number of \c LXC_CLONE_* flags */
#define LXC_CREATE_QUIET (1 << 0) /*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */ #define LXC_CREATE_QUIET (1 << 0) /*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */
#define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */ #define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */
#define LXC_MOUNT_API_V1 1
struct bdev_specs; struct bdev_specs;
...@@ -53,6 +54,10 @@ struct migrate_opts; ...@@ -53,6 +54,10 @@ struct migrate_opts;
struct lxc_console_log; struct lxc_console_log;
struct lxc_mount {
int version;
};
/*! /*!
* An LXC container. * An LXC container.
* *
...@@ -846,6 +851,20 @@ struct lxc_container { ...@@ -846,6 +851,20 @@ struct lxc_container {
* \return \c true if the container was rebooted successfully, else \c false. * \return \c true if the container was rebooted successfully, else \c false.
*/ */
bool (*reboot2)(struct lxc_container *c, int timeout); bool (*reboot2)(struct lxc_container *c, int timeout);
/*!
* \brief Mount the host's path `source` onto the container's path `target`.
*/
int (*mount)(struct lxc_container *c,
const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data, struct lxc_mount *mnt);
/*!
* \brief Unmount the container's path `target`.
*/
int (*umount)(struct lxc_container *c, const char *target,
unsigned long mountflags, struct lxc_mount *mnt);
}; };
/*! /*!
......
...@@ -1529,6 +1529,75 @@ static inline int do_share_ns(void *arg) ...@@ -1529,6 +1529,75 @@ static inline int do_share_ns(void *arg)
return 0; return 0;
} }
static int lxc_setup_shmount(struct lxc_conf *conf)
{
size_t len_cont;
char *full_cont_path;
int ret = -1;
/* Construct the shmount path under the container root. */
len_cont = strlen(conf->rootfs.mount) + 1 + strlen(conf->shmount.path_cont);
/* +1 for the terminating '\0' */
full_cont_path = malloc(len_cont + 1);
if (!full_cont_path) {
SYSERROR("Not enough memory");
return -ENOMEM;
}
ret = snprintf(full_cont_path, len_cont + 1, "%s/%s",
conf->rootfs.mount, conf->shmount.path_cont);
if (ret < 0 || ret >= len_cont + 1) {
SYSERROR("Failed to create filename");
free(full_cont_path);
return -1;
}
/* Check if shmount point is already set up. */
if (is_shared_mountpoint(conf->shmount.path_host)) {
INFO("Path \"%s\" is already MS_SHARED. Reusing",
conf->shmount.path_host);
free(full_cont_path);
return 0;
}
/* Create host and cont mount paths */
ret = mkdir_p(conf->shmount.path_host, 0711);
if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create directory \"%s\"",
conf->shmount.path_host);
free(full_cont_path);
return ret;
}
ret = mkdir_p(full_cont_path, 0711);
if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create directory \"%s\"", full_cont_path);
free(full_cont_path);
return ret;
}
/* Prepare host mountpoint */
ret = mount("tmpfs", conf->shmount.path_host, "tmpfs", 0,
"size=100k,mode=0711");
if (ret < 0) {
SYSERROR("Failed to mount \"%s\"", conf->shmount.path_host);
free(full_cont_path);
return ret;
}
ret = mount(conf->shmount.path_host, conf->shmount.path_host, "none",
MS_REC | MS_SHARED, "");
if (ret < 0) {
SYSERROR("Failed to make shared \"%s\"", conf->shmount.path_host);
free(full_cont_path);
return ret;
}
INFO("Setup shared mount point \"%s\"", conf->shmount.path_host);
free(full_cont_path);
return 0;
}
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which /* lxc_spawn() performs crucial setup tasks and clone()s the new process which
* exec()s the requested container binary. * exec()s the requested container binary.
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed * Note that lxc_spawn() runs in the parent namespaces. Any operations performed
...@@ -1606,6 +1675,25 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1606,6 +1675,25 @@ static int lxc_spawn(struct lxc_handler *handler)
} }
} }
if (conf->shmount.path_host) {
if (!conf->shmount.path_cont) {
lxc_sync_fini(handler);
return -1;
}
ret = lxc_setup_shmount(conf);
if (ret < 0) {
ERROR("Failed to setup shared mount point");
lxc_sync_fini(handler);
return -1;
}
}
if (!cgroup_init(handler)) {
ERROR("Failed initializing cgroup support");
goto out_delete_net;
}
if (!cgroup_ops->create(cgroup_ops, handler)) { if (!cgroup_ops->create(cgroup_ops, handler)) {
ERROR("Failed creating cgroups"); ERROR("Failed creating cgroups");
goto out_delete_net; goto out_delete_net;
......
...@@ -1219,19 +1219,12 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval) ...@@ -1219,19 +1219,12 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return hval; return hval;
} }
/* bool is_shared_mountpoint(const char *path)
* Detect whether / is mounted MS_SHARED. The only way I know of to
* check that is through /proc/self/mountinfo.
* I'm only checking for /. If the container rootfs or mount location
* is MS_SHARED, but not '/', then you're out of luck - figuring that
* out would be too much work to be worth it.
*/
int detect_shared_rootfs(void)
{ {
char buf[LXC_LINELEN], *p; char buf[LXC_LINELEN];
FILE *f; FILE *f;
int i; int i;
char *p2; char *p, *p2;
f = fopen("/proc/self/mountinfo", "r"); f = fopen("/proc/self/mountinfo", "r");
if (!f) if (!f)
...@@ -1248,17 +1241,31 @@ int detect_shared_rootfs(void) ...@@ -1248,17 +1241,31 @@ int detect_shared_rootfs(void)
continue; continue;
*p2 = '\0'; *p2 = '\0';
if (strcmp(p + 1, "/") == 0) { if (strcmp(p + 1, path) == 0) {
/* This is '/'. Is it shared? */ /* This is the path. Is it shared? */
p = strchr(p2 + 1, ' '); p = strchr(p2 + 1, ' ');
if (p && strstr(p, "shared:")) { if (p && strstr(p, "shared:")) {
fclose(f); fclose(f);
return 1; return true;
} }
} }
} }
fclose(f); fclose(f);
return false;
}
/*
* Detect whether / is mounted MS_SHARED. The only way I know of to
* check that is through /proc/self/mountinfo.
* I'm only checking for /. If the container rootfs or mount location
* is MS_SHARED, but not '/', then you're out of luck - figuring that
* out would be too much work to be worth it.
*/
int detect_shared_rootfs(void)
{
if (is_shared_mountpoint("/"))
return 1;
return 0; return 0;
} }
......
...@@ -502,6 +502,7 @@ extern bool dir_exists(const char *path); ...@@ -502,6 +502,7 @@ extern bool dir_exists(const char *path);
#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
extern uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval); extern uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
extern bool is_shared_mountpoint(const char *path);
extern int detect_shared_rootfs(void); extern int detect_shared_rootfs(void);
extern bool detect_ramfs_rootfs(void); extern bool detect_ramfs_rootfs(void);
extern char *on_path(const char *cmd, const char *rootfs); extern char *on_path(const char *cmd, const char *rootfs);
......
...@@ -33,6 +33,7 @@ lxc_test_state_server_SOURCES = state_server.c lxctest.h ...@@ -33,6 +33,7 @@ lxc_test_state_server_SOURCES = state_server.c lxctest.h
lxc_test_share_ns_SOURCES = share_ns.c lxctest.h lxc_test_share_ns_SOURCES = share_ns.c lxctest.h
lxc_test_criu_check_feature_SOURCES = criu_check_feature.c lxctest.h lxc_test_criu_check_feature_SOURCES = criu_check_feature.c lxctest.h
lxc_test_raw_clone_SOURCES = lxc_raw_clone.c lxctest.h lxc_test_raw_clone_SOURCES = lxc_raw_clone.c lxctest.h
lxc_test_mount_injection_SOURCES = mount_injection.c
AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
-DLXCPATH=\"$(LXCPATH)\" \ -DLXCPATH=\"$(LXCPATH)\" \
...@@ -64,7 +65,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \ ...@@ -64,7 +65,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
lxc-test-apparmor lxc-test-utils lxc-test-parse-config-file \ lxc-test-apparmor lxc-test-utils lxc-test-parse-config-file \
lxc-test-config-jump-table lxc-test-shortlived \ lxc-test-config-jump-table lxc-test-shortlived \
lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns \ lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns \
lxc-test-criu-check-feature lxc-test-raw-clone lxc-test-criu-check-feature lxc-test-raw-clone \
lxc-test-mount-injection
bin_SCRIPTS = bin_SCRIPTS =
if ENABLE_TOOLS if ENABLE_TOOLS
...@@ -121,6 +123,7 @@ EXTRA_DIST = \ ...@@ -121,6 +123,7 @@ EXTRA_DIST = \
lxc-test-unpriv \ lxc-test-unpriv \
lxc-test-utils.c \ lxc-test-utils.c \
may_control.c \ may_control.c \
mount_injection.c \
parse_config_file.c \ parse_config_file.c \
saveconfig.c \ saveconfig.c \
shortlived.c \ shortlived.c \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment