Skip to content

Commit

Permalink
linux: add new fallback when mount fails with EBUSY
Browse files Browse the repository at this point in the history
if the mount fails with EBUSY, attempt to mount it to a temporary
directory under the state directory and then move it to the correct
destination with MS_MOVE.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Sep 21, 2023
1 parent 2239c50 commit 523eed3
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 2 deletions.
33 changes: 31 additions & 2 deletions src/libcrun/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -1317,8 +1317,37 @@ do_mount_cgroup_v2 (libcrun_container_t *container, int targetfd, const char *ta
if (errno == EBUSY)
{
/* If we got EBUSY it means the cgroup file system is already mounted at the targetfd and we
cannot stack another one on top of it. Place a tmpfs in the middle, then try again. */
ret = do_mount (container, "tmpfs", targetfd, target, "tmpfs", 0, "nr_blocks=1,nr_inodes=1", LABEL_NONE, err);
cannot stack another one on top of it. First attempt with a temporary mount and then move
it to the destination directory. If that cannot be used try mounting a tmpfs below the
cgroup mount. */
cleanup_free char *state_dir = NULL;

state_dir = libcrun_get_state_directory (container->context->state_root, container->context->id);

if (state_dir)
{
cleanup_free char *tmp_mount_dir = NULL;

ret = append_paths (&tmp_mount_dir, err, state_dir, "tmpmount", NULL);
if (UNLIKELY (ret < 0))
return ret;

ret = crun_ensure_directory (tmp_mount_dir, 0700, true, err);
if (UNLIKELY (ret < 0))
return ret;

ret = mount ("cgroup2", tmp_mount_dir, "cgroup2", 0, NULL);
if (LIKELY (ret == 0))
{
ret = do_mount (container, tmp_mount_dir, targetfd, target, NULL, MS_MOVE | mountflags, NULL, LABEL_NONE, err);
if (LIKELY (ret == 0))
return 0;

crun_error_release (err);
}
}

ret = do_mount (container, "tmpfs", targetfd, target, "tmpfs", MS_PRIVATE, "nr_blocks=1,nr_inodes=1", LABEL_NONE, err);
if (LIKELY (ret == 0))
{
ret = do_mount (container, "cgroup2", targetfd, target, "cgroup2", mountflags, NULL, LABEL_NONE, err);
Expand Down
51 changes: 51 additions & 0 deletions tests/test_mounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,56 @@ def check(uidMappings, gidMappings, recursive, expected):

return 0

def test_cgroup_mount_without_netns():
for cgroupns in [True, False]:
conf = base_config()
conf['process']['args'] = ['/init', 'cat', '/proc/self/mountinfo']
add_all_namespaces(conf, cgroupns=cgroupns, netns=False)
mounts = [
{
"destination": "/proc",
"type": "proc"
},
{
"destination": "/sys",
"type": "bind",
"source": "/sys",
"options": [
"rprivate",
"nosuid",
"noexec",
"nodev",
"ro",
"rbind"
]
},
{
"destination": "/sys/fs/cgroup",
"type": "cgroup",
"source": "cgroup",
"options": [
"rprivate",
"nosuid",
"noexec",
"nodev",
"rprivate",
"relatime",
"ro"
]
}
]

conf['mounts'] = mounts

out, _ = run_and_get_output(conf)
print(out)
for i in out.split("\n"):
if i.find("/sys/fs/cgroup") >= 0:
if i.find("tmpfs") >= 0:
print("tmpfs temporary mount still present with cgroupns=%s %s" % (cgroupns, i))
return -1
return 0

all_tests = {
"mount-ro" : test_mount_ro,
"mount-rw" : test_mount_rw,
Expand All @@ -439,6 +489,7 @@ def check(uidMappings, gidMappings, recursive, expected):
"mount-linux-readonly-should-inherit-flags": test_mount_readonly_should_inherit_options_from_parent,
"proc-linux-readonly-should-inherit-flags": test_proc_readonly_should_inherit_options_from_parent,
"mount-ro-cgroup": test_ro_cgroup,
"cgroup-mount-without-netns": test_cgroup_mount_without_netns,
}

if __name__ == "__main__":
Expand Down

0 comments on commit 523eed3

Please sign in to comment.