Unverified Commit f6276497 by Stéphane Graber Committed by GitHub

Merge pull request #3707 from brauner/2021-03-09/fixes

conf: automount fixes
parents 90b7adcc 96f306e6
...@@ -613,24 +613,40 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags) ...@@ -613,24 +613,40 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags)
bool has_cap_net_admin; bool has_cap_net_admin;
if (flags & LXC_AUTO_PROC_MASK) { if (flags & LXC_AUTO_PROC_MASK) {
ret = strnprintf(rootfs->buf, sizeof(rootfs->buf), "%s/proc",
rootfs->path ? rootfs->mount : "");
if (ret < 0)
return ret_errno(EIO);
ret = umount2(rootfs->buf, MNT_DETACH);
if (ret)
SYSDEBUG("Tried to ensure procfs is unmounted");
ret = mkdirat(rootfs->dfd_mnt, "proc" , S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); ret = mkdirat(rootfs->dfd_mnt, "proc" , S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-errno, errno, return syserror("Failed to create procfs mountpoint under %d", rootfs->dfd_mnt);
"Failed to create proc mountpoint under %d", rootfs->dfd_mnt);
} }
if (flags & LXC_AUTO_SYS_MASK) { if (flags & LXC_AUTO_SYS_MASK) {
ret = strnprintf(rootfs->buf, sizeof(rootfs->buf), "%s/sys",
rootfs->path ? rootfs->mount : "");
if (ret < 0)
return ret_errno(EIO);
ret = umount2(rootfs->buf, MNT_DETACH);
if (ret)
SYSDEBUG("Tried to ensure sysfs is unmounted");
ret = mkdirat(rootfs->dfd_mnt, "sys" , S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); ret = mkdirat(rootfs->dfd_mnt, "sys" , S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-errno, errno, return syserror("Failed to create sysfs mountpoint under %d", rootfs->dfd_mnt);
"Failed to create sysfs mountpoint under %d", rootfs->dfd_mnt);
} }
has_cap_net_admin = lxc_wants_cap(CAP_NET_ADMIN, conf); has_cap_net_admin = lxc_wants_cap(CAP_NET_ADMIN, conf);
for (i = 0; default_mounts[i].match_mask; i++) { for (i = 0; default_mounts[i].match_mask; i++) {
__do_free char *destination = NULL, *source = NULL; __do_free char *destination = NULL, *source = NULL;
int saved_errno;
unsigned long mflags; unsigned long mflags;
if ((flags & default_mounts[i].match_mask) != default_mounts[i].match_flag) if ((flags & default_mounts[i].match_mask) != default_mounts[i].match_flag)
continue; continue;
...@@ -638,11 +654,11 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags) ...@@ -638,11 +654,11 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags)
/* will act like strdup if %r is not present */ /* will act like strdup if %r is not present */
source = lxc_string_replace("%r", rootfs->path ? rootfs->mount : "", default_mounts[i].source); source = lxc_string_replace("%r", rootfs->path ? rootfs->mount : "", default_mounts[i].source);
if (!source) if (!source)
return -1; return syserror_set(-ENOMEM, "Failed to create source path");
} }
if (!default_mounts[i].destination) if (!default_mounts[i].destination)
return log_error(-1, "BUG: auto mounts destination %d was NULL", i); return syserror_set(-EINVAL, "BUG: auto mounts destination %d was NULL", i);
if (!has_cap_net_admin && default_mounts[i].requires_cap_net_admin) { if (!has_cap_net_admin && default_mounts[i].requires_cap_net_admin) {
TRACE("Container does not have CAP_NET_ADMIN. Skipping \"%s\" mount", default_mounts[i].source ?: "(null)"); TRACE("Container does not have CAP_NET_ADMIN. Skipping \"%s\" mount", default_mounts[i].source ?: "(null)");
...@@ -652,25 +668,21 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags) ...@@ -652,25 +668,21 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags)
/* will act like strdup if %r is not present */ /* will act like strdup if %r is not present */
destination = lxc_string_replace("%r", rootfs->path ? rootfs->mount : "", default_mounts[i].destination); destination = lxc_string_replace("%r", rootfs->path ? rootfs->mount : "", default_mounts[i].destination);
if (!destination) if (!destination)
return -1; return syserror_set(-ENOMEM, "Failed to create target path");
mflags = add_required_remount_flags(source, destination, mflags = add_required_remount_flags(source, destination,
default_mounts[i].flags); default_mounts[i].flags);
ret = safe_mount(source, destination, default_mounts[i].fstype, ret = safe_mount(source, destination, default_mounts[i].fstype,
mflags, default_mounts[i].options, mflags, default_mounts[i].options,
rootfs->path ? rootfs->mount : NULL); rootfs->path ? rootfs->mount : NULL);
saved_errno = errno;
if (ret < 0 && errno == ENOENT) {
INFO("Mount source or target for \"%s\" on \"%s\" does not exist. Skipping", source, destination);
ret = 0;
} else if (ret < 0) {
SYSERROR("Failed to mount \"%s\" on \"%s\" with flags %lu", source, destination, mflags);
}
if (ret < 0) { if (ret < 0) {
errno = saved_errno; if (errno != ENOENT)
return -1; return syserror("Failed to mount \"%s\" on \"%s\" with flags %lu", source, destination, mflags);
INFO("Mount source or target for \"%s\" on \"%s\" does not exist. Skipping", source, destination);
continue;
} }
TRACE("Mounted automount \"%s\" on \"%s\" with flags %lu", source, destination, mflags);
} }
if (flags & LXC_AUTO_CGROUP_MASK) { if (flags & LXC_AUTO_CGROUP_MASK) {
...@@ -3111,7 +3123,7 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf) ...@@ -3111,7 +3123,7 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf)
} }
/* Walk /proc/mounts and change any shared entries to dependent mounts. */ /* Walk /proc/mounts and change any shared entries to dependent mounts. */
void turn_into_dependent_mounts(void) static void turn_into_dependent_mounts(const struct lxc_rootfs *rootfs)
{ {
__do_free char *line = NULL; __do_free char *line = NULL;
__do_fclose FILE *f = NULL; __do_fclose FILE *f = NULL;
...@@ -3120,9 +3132,10 @@ void turn_into_dependent_mounts(void) ...@@ -3120,9 +3132,10 @@ void turn_into_dependent_mounts(void)
ssize_t copied; ssize_t copied;
int ret; int ret;
mntinfo_fd = open("/proc/self/mountinfo", O_RDONLY | O_CLOEXEC); mntinfo_fd = open_at(rootfs->dfd_host, "proc/self/mountinfo", PROTECT_OPEN,
(PROTECT_LOOKUP_BENEATH_XDEV & ~RESOLVE_NO_SYMLINKS), 0);
if (mntinfo_fd < 0) { if (mntinfo_fd < 0) {
SYSERROR("Failed to open \"/proc/self/mountinfo\""); SYSERROR("Failed to open %d/proc/self/mountinfo", rootfs->dfd_host);
return; return;
} }
...@@ -3187,7 +3200,6 @@ void turn_into_dependent_mounts(void) ...@@ -3187,7 +3200,6 @@ void turn_into_dependent_mounts(void)
SYSERROR("Failed to recursively turn old root mount tree into dependent mount. Continuing..."); SYSERROR("Failed to recursively turn old root mount tree into dependent mount. Continuing...");
continue; continue;
} }
TRACE("Recursively turned old root mount tree into dependent mount");
} }
TRACE("Turned all mount table entries into dependent mount"); TRACE("Turned all mount table entries into dependent mount");
} }
...@@ -3256,10 +3268,13 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, ...@@ -3256,10 +3268,13 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
if (conf->rootfs.dfd_host < 0) if (conf->rootfs.dfd_host < 0)
return log_error_errno(-errno, errno, "Failed to open \"/\""); return log_error_errno(-errno, errno, "Failed to open \"/\"");
turn_into_dependent_mounts(&conf->rootfs);
if (conf->rootfs_setup) { if (conf->rootfs_setup) {
const char *path = conf->rootfs.mount; const char *path = conf->rootfs.mount;
/* The rootfs was set up in another namespace. bind-mount it to /*
* The rootfs was set up in another namespace. bind-mount it to
* give us a mount in our own ns so we can pivot_root to it * give us a mount in our own ns so we can pivot_root to it
*/ */
ret = mount(path, path, "rootfs", MS_BIND, NULL); ret = mount(path, path, "rootfs", MS_BIND, NULL);
...@@ -3273,8 +3288,6 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, ...@@ -3273,8 +3288,6 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
return log_trace(0, "Bind mounted container / onto itself"); return log_trace(0, "Bind mounted container / onto itself");
} }
turn_into_dependent_mounts();
ret = run_lxc_hooks(name, "pre-mount", conf, NULL); ret = run_lxc_hooks(name, "pre-mount", conf, NULL);
if (ret < 0) if (ret < 0)
return log_error(-1, "Failed to run pre-mount hooks"); return log_error(-1, "Failed to run pre-mount hooks");
...@@ -3521,7 +3534,7 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3521,7 +3534,7 @@ int lxc_setup(struct lxc_handler *handler)
ret = lxc_create_tmp_proc_mount(lxc_conf); ret = lxc_create_tmp_proc_mount(lxc_conf);
if (ret < 0) if (ret < 0)
return log_error(-1, "Failed to \"/proc\" LSMs"); return log_error(-1, "Failed to mount transient procfs instance for LSMs");
ret = lxc_setup_console(handler, &lxc_conf->rootfs, &lxc_conf->console, ret = lxc_setup_console(handler, &lxc_conf->rootfs, &lxc_conf->console,
lxc_conf->ttys.dir); lxc_conf->ttys.dir);
......
...@@ -514,7 +514,6 @@ __hidden extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), v ...@@ -514,7 +514,6 @@ __hidden extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), v
__hidden extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata); __hidden extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata);
__hidden extern int parse_propagationopts(const char *mntopts, unsigned long *pflags); __hidden extern int parse_propagationopts(const char *mntopts, unsigned long *pflags);
__hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); __hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
__hidden extern void turn_into_dependent_mounts(void);
__hidden extern void suggest_default_idmap(void); __hidden extern void suggest_default_idmap(void);
__hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers); __hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers);
__hidden extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings); __hidden extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings);
......
...@@ -2050,7 +2050,6 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops, ...@@ -2050,7 +2050,6 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
} }
INFO("Unshared CLONE_NEWNS"); INFO("Unshared CLONE_NEWNS");
turn_into_dependent_mounts();
ret = lxc_setup_rootfs_prepare_root(conf, name, lxcpath); ret = lxc_setup_rootfs_prepare_root(conf, name, lxcpath);
if (ret < 0) { if (ret < 0) {
ERROR("Error setting up rootfs mount as root before spawn"); ERROR("Error setting up rootfs mount as root before spawn");
......
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