[PATCH STAGING v2 08/16] fchroot05: test failfs root can not be referenced
Andrea Cervesato <[email protected]>
| Newsgroups | gmane.linux.ltp |
|---|---|
| Message-ID | <[email protected]> |
From: Andrea Cervesato <andrea.cervesato-IBi9RG/[email protected]> Verify that once fchroot() moved the root into failfs, the root directory can not be opened anymore, not even with O_PATH, nor pinned by following the /proc/self/root magic link, although readlink() still names it as "failfs:/" since it does not follow the link. Signed-off-by: Andrea Cervesato <andrea.cervesato-IBi9RG/[email protected]> --- runtest/staging | 1 + testcases/kernel/syscalls/fchroot/.gitignore | 1 + testcases/kernel/syscalls/fchroot/fchroot05.c | 75 +++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/runtest/staging b/runtest/staging index 91dfdba08..49f51d637 100644 --- a/runtest/staging +++ b/runtest/staging @@ -4,3 +4,4 @@ fchroot01 fchroot01 fchroot02 fchroot02 fchroot03 fchroot03 fchroot04 fchroot04 +fchroot05 fchroot05 diff --git a/testcases/kernel/syscalls/fchroot/.gitignore b/testcases/kernel/syscalls/fchroot/.gitignore index 9270c1408..0697f10eb 100644 --- a/testcases/kernel/syscalls/fchroot/.gitignore +++ b/testcases/kernel/syscalls/fchroot/.gitignore @@ -2,3 +2,4 @@ fchroot01 fchroot02 fchroot03 fchroot04 +fchroot05 diff --git a/testcases/kernel/syscalls/fchroot/fchroot05.c b/testcases/kernel/syscalls/fchroot/fchroot05.c new file mode 100644 index 000000000..f183d749c --- /dev/null +++ b/testcases/kernel/syscalls/fchroot/fchroot05.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato-IBi9RG/[email protected]> + */ + +/*\ + * Test that the failfs root can not be referenced once it is the process + * root. + * + * After :manpage:`fchroot(2)` moved the root into failfs, the root + * directory can not be opened anymore, not even with ``O_PATH``, because the + * walk lands on the failfs root as its terminal. The root also can not + * be pinned by following the /proc/self/root magic link into it, although + * :manpage:`readlink(2)` still names it as "failfs:/" since it does not + * follow the link. + * + * Root is required because entering failfs with the ``FD_FAILFS_ROOT`` + * sentinel requires ``CAP_SYS_CHROOT``. + * + * /proc must be opened before entering failfs because every absolute path + * lookup fails once the root is unreachable. The test runs in a forked + * child so the root of the parent process is left untouched. + */ + +#define _GNU_SOURCE +#include <fcntl.h> +#include <limits.h> +#include <sys/stat.h> +#include <unistd.h> +#include "tst_test.h" +#include "lapi/fcntl.h" +#include "lapi/syscalls.h" + +static void run(void) +{ + if (SAFE_FORK()) + return; + + char buf[PATH_MAX]; + struct stat st; + int procfd, len; + + procfd = SAFE_OPEN("/proc", O_PATH | O_DIRECTORY); + + TST_EXP_PASS(tst_syscall(__NR_fchroot, FD_FAILFS_ROOT, 0), + "fchroot() with the FD_FAILFS_ROOT sentinel"); + + TST_EXP_FAIL2(open("/", O_RDONLY | O_DIRECTORY), EOPNOTSUPP, + "open() of the failfs root"); + + TST_EXP_FAIL2(open("/", O_PATH), EOPNOTSUPP, + "O_PATH open() of the failfs root"); + + TST_EXP_FAIL2(openat(procfd, "self/root", O_PATH), EOPNOTSUPP, + "pin of the root via /proc/self/root"); + + TST_EXP_FAIL(fstatat(procfd, "self/root", &st, 0), EOPNOTSUPP, + "stat of the root via /proc/self/root"); + + len = readlinkat(procfd, "self/root", buf, sizeof(buf) - 1); + if (len < 0) { + tst_res(TFAIL | TTERRNO, "readlinkat() of /proc/self/root"); + } else { + buf[len] = '\0'; + TST_EXP_EQ_STR(buf, "failfs:/"); + } + + exit(0); +} + +static struct tst_test test = { + .test_all = run, + .needs_root = 1, + .forks_child = 1, +}; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp