diff options
author | Pavel Tikhomirov <ptikhomirov@virtuozzo.com> | 2022-01-12 16:00:56 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2022-04-29 03:53:52 +0300 |
commit | e50abbd3b38539c1dc72b67940e5fd5604934199 (patch) | |
tree | 108f138a3d444593cdc03dc0ba257f0aa066ddad /test | |
parent | a963ceb7702466f068c808fabc4741068ce20704 (diff) |
zdtm: add mnt_ext_collision test
This test creates two mount namespaces, one "root" with external mount
at /mnt_ext_collision.test/dst and one "nested" with different internal
mount at /mnt_ext_collision.test/dst instead.
This case is important for nested containers, if we dump a container
with some external mount in /mnt we should not also replace mounts in
/mnt for nested containers with the external one. (One example is docker
containers inside Virtuozzo containers.)
Without previous patch which restricts external mounts resolution to
only root mntns of container this test fails as internal mount is
replaced by external one after migration.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/zdtm/static/Makefile | 1 | ||||
-rw-r--r-- | test/zdtm/static/mnt_ext_collision.c | 194 | ||||
-rw-r--r-- | test/zdtm/static/mnt_ext_collision.desc | 5 | ||||
-rwxr-xr-x | test/zdtm/static/mnt_ext_collision.hook | 12 |
4 files changed, 212 insertions, 0 deletions
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index a64c51cd0..565b32400 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -400,6 +400,7 @@ TST_DIR = \ mnt_ext_master \ mnt_ext_dev \ mnt_ext_root \ + mnt_ext_collision \ mnt_tracefs \ mntns_deleted \ unlink_regular00 \ diff --git a/test/zdtm/static/mnt_ext_collision.c b/test/zdtm/static/mnt_ext_collision.c new file mode 100644 index 000000000..324a3484c --- /dev/null +++ b/test/zdtm/static/mnt_ext_collision.c @@ -0,0 +1,194 @@ +#include <sched.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <linux/limits.h> + +#include "zdtmtst.h" +#include "lock.h" + +const char *test_doc = "Check external mount mountpoint collide with different mount in nested mntns"; +const char *test_author = "Pavel Tikhomirov <ptikhomirov@virtuozzo.com>"; + +char *dirname = "mnt_ext_collision.test"; +TEST_OPTION(dirname, string, "directory name", 1); + +char *source = "zdtm_ext_collision"; +char *source2 = "zdtm_ext_collision_2"; + +enum { + TEST_INIT = 0, + TEST_CHILD, + TEST_CHECK, + TEST_EXIT, + EMERGENCY_ABORT, +}; + +futex_t *futex; + +#define BUF_SIZE 4096 + +static int child(void) +{ + char dst[PATH_MAX], dst_file[PATH_MAX]; + int fd; + + if (unshare(CLONE_NEWNS)) { + pr_perror("unshare"); + goto err; + } + + /* + * Umount external mount copy + */ + sprintf(dst, "/%s/dst", dirname); + if (umount(dst)) { + pr_perror("umount"); + goto err; + } + + /* + * Mount tmpfs in its place + */ + if (mount(source2, dst, "tmpfs", 0, NULL)) { + pr_perror("mount tmpfs"); + goto err; + } + + sprintf(dst_file, "/%s/dst/file", dirname); + fd = open(dst_file, O_RDWR | O_CREAT | O_EXCL, 0666); + if (fd < 0) { + pr_perror("open"); + goto err; + } + close(fd); + + futex_set_and_wake(futex, TEST_CHILD); + futex_wait_while_lt(futex, TEST_CHECK); + + if (access(dst_file, F_OK)) { + pr_perror("access"); + goto err; + } + + futex_set_and_wake(futex, TEST_EXIT); + return 0; +err: + futex_set_and_wake(futex, EMERGENCY_ABORT); + return 1; +} + +int main(int argc, char **argv) +{ + char *root, testdir[PATH_MAX]; + char lckd[PATH_MAX], dst[PATH_MAX]; + char *tmp = "/tmp/zdtm_ext_collision.tmp"; + char *zdtm_newns = getenv("ZDTM_NEWNS"); + int pid; + + root = getenv("ZDTM_ROOT"); + if (root == NULL) { + pr_perror("root"); + return 1; + } + + if (!zdtm_newns) { + pr_perror("ZDTM_NEWNS is not set"); + return 1; + } else if (strcmp(zdtm_newns, "1")) { + goto test; + } + + /* Prepare directories in test root */ + sprintf(testdir, "%s/%s", root, dirname); + mkdir(testdir, 0755); + + sprintf(lckd, "%s/%s/lckd", root, dirname); + mkdir(lckd, 0755); + sprintf(dst, "%s/%s/dst", root, dirname); + mkdir(dst, 0755); + + /* Prepare mount in criu root */ + mkdir(tmp, 0755); + if (mount(source, tmp, "tmpfs", 0, NULL)) { + pr_perror("mount tmpfs"); + return 1; + } + if (mount(NULL, tmp, NULL, MS_PRIVATE, NULL)) { + pr_perror("make private"); + return 1; + } + + /* + * Create temporary mntns, next mounts will not show up in criu mntns + */ + if (unshare(CLONE_NEWNS)) { + pr_perror("unshare"); + return 1; + } + + /* + * Populate external mount to the tests mntns root + * (in uns flavour this would become locked) + */ + if (mount(tmp, lckd, NULL, MS_BIND, NULL)) { + pr_perror("bind"); + return 1; + } +test: + test_init(argc, argv); + + /* + * Hack to create unlocked external mount without pivot_root+bind thing + */ + sprintf(lckd, "/%s/lckd", dirname); + sprintf(dst, "/%s/dst", dirname); + if (mount(lckd, dst, NULL, MS_BIND, NULL)) { + pr_perror("bind"); + return 1; + } + + /* + * Setup futex for processes syncronization + */ + futex = mmap(NULL, sizeof(futex), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (futex == MAP_FAILED) { + pr_perror("mmap"); + return 1; + } + futex_init(futex); + + /* + * Fork child which would have nested mntns + */ + pid = fork(); + if (pid < 0) { + pr_perror("fork"); + return 1; + } else if (pid == 0) { + exit(child()); + } + + futex_wait_while_lt(futex, TEST_CHILD); + if (futex_get(futex) == EMERGENCY_ABORT) { + pr_err("Fail in child\n"); + return 1; + } + + test_daemon(); + test_waitsig(); + + futex_set_and_wake(futex, TEST_CHECK); + futex_wait_while_lt(futex, TEST_EXIT); + if (futex_get(futex) == EMERGENCY_ABORT) { + fail("Fail in child on check stage"); + return 1; + } + + waitpid(pid, NULL, 0); + pass(); + return 0; +} diff --git a/test/zdtm/static/mnt_ext_collision.desc b/test/zdtm/static/mnt_ext_collision.desc new file mode 100644 index 000000000..9b68a4ae0 --- /dev/null +++ b/test/zdtm/static/mnt_ext_collision.desc @@ -0,0 +1,5 @@ +{ 'dopts': '--external mnt[/mnt_ext_collision.test/dst]:ZDTM', + 'feature': 'mnt_id', + 'flavor': 'ns uns', + 'flags': 'suid', + 'ropts': '--external mnt[ZDTM]:/tmp/zdtm_ext_collision.tmp'} diff --git a/test/zdtm/static/mnt_ext_collision.hook b/test/zdtm/static/mnt_ext_collision.hook new file mode 100755 index 000000000..31c908d67 --- /dev/null +++ b/test/zdtm/static/mnt_ext_collision.hook @@ -0,0 +1,12 @@ +#!/bin/bash + +[ "$1" == "--clean" ] || exit 0 + +TMP="/tmp/zdtm_ext_collision.tmp" +echo "Cleanup mnt_ext_collision" +umount "$TMP" +rm -rf $TMP + +rm -rf "mnt_ext_collision.test" + +exit 0 |