Commit 7e395cae authored by Tycho Andersen's avatar Tycho Andersen Committed by Pavel Emelyanov

mnt: cut shared root path from bind path

If a mount like:

96 95 0:21 /cgmanager /sys/fs/cgroup/cgmanager rw master:9 - tmpfs tmpfs rw,mode=755

is present in the container and the host has a similar bind mount, e.g.

46 27 0:21 /cgmanager /sys/fs/cgroup/cgmanager rw shared:9 - tmpfs tmpfs rw,mode=755

then the best match mount's root path /and/ the target mountpoint have part of
the path in them; we should cut the shared piece of the path and just
concatenate the non-duplicate pieces.
Reported-by: 's avatarAndrew Vagin <avagin@odin.com>
CC: Andrew Vagin <avagin@odin.com>
Signed-off-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Acked-by: 's avatarAndrew Vagin <avagin@odin.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a1649fd3
...@@ -647,6 +647,25 @@ static int validate_mounts(struct mount_info *info, bool for_dump) ...@@ -647,6 +647,25 @@ static int validate_mounts(struct mount_info *info, bool for_dump)
return 0; return 0;
} }
static char *cut_root_for_bind(char *target_root, char *source_root)
{
int tok = 0;
/*
* Cut common part of root.
* For non-root binds the source is always "/" (checked)
* so this will result in this slash removal only.
*/
while (target_root[tok] == source_root[tok]) {
tok++;
if (source_root[tok] == '\0')
break;
BUG_ON(target_root[tok] == '\0');
}
return target_root + tok;
}
static struct mount_info *find_best_external_match(struct mount_info *list, struct mount_info *info) static struct mount_info *find_best_external_match(struct mount_info *list, struct mount_info *info)
{ {
struct mount_info *it, *candidate = NULL; struct mount_info *it, *candidate = NULL;
...@@ -722,7 +741,7 @@ static int resolve_external_mounts(struct mount_info *info) ...@@ -722,7 +741,7 @@ static int resolve_external_mounts(struct mount_info *info)
for (m = info; m; m = m->next) { for (m = info; m; m = m->next) {
int ret, size; int ret, size;
char *p; char *p, *cut_root;
struct ext_mount *em; struct ext_mount *em;
struct mount_info *match; struct mount_info *match;
...@@ -764,12 +783,16 @@ static int resolve_external_mounts(struct mount_info *info) ...@@ -764,12 +783,16 @@ static int resolve_external_mounts(struct mount_info *info)
continue; continue;
} }
size = strlen(match->mountpoint + 1) + strlen(m->root) + 1; cut_root = cut_root_for_bind(m->root, match->root);
/* +2 for the NULL byte and the extra / in the sprintf below,
* which we cut off in cut_root_for_bind(). */
size = strlen(match->mountpoint + 1) + strlen(cut_root) + 2;
p = xmalloc(sizeof(char) * size); p = xmalloc(sizeof(char) * size);
if (!p) if (!p)
return -1; return -1;
ret = snprintf(p, size, "%s%s", match->mountpoint + 1, m->root); ret = snprintf(p, size, "%s/%s", match->mountpoint + 1, cut_root);
if (ret < 0 || ret >= size) { if (ret < 0 || ret >= size) {
free(p); free(p);
return -1; return -1;
...@@ -1817,8 +1840,7 @@ static int do_bind_mount(struct mount_info *mi) ...@@ -1817,8 +1840,7 @@ static int do_bind_mount(struct mount_info *mi)
bool force_private_remount = false; bool force_private_remount = false;
if (!mi->need_plugin) { if (!mi->need_plugin) {
char *root, rpath[PATH_MAX]; char *root, *cut_root, rpath[PATH_MAX];
int tok = 0;
if (mi->external) { if (mi->external) {
/* /*
...@@ -1833,21 +1855,10 @@ static int do_bind_mount(struct mount_info *mi) ...@@ -1833,21 +1855,10 @@ static int do_bind_mount(struct mount_info *mi)
} }
shared = mi->shared_id && mi->shared_id == mi->bind->shared_id; shared = mi->shared_id && mi->shared_id == mi->bind->shared_id;
cut_root = cut_root_for_bind(mi->root, mi->bind->root);
/*
* Cut common part of root.
* For non-root binds the source is always "/" (checked)
* so this will result in this slash removal only.
*/
while (mi->root[tok] == mi->bind->root[tok]) {
tok++;
if (mi->bind->root[tok] == '\0')
break;
BUG_ON(mi->root[tok] == '\0');
}
snprintf(rpath, sizeof(rpath), "%s/%s", snprintf(rpath, sizeof(rpath), "%s/%s",
mi->bind->mountpoint, mi->root + tok); mi->bind->mountpoint, cut_root);
root = rpath; root = rpath;
do_bind: do_bind:
pr_info("\tBind %s to %s\n", root, mi->mountpoint); pr_info("\tBind %s to %s\n", root, mi->mountpoint);
......
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