From: Andrei Vagin <avagin@xxxxxxxxx> Currently, a reconfigure call-back is implemented only for the proc file system. This test creates a new mount and pid namespace and then we can create a new proc mount instance and be sure that a host configuration will not be affected. Signed-off-by: Andrei Vagin <avagin@xxxxxxxxx> --- tools/testing/selftests/fsopen/Makefile | 5 + tools/testing/selftests/fsopen/config | 2 + tools/testing/selftests/fsopen/fsopen.c | 120 ++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 tools/testing/selftests/fsopen/Makefile create mode 100644 tools/testing/selftests/fsopen/config create mode 100644 tools/testing/selftests/fsopen/fsopen.c diff --git a/tools/testing/selftests/fsopen/Makefile b/tools/testing/selftests/fsopen/Makefile new file mode 100644 index 000000000000..bfb1dd015e37 --- /dev/null +++ b/tools/testing/selftests/fsopen/Makefile @@ -0,0 +1,5 @@ +CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS) + +TEST_GEN_PROGS := fsopen + +include ../lib.mk diff --git a/tools/testing/selftests/fsopen/config b/tools/testing/selftests/fsopen/config new file mode 100644 index 000000000000..d2ced6498f5a --- /dev/null +++ b/tools/testing/selftests/fsopen/config @@ -0,0 +1,2 @@ +CONFIG_PROC_FS=y +CONFIG_PID_NS=y diff --git a/tools/testing/selftests/fsopen/fsopen.c b/tools/testing/selftests/fsopen/fsopen.c new file mode 100644 index 000000000000..c7cbfcda40ad --- /dev/null +++ b/tools/testing/selftests/fsopen/fsopen.c @@ -0,0 +1,120 @@ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include <unistd.h> +#include <stdio.h> +#include <unistd.h> +#include <sched.h> +#include <linux/fs.h> +#include <sys/syscall.h> +#include <sys/wait.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +static int sys_mount(char *dev_name, char *dir_name, char *type, + unsigned long flags, void *data) +{ + return syscall(__NR_mount, dev_name, dir_name, type, flags, data); +} + +static int sys_fsopen(const char *fs_name, unsigned int flags) +{ + return syscall(__NR_fsopen, fs_name, flags); +} + +static int sys_fsmount(int fsfd, unsigned int flags, unsigned int ms_flags) +{ + return syscall(__NR_fsmount, fsfd, flags, ms_flags); +} + +static int sys_fspick(unsigned int dirfd, const char *path, unsigned int flags) +{ + return syscall(__NR_fspick, dirfd, path, flags); +} + +static int sys_fsconfig(int fd, unsigned int cmd, const char *key, const char *value, int aux) +{ + return syscall(__NR_fsconfig, fd, cmd, key, value, aux); +} + +static int move_mount(int from_dfd, char *from_pathname, + int to_dfd, char *to_pathname, unsigned int flags) +{ + return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags); +} + +#define pr_err(fmt, ...) \ + ({ \ + fprintf(stderr, "%s:%d:" fmt ": %m\n", \ + __func__, __LINE__, ##__VA_ARGS__); \ + 1; \ + }) + +static const char dev[] = "s test_fsopen_123"; +//static const char opts[] = "rw"; +static int test() +{ + int fsfd, fsfd2, dfd; + + fsfd = sys_fsopen("proc", 0); + if (fsfd < 0) + return pr_err("sys_fsopen"); + + if (sys_fsconfig(fsfd, FSCONFIG_SET_STRING, "gid", "0", 0)) + return pr_err("sys_fsconfig sets gid=5"); + + if (sys_fsconfig(fsfd, FSCONFIG_SET_STRING, "source", dev, 0) < 0) + return pr_err("fsconfig_set_string sets source = %s", dev); + + if (sys_fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0) + return pr_err("fsconfig_cmd_create"); + + dfd = sys_fsmount(fsfd, 0, 0); + if (dfd < 0) + return pr_err("sys_fsmount"); + + if (move_mount(dfd, ".", AT_FDCWD, "/proc", 0)) + return pr_err("move_mount"); + + fsfd2 = sys_fspick(dfd, ".", 0); + if (fsfd2 < 0) + return pr_err("sys_fspick"); + + if (sys_fsconfig(fsfd2, FSCONFIG_SET_STRING, "gid", "5", 0)) + return pr_err("fsconfig_set_string sets gid=5"); + + if (sys_fsconfig(fsfd2, FSCONFIG_CMD_RECONFIGURE, NULL, NULL, 0)) + return pr_err("fsconfig_cmd_reconfigure"); + + if (close(dfd) < 0) + return pr_err("close(dfd)"); + if (close(fsfd) < 0) + return pr_err("close(fsfd)"); + if (close(fsfd2) < 0) + return pr_err("close(fsfd2)"); + + return 0; +} + +int main() +{ + pid_t pid; + int status; + + if (unshare(CLONE_NEWNS | CLONE_NEWPID)) + return pr_err("unshare"); + + if (sys_mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL)) + return pr_err("mount"); + + pid = fork(); + if (pid < 0) + return pr_err("fork"); + if (pid == 0) + return test(); + if (waitpid(pid, &status, 0) != pid) + return pr_err("waitpid"); + if (status) + return 1; + return 0; +} -- 2.17.1