Commit 24f63b5f authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

mount: open a mount point if it's going to be overmounted

If a mount point has to be bind-mounted to somewhere, we need to have
access to it. This patch solves a problem, when the mount point is
overmounted. In this case we can open the targret mount point and then
use /proc/pid/FD to access it.

v2: make a bind-mount from an underlying mount via a file descriptor
v3: add a separate buffer to generate path to a file descriptor
v4: use the PSFDS contant.
Reported-by: 's avatarStanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Cc: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent fe5a5ba2
...@@ -49,6 +49,7 @@ struct mount_info { ...@@ -49,6 +49,7 @@ struct mount_info {
*/ */
char *mountpoint; char *mountpoint;
char *ns_mountpoint; char *ns_mountpoint;
int fd;
unsigned flags; unsigned flags;
unsigned sb_flags; unsigned sb_flags;
int master_id; int master_id;
......
...@@ -2451,6 +2451,7 @@ static int umount_clean_path() ...@@ -2451,6 +2451,7 @@ static int umount_clean_path()
static int do_bind_mount(struct mount_info *mi) static int do_bind_mount(struct mount_info *mi)
{ {
char mnt_fd_path[PSFDS];
char *root, *cut_root, rpath[PATH_MAX]; char *root, *cut_root, rpath[PATH_MAX];
unsigned long mflags; unsigned long mflags;
int exit_code = -1; int exit_code = -1;
...@@ -2484,11 +2485,23 @@ static int do_bind_mount(struct mount_info *mi) ...@@ -2484,11 +2485,23 @@ static int do_bind_mount(struct mount_info *mi)
private = !mi->master_id && !shared; private = !mi->master_id && !shared;
cut_root = cut_root_for_bind(mi->root, mi->bind->root); cut_root = cut_root_for_bind(mi->root, mi->bind->root);
if (list_empty(&mi->bind->children)) /* Mount private can be initialized on mount() callback, which is
mnt_path = mi->bind->mountpoint; * called only once.
else { * It have to be copied to all it's sibling structures to provide users
* of it with actual data.
*/
mi->private = mi->bind->private;
mnt_path = mi->bind->mountpoint;
if (mi->bind->fd >= 0) {
snprintf(mnt_fd_path, sizeof(mnt_fd_path),
"/proc/self/fd/%d", mi->bind->fd);
mnt_path = mnt_fd_path;
}
if (!list_empty(&mi->bind->children)) {
/* mi->bind->mountpoint may be overmounted */ /* mi->bind->mountpoint may be overmounted */
if (mount(mi->bind->mountpoint, mnt_clean_path, NULL, MS_BIND, NULL)) { if (mount(mnt_path, mnt_clean_path, NULL, MS_BIND, NULL)) {
pr_perror("Unable to bind-mount %s to %s", pr_perror("Unable to bind-mount %s to %s",
mi->bind->mountpoint, mnt_clean_path); mi->bind->mountpoint, mnt_clean_path);
} }
...@@ -2643,6 +2656,12 @@ static int do_mount_root(struct mount_info *mi) ...@@ -2643,6 +2656,12 @@ static int do_mount_root(struct mount_info *mi)
return fetch_rt_stat(mi, mi->mountpoint); return fetch_rt_stat(mi, mi->mountpoint);
} }
static int do_close_one(struct mount_info *mi)
{
close_safe(&mi->fd);
return 0;
}
static int do_mount_one(struct mount_info *mi) static int do_mount_one(struct mount_info *mi)
{ {
int ret; int ret;
...@@ -2655,6 +2674,14 @@ static int do_mount_one(struct mount_info *mi) ...@@ -2655,6 +2674,14 @@ static int do_mount_one(struct mount_info *mi)
return 1; return 1;
} }
if (mi->parent && !strcmp(mi->parent->mountpoint, mi->mountpoint)) {
mi->parent->fd = open(mi->parent->mountpoint, O_PATH);
if (mi->parent->fd < 0) {
pr_perror("Unable to open %s", mi->mountpoint);
return -1;
}
}
pr_debug("\tMounting %s @%s (%d)\n", mi->fstype->name, mi->mountpoint, mi->need_plugin); pr_debug("\tMounting %s @%s (%d)\n", mi->fstype->name, mi->mountpoint, mi->need_plugin);
if (!mi->parent) { if (!mi->parent) {
...@@ -2777,6 +2804,7 @@ struct mount_info *mnt_entry_alloc() ...@@ -2777,6 +2804,7 @@ struct mount_info *mnt_entry_alloc()
new = xzalloc(sizeof(struct mount_info)); new = xzalloc(sizeof(struct mount_info));
if (new) { if (new) {
new->fd = -1;
INIT_LIST_HEAD(&new->children); INIT_LIST_HEAD(&new->children);
INIT_LIST_HEAD(&new->siblings); INIT_LIST_HEAD(&new->siblings);
INIT_LIST_HEAD(&new->mnt_slave_list); INIT_LIST_HEAD(&new->mnt_slave_list);
...@@ -3254,6 +3282,7 @@ static int populate_mnt_ns(void) ...@@ -3254,6 +3282,7 @@ static int populate_mnt_ns(void)
return -1; return -1;
ret = mnt_tree_for_each(pms, do_mount_one); ret = mnt_tree_for_each(pms, do_mount_one);
mnt_tree_for_each(pms, do_close_one);
if (umount_clean_path()) if (umount_clean_path())
return -1; return -1;
......
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