]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: add test for umount_recursive()
authorLennart Poettering <lennart@poettering.net>
Tue, 16 May 2023 13:41:48 +0000 (15:41 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 17 May 2023 08:29:53 +0000 (10:29 +0200)
src/test/meson.build
src/test/test-mount-util.c

index 7f8de2a2ce20ea7376db421793690e834f73009a..d7eb2a857ddf63e963854206ef6eec6f49d2ade1 100644 (file)
@@ -117,7 +117,6 @@ simple_tests += files(
         'test-mempool.c',
         'test-mkdir.c',
         'test-modhex.c',
-        'test-mount-util.c',
         'test-mountpoint-util.c',
         'test-net-naming-scheme.c',
         'test-nulstr-util.c',
@@ -319,6 +318,10 @@ tests += [
                 'sources' : files('test-mempress.c'),
                 'dependencies' : threads,
         },
+        {
+                'sources' : files('test-mount-util.c'),
+                'dependencies' : libmount,
+        },
         {
                 'sources' : files('test-netlink-manual.c'),
                 'dependencies' : libkmod,
index a395f0cc6d084072470b1b92f0e926f269aea677..2529b2f0eee87852e185c01b18271461ed4e8076 100644 (file)
@@ -8,6 +8,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "libmount-util.h"
 #include "missing_magic.h"
 #include "missing_mount.h"
 #include "mkdir.h"
@@ -406,7 +407,7 @@ TEST(make_mount_switch_root) {
         assert_se(touch(s) >= 0);
 
         for (int force_ms_move = 0; force_ms_move < 2; force_ms_move++) {
-                r = safe_fork("(switch-root",
+                r = safe_fork("(switch-root)",
                               FORK_RESET_SIGNALS |
                               FORK_CLOSE_ALL_FDS |
                               FORK_DEATHSIG |
@@ -431,6 +432,93 @@ TEST(make_mount_switch_root) {
         }
 }
 
+TEST(umount_recursive) {
+        static const struct {
+                const char *prefix;
+                const char * const keep[3];
+        } test_table[] = {
+                {
+                        .prefix = NULL,
+                        .keep = {},
+                },
+                {
+                        .prefix = "/run",
+                        .keep = {},
+                },
+                {
+                        .prefix = NULL,
+                        .keep = { "/dev/shm", NULL },
+                },
+                {
+                        .prefix = "/dev",
+                        .keep = { "/dev/pts", "/dev/shm", NULL },
+                },
+        };
+
+        int r;
+
+        FOREACH_ARRAY(t, test_table, ELEMENTSOF(test_table)) {
+
+                r = safe_fork("(umount-rec)",
+                              FORK_RESET_SIGNALS |
+                              FORK_CLOSE_ALL_FDS |
+                              FORK_DEATHSIG |
+                              FORK_WAIT |
+                              FORK_REOPEN_LOG |
+                              FORK_LOG |
+                              FORK_NEW_MOUNTNS |
+                              FORK_MOUNTNS_SLAVE,
+                              NULL);
+
+                if (r < 0 && ERRNO_IS_PRIVILEGE(r)) {
+                        log_notice("Skipping umount_recursive() test, lacking privileges");
+                        return;
+                }
+
+                assert_se(r >= 0);
+                if (r == 0) { /* child */
+                        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+                        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
+                        _cleanup_fclose_ FILE *f = NULL;
+                        _cleanup_free_ char *k = NULL;
+
+                        /* Open /p/s/m file before we unmount everything (which might include /proc/) */
+                        f = fopen("/proc/self/mountinfo", "re");
+                        if (!f) {
+                                log_error_errno(errno, "Faile to open /proc/self/mountinfo: %m");
+                                _exit(EXIT_FAILURE);
+                        }
+
+                        assert_se(k = strv_join((char**) t->keep, " "));
+                        log_info("detaching just %s (keep: %s)", strna(t->prefix), strna(empty_to_null(k)));
+
+                        assert_se(umount_recursive_full(t->prefix, MNT_DETACH, (char**) t->keep) >= 0);
+
+                        r = libmount_parse("/proc/self/mountinfo", f, &table, &iter);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
+                                _exit(EXIT_FAILURE);
+                        }
+
+                        for (;;) {
+                                struct libmnt_fs *fs;
+
+                                r = mnt_table_next_fs(table, iter, &fs);
+                                if (r == 1)
+                                        break;
+                                if (r < 0) {
+                                        log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
+                                        _exit(EXIT_FAILURE);
+                                }
+
+                                log_debug("left after complete umount: %s", mnt_fs_get_target(fs));
+                        }
+
+                        _exit(EXIT_SUCCESS);
+                }
+        }
+}
+
 static int intro(void) {
          /* Create a dummy network interface for testing remount_sysfs(). */
         (void) system("ip link add dummy-test-mnt type dummy");