Re: [LTP] [PATCH STAGING v2 09/16] fchroot06: test path walks under failfs root
Cyril Hrubis <[email protected]>
| Newsgroups | it.linux.lists.ltp |
|---|---|
| Message-ID | <[email protected]> |
Hi! > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (C) 2026 SUSE LLC Andrea Cervesato <[email protected]> > + */ > + > +/*\ > + * Test path walks under the failfs root. > + * > + * Once :manpage:`fchroot(2)` moved the process root into failfs, only > + * lookups anchored at a file descriptor keep working: > + * > + * - lookups relative to the working directory, which stays in the real > + * filesystem, keep working > + * - lookups anchored at a pre-opened directory fd keep working, including > + * resolution of relative symlinks > + * - absolute symlinks restart the walk at the failfs root and fail with > + * ``EOPNOTSUPP`` > + * - ".." walks clamp at the top of the mount tree, not at the failfs > + * root, so walking up from the working directory lands on the real > + * root > + * > + * Root is required because entering failfs with the ``FD_FAILFS_ROOT`` > + * sentinel requires ``CAP_SYS_CHROOT``. > + * > + * The test runs in a forked child so the root of the parent process is > + * left untouched. > + */ > + > +#define _GNU_SOURCE > +#include <fcntl.h> > +#include <sys/stat.h> > +#include "tst_test.h" > +#include "lapi/fcntl.h" > +#include "lapi/syscalls.h" > +#include "tst_safe_file_at.h" > + > +#define RELDIR "rel" > +#define ABSDIR "abs" > + > +static char upwards[PATH_MAX]; > + > +static void run(void) > +{ > + if (SAFE_FORK()) > + return; > + > + struct stat realroot, st; > + int dfd, fd; > + > + SAFE_STAT("/", &realroot); > + dfd = SAFE_OPEN(".", O_RDONLY | O_DIRECTORY); > + > + TST_EXP_PASS(tst_syscall(__NR_fchroot, FD_FAILFS_ROOT, 0), > + "fchroot() with the FD_FAILFS_ROOT sentinel"); > + > + fd = SAFE_OPENAT(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY); > + SAFE_CLOSE(fd); This is a test right? So it should be TST_EXP_FD(openat(...)); > + fd = SAFE_OPENAT(dfd, "canary", O_WRONLY | O_CREAT, 0600); > + SAFE_WRITE(SAFE_WRITE_ALL, fd, "x", 1); > + SAFE_CLOSE(fd); > + > + fd = SAFE_OPENAT(dfd, RELDIR, O_RDONLY); > + SAFE_CLOSE(fd); These as well. > + TST_EXP_FAIL2(openat(dfd, ABSDIR, O_RDONLY), EOPNOTSUPP, > + "resolution of an absolute symlink"); > + > + fd = SAFE_OPENAT(AT_FDCWD, upwards, O_PATH); > + SAFE_FSTAT(fd, &st); > + SAFE_CLOSE(fd); And here. > + TST_EXP_EXPR(st.st_dev == realroot.st_dev && > + st.st_ino == realroot.st_ino, > + "'..' walk clamps at the top of the mount tree"); > + > + SAFE_CLOSE(dfd); > + > + exit(0); > +} > + > +static void setup(void) > +{ > + char *tmpdir; > + char abs_path[PATH_MAX]; > + struct stat root_st, st; > + int fd, off; > + > + tmpdir = tst_tmpdir_path(); > + snprintf(abs_path, sizeof(abs_path), "%s/%s", tmpdir, "target"); > + > + SAFE_TOUCH("target", 0644, NULL); > + SAFE_SYMLINK("target", RELDIR); > + SAFE_SYMLINK(abs_path, ABSDIR); > + > + SAFE_STAT("/", &root_st); > + > + off = snprintf(upwards, sizeof(upwards), ".."); > + while (1) { > + fd = SAFE_OPENAT(AT_FDCWD, upwards, O_PATH); > + SAFE_FSTAT(fd, &st); > + SAFE_CLOSE(fd); > + > + if (st.st_dev == root_st.st_dev && st.st_ino == root_st.st_ino) > + break; > + > + off += snprintf(upwards + off, sizeof(upwards) - off, "/.."); > + } > +} > + > +static struct tst_test test = { > + .setup = setup, > + .test_all = run, > + .needs_root = 1, > + .needs_tmpdir = 1, > + .forks_child = 1, > +}; > > -- > 2.51.0 > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp -- Cyril Hrubis [email protected] -- Mailing list info: https://lists.linux.it/listinfo/ltp