#endif
#include "af_unix.h"
-#include "bdev.h"
#include "caps.h" /* for lxc_caps_last_cap() */
#include "cgroup.h"
#include "conf.h"
#include "confile_utils.h"
#include "error.h"
#include "log.h"
-#include "lxcaufs.h"
#include "lxclock.h"
-#include "lxcoverlay.h"
#include "lxcseccomp.h"
#include "namespace.h"
#include "network.h"
#include "parse.h"
+#include "storage.h"
+#include "storage/aufs.h"
+#include "storage/overlay.h"
#include "utils.h"
#include "lsm/lsm.h"
extern int memfd_create(const char *name, unsigned int flags);
#endif
-char *lxchook_names[NUM_LXC_HOOKS] = {
- "pre-start", "pre-mount", "mount", "autodev", "start", "stop", "post-stop", "clone", "destroy" };
+char *lxchook_names[NUM_LXC_HOOKS] = {"pre-start", "pre-mount", "mount",
+ "autodev", "start", "stop",
+ "post-stop", "clone", "destroy"};
typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
return -1;
}
-/*
- * Just create a path for /dev under $lxcpath/$name and in rootfs
- * If we hit an error, log it but don't fail yet.
+/* Just create a path for /dev under $lxcpath/$name and in rootfs If we hit an
+ * error, log it but don't fail yet.
*/
-static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, const char *lxcpath)
+static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs,
+ const char *lxcpath)
{
int ret;
size_t clen;
char *path;
- INFO("Mounting container /dev");
+ INFO("Preparing \"/dev\"");
/* $(rootfs->mount) + "/dev/pts" + '\0' */
clen = (rootfs->path ? strlen(rootfs->mount) : 0) + 9;
path = alloca(clen);
ret = snprintf(path, clen, "%s/dev", rootfs->path ? rootfs->mount : "");
- if (ret < 0 || ret >= clen)
+ if (ret < 0 || (size_t)ret >= clen)
return -1;
if (!dir_exists(path)) {
- WARN("No /dev in container.");
- WARN("Proceeding without autodev setup");
+ WARN("\"/dev\" directory does not exist. Proceeding without "
+ "autodev being set up");
return 0;
}
ret = safe_mount("none", path, "tmpfs", 0, "size=500000,mode=755",
- rootfs->path ? rootfs->mount : NULL);
- if (ret != 0) {
- SYSERROR("Failed mounting tmpfs onto %s\n", path);
+ rootfs->path ? rootfs->mount : NULL);
+ if (ret < 0) {
+ SYSERROR("Failed to mount tmpfs on \"%s\"", path);
return -1;
}
-
- INFO("Mounted tmpfs onto %s", path);
+ INFO("Mounted tmpfs on \"%s\"", path);
ret = snprintf(path, clen, "%s/dev/pts", rootfs->path ? rootfs->mount : "");
- if (ret < 0 || ret >= clen)
+ if (ret < 0 || (size_t)ret >= clen)
return -1;
- /*
- * If we are running on a devtmpfs mapping, dev/pts may already exist.
+ /* If we are running on a devtmpfs mapping, dev/pts may already exist.
* If not, then create it and exit if that fails...
*/
if (!dir_exists(path)) {
ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
- if (ret) {
- SYSERROR("Failed to create /dev/pts in container");
+ if (ret < 0) {
+ SYSERROR("Failed to create directory \"%s\"", path);
return -1;
}
}
- INFO("Mounted container /dev");
+ INFO("Prepared \"/dev\"");
return 0;
}
};
static const struct lxc_devs lxc_devs[] = {
- { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
- { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
- { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 },
- { "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 },
- { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 },
- { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 },
+ { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
+ { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
+ { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 },
+ { "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 },
+ { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 },
+ { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 },
};
static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
int i;
mode_t cmask;
- ret = snprintf(path, MAXPATHLEN, "%s/dev", rootfs->path ? rootfs->mount : "");
- if (ret < 0 || ret >= MAXPATHLEN) {
- ERROR("Error calculating container /dev location");
+ ret = snprintf(path, MAXPATHLEN, "%s/dev",
+ rootfs->path ? rootfs->mount : "");
+ if (ret < 0 || ret >= MAXPATHLEN)
return -1;
- }
/* ignore, just don't try to fill in */
if (!dir_exists(path))
return 0;
- INFO("populating container /dev");
+ INFO("Populating \"/dev\"");
+
cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
const struct lxc_devs *d = &lxc_devs[i];
- ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", rootfs->path ? rootfs->mount : "", d->name);
+ ret = snprintf(path, MAXPATHLEN, "%s/dev/%s",
+ rootfs->path ? rootfs->mount : "", d->name);
if (ret < 0 || ret >= MAXPATHLEN)
return -1;
ret = mknod(path, d->mode, makedev(d->maj, d->min));
if (ret < 0) {
- char hostpath[MAXPATHLEN];
FILE *pathfile;
+ char hostpath[MAXPATHLEN];
if (errno == EEXIST) {
DEBUG("\"%s\" device already existed", path);
ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", d->name);
if (ret < 0 || ret >= MAXPATHLEN)
return -1;
+
pathfile = fopen(path, "wb");
if (!pathfile) {
- SYSERROR("Failed to create device mount target '%s'", path);
+ SYSERROR("Failed to create file \"%s\"", path);
return -1;
}
fclose(pathfile);
- if (safe_mount(hostpath, path, 0, MS_BIND, NULL, rootfs->path ? rootfs->mount : NULL) != 0) {
- SYSERROR("Failed bind mounting device %s from host into container", d->name);
+
+ ret = safe_mount(hostpath, path, 0, MS_BIND, NULL,
+ rootfs->path ? rootfs->mount : NULL);
+ if (ret < 0) {
+ SYSERROR("Failed to bind mount \"%s\" from "
+ "host into container",
+ d->name);
return -1;
}
- DEBUG("bind mounted \"%s\" onto \"%s\"", hostpath, path);
+ DEBUG("Bind mounted \"%s\" onto \"%s\"", hostpath,
+ path);
} else {
- DEBUG("created device node \"%s\"", path);
+ DEBUG("Created device node \"%s\"", path);
}
}
umask(cmask);
- INFO("populated container /dev");
+ INFO("Populated \"/dev\"");
return 0;
}
static int lxc_setup_rootfs(struct lxc_conf *conf)
{
int ret;
- struct bdev *bdev;
+ struct lxc_storage *bdev;
const struct lxc_rootfs *rootfs;
rootfs = &conf->rootfs;
return -1;
}
- bdev = bdev_init(conf, rootfs->path, rootfs->mount, rootfs->options);
+ bdev = storage_init(conf, rootfs->path, rootfs->mount, rootfs->options);
if (!bdev) {
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".",
rootfs->path, rootfs->mount,
}
ret = bdev->ops->mount(bdev);
- bdev_put(bdev);
+ storage_put(bdev);
if (ret < 0) {
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".",
rootfs->path, rootfs->mount,
static int lxc_setup_devpts(int num_pts)
{
int ret;
- const char *devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5";
+ const char *default_devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5";
+ char devpts_mntopts[256];
if (!num_pts) {
DEBUG("no new devpts instance will be mounted since no pts "
return 0;
}
+ ret = snprintf(devpts_mntopts, sizeof(devpts_mntopts), "%s,max=%d",
+ default_devpts_mntopts, num_pts);
+ if (ret < 0 || (size_t)ret >= sizeof(devpts_mntopts))
+ return -1;
+
/* Unmount old devpts instance. */
ret = access("/dev/pts/ptmx", F_OK);
if (!ret) {
static int mount_entry(const char *fsname, const char *target,
const char *fstype, unsigned long mountflags,
- const char *data, int optional, int dev, const char *rootfs)
+ const char *data, int optional, int dev,
+ const char *rootfs)
{
+ int ret;
#ifdef HAVE_STATVFS
struct statvfs sb;
#endif
- if (safe_mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data, rootfs)) {
+ ret = safe_mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data,
+ rootfs);
+ if (ret < 0) {
if (optional) {
- INFO("failed to mount '%s' on '%s' (optional): %s", fsname,
- target, strerror(errno));
+ INFO("Failed to mount \"%s\" on \"%s\" (optional): %s",
+ fsname, target, strerror(errno));
return 0;
}
- else {
- SYSERROR("failed to mount '%s' on '%s'", fsname, target);
- return -1;
- }
+
+ SYSERROR("Failed to mount \"%s\" on \"%s\"", fsname, target);
+ return -1;
}
if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
- DEBUG("remounting %s on %s to respect bind or remount options",
- fsname ? fsname : "(none)", target ? target : "(none)");
unsigned long rqd_flags = 0;
+
+ DEBUG("Remounting \"%s\" on \"%s\" to respect bind or remount "
+ "options",
+ fsname ? fsname : "(none)", target ? target : "(none)");
+
if (mountflags & MS_RDONLY)
rqd_flags |= MS_RDONLY;
#ifdef HAVE_STATVFS
if (statvfs(fsname, &sb) == 0) {
unsigned long required_flags = rqd_flags;
+
if (sb.f_flag & MS_NOSUID)
required_flags |= MS_NOSUID;
+
if (sb.f_flag & MS_NODEV && !dev)
required_flags |= MS_NODEV;
+
if (sb.f_flag & MS_RDONLY)
required_flags |= MS_RDONLY;
+
if (sb.f_flag & MS_NOEXEC)
required_flags |= MS_NOEXEC;
- DEBUG("(at remount) flags for %s was %lu, required extra flags are %lu", fsname, sb.f_flag, required_flags);
- /*
- * If this was a bind mount request, and required_flags
+
+ DEBUG("Flags for \"%s\" were %lu, required extra flags "
+ "are %lu", fsname, sb.f_flag, required_flags);
+
+ /* If this was a bind mount request, and required_flags
* does not have any flags which are not already in
- * mountflags, then skip the remount
+ * mountflags, then skip the remount.
*/
if (!(mountflags & MS_REMOUNT)) {
- if (!(required_flags & ~mountflags) && rqd_flags == 0) {
- DEBUG("mountflags already was %lu, skipping remount",
- mountflags);
+ if (!(required_flags & ~mountflags) &&
+ rqd_flags == 0) {
+ DEBUG("Mountflags already were %lu, "
+ "skipping remount", mountflags);
goto skipremount;
}
}
+
mountflags |= required_flags;
}
#endif
- if (mount(fsname, target, fstype,
- mountflags | MS_REMOUNT, data) < 0) {
+ ret = mount(fsname, target, fstype, mountflags | MS_REMOUNT, data);
+ if (ret < 0) {
if (optional) {
- INFO("failed to mount '%s' on '%s' (optional): %s",
- fsname, target, strerror(errno));
+ INFO("Failed to mount \"%s\" on \"%s\" "
+ "(optional): %s", fsname, target,
+ strerror(errno));
return 0;
}
- else {
- SYSERROR("failed to mount '%s' on '%s'",
- fsname, target);
- return -1;
- }
+
+ SYSERROR("Failed to mount \"%s\" on \"%s\"", fsname, target);
+ return -1;
}
}
#ifdef HAVE_STATVFS
skipremount:
#endif
- DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
+ DEBUG("Mounted \"%s\" on \"%s\" with filesystem type \"%s\"", fsname,
+ target, fstype);
return 0;
}
-/*
- * Remove 'optional', 'create=dir', and 'create=file' from mntopt
- */
+/* Remove "optional", "create=dir", and "create=file" from mntopt */
static void cull_mntent_opt(struct mntent *mntent)
{
int i;
- char *p, *p2;
- char *list[] = {"create=dir",
- "create=file",
- "optional",
- NULL };
-
- for (i=0; list[i]; i++) {
- if (!(p = strstr(mntent->mnt_opts, list[i])))
+ char *list[] = {"create=dir", "create=file", "optional", NULL};
+
+ for (i = 0; list[i]; i++) {
+ char *p, *p2;
+
+ p = strstr(mntent->mnt_opts, list[i]);
+ if (!p)
continue;
+
p2 = strchr(p, ',');
if (!p2) {
/* no more mntopts, so just chop it here */
*p = '\0';
continue;
}
- memmove(p, p2+1, strlen(p2+1)+1);
+
+ memmove(p, p2 + 1, strlen(p2 + 1) + 1);
}
}
static int mount_entry_create_dir_file(const struct mntent *mntent,
- const char* path, const struct lxc_rootfs *rootfs,
- const char *lxc_name, const char *lxc_path)
+ const char *path,
+ const struct lxc_rootfs *rootfs,
+ const char *lxc_name,
+ const char *lxc_path)
{
- char *pathdirname = NULL;
int ret = 0;
- FILE *pathfile = NULL;
- if (strncmp(mntent->mnt_type, "overlay", 7) == 0) {
- if (ovl_mkdir(mntent, rootfs, lxc_name, lxc_path) < 0)
- return -1;
- } else if (strncmp(mntent->mnt_type, "aufs", 4) == 0) {
- if (aufs_mkdir(mntent, rootfs, lxc_name, lxc_path) < 0)
- return -1;
- }
+ if (!strncmp(mntent->mnt_type, "overlay", 7))
+ ret = ovl_mkdir(mntent, rootfs, lxc_name, lxc_path);
+ else if (!strncmp(mntent->mnt_type, "aufs", 4))
+ ret = aufs_mkdir(mntent, rootfs, lxc_name, lxc_path);
+ if (ret < 0)
+ return -1;
if (hasmntopt(mntent, "create=dir")) {
- if (mkdir_p(path, 0755) < 0) {
- WARN("Failed to create mount target '%s'", path);
- ret = -1;
+ ret = mkdir_p(path, 0755);
+ if (ret < 0 && errno != EEXIST) {
+ SYSERROR("Failed to create directory \"%s\"", path);
+ return -1;
}
}
if (hasmntopt(mntent, "create=file") && access(path, F_OK)) {
- pathdirname = strdup(path);
- pathdirname = dirname(pathdirname);
- if (mkdir_p(pathdirname, 0755) < 0) {
- WARN("Failed to create target directory");
- }
- pathfile = fopen(path, "wb");
- if (!pathfile) {
- WARN("Failed to create mount target '%s'", path);
- ret = -1;
- } else {
- fclose(pathfile);
+ int fd;
+ char *p1, *p2;
+
+ p1 = strdup(path);
+ if (!p1)
+ return -1;
+
+ p2 = dirname(p1);
+
+ ret = mkdir_p(p2, 0755);
+ free(p1);
+ if (ret < 0 && errno != EEXIST) {
+ SYSERROR("Failed to create directory \"%s\"", path);
+ return -1;
}
+
+ fd = open(path, O_CREAT, 0644);
+ if (fd < 0)
+ return -1;
+ close(fd);
}
- free(pathdirname);
- return ret;
+
+ return 0;
}
/* rootfs, lxc_name, and lxc_path can be NULL when the container is created
* without a rootfs. */
static inline int mount_entry_on_generic(struct mntent *mntent,
- const char* path, const struct lxc_rootfs *rootfs,
- const char *lxc_name, const char *lxc_path)
+ const char *path,
+ const struct lxc_rootfs *rootfs,
+ const char *lxc_name,
+ const char *lxc_path)
{
+ int ret;
unsigned long mntflags;
char *mntdata;
- int ret;
- bool optional = hasmntopt(mntent, "optional") != NULL;
- bool dev = hasmntopt(mntent, "dev") != NULL;
-
+ bool dev, optional;
char *rootfs_path = NULL;
+
+ optional = hasmntopt(mntent, "optional") != NULL;
+ dev = hasmntopt(mntent, "dev") != NULL;
+
if (rootfs && rootfs->path)
rootfs_path = rootfs->mount;
- ret = mount_entry_create_dir_file(mntent, path, rootfs, lxc_name, lxc_path);
-
- if (ret < 0)
- return optional ? 0 : -1;
+ ret = mount_entry_create_dir_file(mntent, path, rootfs, lxc_name,
+ lxc_path);
+ if (ret < 0) {
+ if (optional)
+ return 0;
+ return -1;
+ }
cull_mntent_opt(mntent);
- if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
- free(mntdata);
+ ret = parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata);
+ if (ret < 0)
return -1;
- }
ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags,
mntdata, optional, dev, rootfs_path);
static inline int mount_entry_on_systemfs(struct mntent *mntent)
{
- char path[MAXPATHLEN];
int ret;
+ char path[MAXPATHLEN];
/* For containers created without a rootfs all mounts are treated as
- * absolute paths starting at / on the host. */
+ * absolute paths starting at / on the host.
+ */
if (mntent->mnt_dir[0] != '/')
ret = snprintf(path, sizeof(path), "/%s", mntent->mnt_dir);
else
ret = snprintf(path, sizeof(path), "%s", mntent->mnt_dir);
-
- if (ret < 0 || ret >= sizeof(path)) {
- ERROR("path name too long");
+ if (ret < 0 || ret >= sizeof(path))
return -1;
- }
return mount_entry_on_generic(mntent, path, NULL, NULL, NULL);
}
const char *lxc_name,
const char *lxc_path)
{
+ int offset;
char *aux;
- char path[MAXPATHLEN];
- int r, ret = 0, offset;
const char *lxcpath;
+ char path[MAXPATHLEN];
+ int ret = 0;
lxcpath = lxc_global_config_value("lxc.lxcpath");
- if (!lxcpath) {
- ERROR("Out of memory");
+ if (!lxcpath)
return -1;
- }
- /* if rootfs->path is a blockdev path, allow container fstab to
- * use $lxcpath/CN/rootfs as the target prefix */
- r = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name);
- if (r < 0 || r >= MAXPATHLEN)
+ /* If rootfs->path is a blockdev path, allow container fstab to use
+ * <lxcpath>/<name>/rootfs" as the target prefix.
+ */
+ ret = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name);
+ if (ret < 0 || ret >= MAXPATHLEN)
goto skipvarlib;
aux = strstr(mntent->mnt_dir, path);
skipvarlib:
aux = strstr(mntent->mnt_dir, rootfs->path);
if (!aux) {
- WARN("ignoring mount point '%s'", mntent->mnt_dir);
+ WARN("Ignoring mount point \"%s\"", mntent->mnt_dir);
return ret;
}
offset = strlen(rootfs->path);
skipabs:
-
- r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
- aux + offset);
- if (r < 0 || r >= MAXPATHLEN) {
- WARN("pathnme too long for '%s'", mntent->mnt_dir);
+ ret = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount, aux + offset);
+ if (ret < 0 || ret >= MAXPATHLEN)
return -1;
- }
return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path);
}
return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path);
}
-static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
- const char *lxc_name, const char *lxc_path)
+/* This logs a NOTICE() when a user specifies mounts that would conflict with
+ * devices liblxc sets up automatically.
+ */
+static void log_notice_on_conflict(const struct lxc_conf *conf, const char *src,
+ const char *dest)
+{
+ char *clean_mnt_fsname, *clean_mnt_dir, *tmp;
+ bool needs_warning = false;
+
+ clean_mnt_fsname = lxc_deslashify(src);
+ if (!clean_mnt_fsname)
+ return;
+
+ clean_mnt_dir = lxc_deslashify(dest);
+ if (!clean_mnt_dir) {
+ free(clean_mnt_fsname);
+ return;
+ }
+
+ tmp = clean_mnt_dir;
+ if (*tmp == '/')
+ tmp++;
+
+ if (strncmp(src, "/dev", 4) || strncmp(tmp, "dev", 3)) {
+ free(clean_mnt_dir);
+ free(clean_mnt_fsname);
+ return;
+ }
+
+ if (!conf->autodev && !conf->pts && !conf->tty &&
+ (!conf->console.path || !strcmp(conf->console.path, "none"))) {
+ free(clean_mnt_dir);
+ free(clean_mnt_fsname);
+ return;
+ }
+
+ if (!strcmp(tmp, "dev") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/pts") && (conf->autodev > 0 || conf->pts > 0))
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/ptmx") && (conf->autodev > 0 || conf->pts > 0))
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/pts/ptmx") && (conf->autodev > 0 || conf->pts > 0))
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/null") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/zero") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/full") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/urandom") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/random") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strcmp(tmp, "dev/tty") && conf->autodev > 0)
+ needs_warning = true;
+ else if (!strncmp(tmp, "dev/tty", 7) && (conf->autodev > 0 || conf->tty > 0))
+ needs_warning = true;
+
+ if (needs_warning)
+ NOTICE("Requesting to mount \"%s\" on \"%s\" while requesting "
+ "automatic device setup under \"/dev\"",
+ clean_mnt_fsname, clean_mnt_dir);
+
+ free(clean_mnt_dir);
+ free(clean_mnt_fsname);
+}
+
+static int mount_file_entries(const struct lxc_conf *conf,
+ const struct lxc_rootfs *rootfs, FILE *file,
+ const char *lxc_name, const char *lxc_path)
{
struct mntent mntent;
char buf[4096];
int ret = -1;
while (getmntent_r(file, &mntent, buf, sizeof(buf))) {
+ log_notice_on_conflict(conf, mntent.mnt_fsname, mntent.mnt_dir);
- if (!rootfs->path) {
- if (mount_entry_on_systemfs(&mntent))
- goto out;
- continue;
- }
-
- /* We have a separate root, mounts are relative to it */
- if (mntent.mnt_dir[0] != '/') {
- if (mount_entry_on_relative_rootfs(&mntent, rootfs, lxc_name, lxc_path))
- goto out;
- continue;
- }
-
- if (mount_entry_on_absolute_rootfs(&mntent, rootfs, lxc_name, lxc_path))
- goto out;
+ if (!rootfs->path)
+ ret = mount_entry_on_systemfs(&mntent);
+ else if (mntent.mnt_dir[0] != '/')
+ ret = mount_entry_on_relative_rootfs(&mntent, rootfs,
+ lxc_name, lxc_path);
+ else
+ ret = mount_entry_on_absolute_rootfs(&mntent, rootfs,
+ lxc_name, lxc_path);
+ if (ret < 0)
+ return -1;
}
-
ret = 0;
- INFO("mount points have been setup");
-out:
+ INFO("Set up mount entries");
return ret;
}
-static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
- const char *lxc_name, const char *lxc_path)
+static int setup_mount(const struct lxc_conf *conf,
+ const struct lxc_rootfs *rootfs, const char *fstab,
+ const char *lxc_name, const char *lxc_path)
{
- FILE *file;
+ FILE *f;
int ret;
if (!fstab)
return 0;
- file = setmntent(fstab, "r");
- if (!file) {
- SYSERROR("failed to use '%s'", fstab);
+ f = setmntent(fstab, "r");
+ if (!f) {
+ SYSERROR("Failed to open \"%s\"", fstab);
return -1;
}
- ret = mount_file_entries(rootfs, file, lxc_name, lxc_path);
+ ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path);
+ if (ret < 0)
+ ERROR("Failed to set up mount entries");
- endmntent(file);
+ endmntent(f);
return ret;
}
int ret;
char *mount_entry;
struct lxc_list *iterator;
- FILE *file;
+ FILE *f;
int fd = -1;
fd = memfd_create("lxc_mount_file", MFD_CLOEXEC);
if (fd < 0) {
if (errno != ENOSYS)
return NULL;
- file = tmpfile();
+ f = tmpfile();
+ TRACE("Created temporary mount file");
} else {
- file = fdopen(fd, "r+");
+ f = fdopen(fd, "r+");
+ TRACE("Created anonymous mount file");
}
- if (!file) {
- int saved_errno = errno;
+ if (!f) {
+ SYSERROR("Could not create mount file");
if (fd != -1)
close(fd);
- ERROR("Could not create mount entry file: %s.", strerror(saved_errno));
return NULL;
}
lxc_list_for_each(iterator, mount) {
mount_entry = iterator->elem;
- ret = fprintf(file, "%s\n", mount_entry);
+ ret = fprintf(f, "%s\n", mount_entry);
if (ret < strlen(mount_entry))
- WARN("Could not write mount entry to anonymous mount file.");
+ WARN("Could not write mount entry to mount file");
}
- if (fseek(file, 0, SEEK_SET) < 0) {
- fclose(file);
+ ret = fseek(f, 0, SEEK_SET);
+ if (ret < 0) {
+ SYSERROR("Failed to seek mount file");
+ fclose(f);
return NULL;
}
- return file;
+ return f;
}
-static int setup_mount_entries(const struct lxc_rootfs *rootfs,
+static int setup_mount_entries(const struct lxc_conf *conf,
+ const struct lxc_rootfs *rootfs,
struct lxc_list *mount, const char *lxc_name,
const char *lxc_path)
{
- FILE *file;
+ FILE *f;
int ret;
- file = make_anonymous_mount_file(mount);
- if (!file)
+ f = make_anonymous_mount_file(mount);
+ if (!f)
return -1;
- ret = mount_file_entries(rootfs, file, lxc_name, lxc_path);
+ ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path);
- fclose(file);
+ fclose(f);
return ret;
}
{
uid_t rootuid, rootgid;
unsigned long val;
- char *chownpath = path;
int hostuid, hostgid, ret;
struct stat sb;
char map1[100], map2[100], map3[100], map4[100], map5[100];
}
rootgid = (gid_t)val;
- /*
- * In case of overlay, we want only the writeable layer to be chowned
- */
- if (strncmp(path, "overlayfs:", 10) == 0 || strncmp(path, "aufs:", 5) == 0) {
- chownpath = strchr(path, ':');
- if (!chownpath) {
- ERROR("Bad overlay path: %s", path);
- return -1;
- }
- chownpath = strchr(chownpath + 1, ':');
- if (!chownpath) {
- ERROR("Bad overlay path: %s", path);
- return -1;
- }
- chownpath++;
- }
- path = chownpath;
if (hostuid == 0) {
if (chown(path, rootuid, rootgid) < 0) {
ERROR("Error chowning %s", path);
return -1;
}
- if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath)) {
+ if (setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath)) {
ERROR("failed to setup the mounts for '%s'", name);
return -1;
}
- if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath)) {
+ if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(lxc_conf, &lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath)) {
ERROR("failed to setup the mount entries for '%s'", name);
return -1;
}
ERROR("failed to run autodev hooks for container '%s'.", name);
return -1;
}
+
if (lxc_fill_autodev(&lxc_conf->rootfs)) {
ERROR("failed to populate /dev in the container");
return -1;