From fd99ead01deb2fa979dd7cff5b07b69a851605c9 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 9 Feb 2026 21:58:48 +0100 Subject: [PATCH] test-userns-restrict: Migrate to new assertion macros We also inline the test functions so we get proper line information in the failure coredumps. --- src/nsresourced/test-userns-restrict.c | 168 +++++++++---------------- 1 file changed, 62 insertions(+), 106 deletions(-) diff --git a/src/nsresourced/test-userns-restrict.c b/src/nsresourced/test-userns-restrict.c index b40c6551bca..dc06b7b08f7 100644 --- a/src/nsresourced/test-userns-restrict.c +++ b/src/nsresourced/test-userns-restrict.c @@ -8,180 +8,136 @@ #include "errno-util.h" #include "fd-util.h" -#include "log.h" -#include "main-func.h" #include "namespace-util.h" #include "pidref.h" #include "process-util.h" #include "rm-rf.h" +#include "tests.h" #include "tmpfile-util.h" #include "userns-restrict.h" static int make_tmpfs_fsmount(void) { _cleanup_close_ int fsfd = -EBADF, mntfd = -EBADF; - fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC); - assert_se(fsfd >= 0); - assert_se(fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0) >= 0); + fsfd = ASSERT_OK_ERRNO(fsopen("tmpfs", FSOPEN_CLOEXEC)); + ASSERT_OK_ERRNO(fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0)); - mntfd = fsmount(fsfd, FSMOUNT_CLOEXEC, 0); - assert_se(mntfd >= 0); + mntfd = ASSERT_OK_ERRNO(fsmount(fsfd, FSMOUNT_CLOEXEC, 0)); return TAKE_FD(mntfd); } -static void test_works_reg(int parent_fd, const char *fname) { - _cleanup_close_ int fd = -EBADF; +static struct userns_restrict_bpf *bpf_obj = NULL; +STATIC_DESTRUCTOR_REGISTER(bpf_obj, userns_restrict_bpf_freep); - fd = openat(parent_fd, fname, O_RDWR|O_CREAT|O_CLOEXEC, 0666); - assert_se(fd >= 0); -} - -static void test_fails_reg(int parent_fd, const char *fname) { - errno = 0; - assert_se(openat(parent_fd, fname, O_RDWR|O_CREAT|O_CLOEXEC, 0666) < 0); - assert_se(errno == EPERM); -} +static int intro(void) { + int r; -static void test_works_dir(int parent_fd, const char *fname) { - assert_se(mkdirat(parent_fd, fname, 0666) >= 0); -} + r = userns_restrict_install(/* pin= */ false, &bpf_obj); + if (ERRNO_IS_NOT_SUPPORTED(r)) + return log_tests_skipped("LSM-BPF logic not supported"); + if (ERRNO_IS_PRIVILEGE(r)) + return log_tests_skipped("Lacking privileges"); + ASSERT_OK(r); -static void test_fails_dir(int parent_fd, const char *fname) { - errno = 0; - assert_se(mkdirat(parent_fd, fname, 0666) < 0); - assert_se(errno == EPERM); + return 0; } -static int run(int argc, char *argv[]) { - _cleanup_(userns_restrict_bpf_freep) struct userns_restrict_bpf *obj = NULL; +TEST(userns_restrict) { _cleanup_close_ int userns_fd = -EBADF, host_fd1 = -EBADF, host_tmpfs = -EBADF, afd = -EBADF, bfd = -EBADF; _cleanup_(rm_rf_physical_and_freep) char *t = NULL; _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; - log_set_max_level(LOG_DEBUG); - log_setup(); - - r = userns_restrict_install(/* pin= */ false, &obj); - if (ERRNO_IS_NOT_SUPPORTED(r)) { - log_notice("Skipping test, LSM-BPF logic not supported."); - return EXIT_TEST_SKIP; - } - if (ERRNO_IS_PRIVILEGE(r)) { - log_notice("Skipping test, lacking privileges."); - return EXIT_TEST_SKIP; - } - if (r < 0) - return r; - - assert_se(mkdtemp_malloc(NULL, &t) >= 0); - - host_fd1 = open(t, O_DIRECTORY|O_CLOEXEC); - assert_se(host_fd1 >= 0); - - host_tmpfs = make_tmpfs_fsmount(); - assert_se(host_tmpfs >= 0); + ASSERT_OK(mkdtemp_malloc(NULL, &t)); - userns_fd = userns_acquire("0 0 1", "0 0 1", /* setgroups_deny= */ true); - if (userns_fd < 0) - return log_error_errno(userns_fd, "Failed to make user namespace: %m"); + host_fd1 = ASSERT_OK_ERRNO(open(t, O_DIRECTORY|O_CLOEXEC)); + host_tmpfs = ASSERT_OK(make_tmpfs_fsmount()); + userns_fd = ASSERT_OK(userns_acquire("0 0 1", "0 0 1", /* setgroups_deny= */ true)); - r = userns_restrict_put_by_fd( - obj, + ASSERT_OK(userns_restrict_put_by_fd( + bpf_obj, userns_fd, /* replace= */ true, /* mount_fds= */ NULL, - /* n_mount_fds= */ 0); - if (r < 0) - return log_error_errno(r, "Failed to restrict user namespace: %m"); + /* n_mount_fds= */ 0)); - afd = eventfd(0, EFD_CLOEXEC); - bfd = eventfd(0, EFD_CLOEXEC); + afd = ASSERT_OK_ERRNO(eventfd(0, EFD_CLOEXEC)); + bfd = ASSERT_OK_ERRNO(eventfd(0, EFD_CLOEXEC)); - assert_se(afd >= 0 && bfd >= 0); - - r = pidref_safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pidref); - assert_se(r >= 0); + r = ASSERT_OK(pidref_safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pidref)); if (r == 0) { _cleanup_close_ int private_tmpfs = -EBADF; - assert_se(setns(userns_fd, CLONE_NEWUSER) >= 0); - assert_se(unshare(CLONE_NEWNS) >= 0); + ASSERT_OK_ERRNO(setns(userns_fd, CLONE_NEWUSER)); + ASSERT_OK_ERRNO(unshare(CLONE_NEWNS)); /* Allocate tmpfs locally */ private_tmpfs = make_tmpfs_fsmount(); /* These two host mounts should be inaccessible */ - test_fails_reg(host_fd1, "test"); - test_fails_reg(host_tmpfs, "xxx"); - test_fails_dir(host_fd1, "test2"); - test_fails_dir(host_tmpfs, "xxx2"); + ASSERT_ERROR_ERRNO(openat(host_fd1, "test", O_RDWR|O_CREAT|O_CLOEXEC, 0666), EPERM); + ASSERT_ERROR_ERRNO(openat(host_tmpfs, "xxx", O_RDWR|O_CREAT|O_CLOEXEC, 0666), EPERM); + ASSERT_ERROR_ERRNO(mkdirat(host_fd1, "test2", 0666), EPERM); + ASSERT_ERROR_ERRNO(mkdirat(host_tmpfs, "xxx2", 0666), EPERM); /* But this mount created locally should be fine */ - test_works_reg(private_tmpfs, "yyy"); - test_works_dir(private_tmpfs, "yyy2"); + safe_close(ASSERT_OK_ERRNO(openat(private_tmpfs, "yyy", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + ASSERT_OK_ERRNO(mkdirat(private_tmpfs, "yyy2", 0666)); /* Let's sync with the parent, so that it allowlists more stuff for us */ - assert_se(eventfd_write(afd, 1) >= 0); + ASSERT_OK_ERRNO(eventfd_write(afd, 1)); uint64_t x; - assert_se(eventfd_read(bfd, &x) >= 0); + ASSERT_OK_ERRNO(eventfd_read(bfd, &x)); /* And now we should also have access to the host tmpfs */ - test_works_reg(host_tmpfs, "zzz"); - test_works_reg(private_tmpfs, "aaa"); - test_works_dir(host_tmpfs, "zzz2"); - test_works_dir(private_tmpfs, "aaa2"); + safe_close(ASSERT_OK_ERRNO(openat(host_tmpfs, "zzz", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + safe_close(ASSERT_OK_ERRNO(openat(private_tmpfs, "aaa", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + ASSERT_OK_ERRNO(mkdirat(host_tmpfs, "zzz2", 0666)); + ASSERT_OK_ERRNO(mkdirat(private_tmpfs, "aaa2", 0666)); /* But this one should still fail */ - test_fails_reg(host_fd1, "bbb"); - test_fails_dir(host_fd1, "bbb2"); + ASSERT_ERROR_ERRNO(openat(host_fd1, "bbb", O_RDWR|O_CREAT|O_CLOEXEC, 0666), EPERM); + ASSERT_ERROR_ERRNO(mkdirat(host_fd1, "bbb2", 0666), EPERM); /* Sync again, to get more stuff allowlisted */ - assert_se(eventfd_write(afd, 1) >= 0); - assert_se(eventfd_read(bfd, &x) >= 0); + ASSERT_OK_ERRNO(eventfd_write(afd, 1)); + ASSERT_OK_ERRNO(eventfd_read(bfd, &x)); /* Everything should now be allowed */ - test_works_reg(host_tmpfs, "ccc"); - test_works_reg(host_fd1, "ddd"); - test_works_reg(private_tmpfs, "eee"); - test_works_dir(host_tmpfs, "ccc2"); - test_works_reg(host_fd1, "ddd2"); - test_works_dir(private_tmpfs, "eee2"); + safe_close(ASSERT_OK_ERRNO(openat(host_tmpfs, "ccc", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + safe_close(ASSERT_OK_ERRNO(openat(host_fd1, "ddd", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + safe_close(ASSERT_OK_ERRNO(openat(private_tmpfs, "eee", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + ASSERT_OK_ERRNO(mkdirat(host_tmpfs, "ccc2", 0666)); + safe_close(ASSERT_OK_ERRNO(openat(host_fd1, "ddd2", O_RDWR|O_CREAT|O_CLOEXEC, 0666))); + ASSERT_OK_ERRNO(mkdirat(private_tmpfs, "eee2", 0666)); _exit(EXIT_SUCCESS); } uint64_t x; - assert_se(eventfd_read(afd, &x) >= 0); + ASSERT_OK_ERRNO(eventfd_read(afd, &x)); - r = userns_restrict_put_by_fd( - obj, + ASSERT_OK(userns_restrict_put_by_fd( + bpf_obj, userns_fd, /* replace= */ false, &host_tmpfs, - 1); - if (r < 0) - return log_error_errno(r, "Failed to loosen user namespace: %m"); - - assert_se(eventfd_write(bfd, 1) >= 0); + 1)); - assert_se(eventfd_read(afd, &x) >= 0); + ASSERT_OK_ERRNO(eventfd_write(bfd, 1)); + ASSERT_OK_ERRNO(eventfd_read(afd, &x)); - r = userns_restrict_put_by_fd( - obj, + ASSERT_OK(userns_restrict_put_by_fd( + bpf_obj, userns_fd, /* replace= */ false, &host_fd1, - 1); - if (r < 0) - return log_error_errno(r, "Failed to loosen user namespace: %m"); + 1)); - assert_se(eventfd_write(bfd, 1) >= 0); + ASSERT_OK_ERRNO(eventfd_write(bfd, 1)); - assert_se(pidref_wait_for_terminate_and_check("(test)", &pidref, WAIT_LOG) >= 0); - - return 0; + ASSERT_OK(pidref_wait_for_terminate_and_check("(test)", &pidref, WAIT_LOG)); } -DEFINE_MAIN_FUNCTION(run); +DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro); -- 2.47.3