File Index
Files and directories
Sign in
FILE

fusectl_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/filesystems/fuse/fusectl_test.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2// Copyright (c) 2025 Chen Linxuan <chenlinxuan@uniontech.com>
  3
  4#define _GNU_SOURCE
  5
  6#include <errno.h>
  7#include <fcntl.h>
  8#include <stdio.h>
  9#include <stdlib.h>
 10#include <string.h>
 11#include <sys/mount.h>
 12#include <sys/stat.h>
 13#include <sys/types.h>
 14#include <sys/wait.h>
 15#include <unistd.h>
 16#include <dirent.h>
 17#include <sched.h>
 18#include <linux/limits.h>
 19
 20#include "kselftest_harness.h"
 21
 22#define FUSECTL_MOUNTPOINT "/sys/fs/fuse/connections"
 23#define FUSE_MOUNTPOINT "/tmp/fuse_mnt_XXXXXX"
 24#define FUSE_DEVICE "/dev/fuse"
 25#define FUSECTL_TEST_VALUE "1"
 26
 27static void write_file(struct __test_metadata *const _metadata,
 28		       const char *path, const char *val)
 29{
 30	int fd = open(path, O_WRONLY);
 31	size_t len = strlen(val);
 32
 33	ASSERT_GE(fd, 0);
 34	ASSERT_EQ(write(fd, val, len), len);
 35	ASSERT_EQ(close(fd), 0);
 36}
 37
 38FIXTURE(fusectl){
 39	char fuse_mountpoint[sizeof(FUSE_MOUNTPOINT)];
 40	int connection;
 41};
 42
 43FIXTURE_SETUP(fusectl)
 44{
 45	const char *fuse_mnt_prog = "./fuse_mnt";
 46	int status, pid;
 47	struct stat statbuf;
 48	uid_t uid = getuid();
 49	gid_t gid = getgid();
 50	char buf[32];
 51
 52	/* Setup userns */
 53	ASSERT_EQ(unshare(CLONE_NEWNS|CLONE_NEWUSER), 0);
 54	sprintf(buf, "0 %d 1", uid);
 55	write_file(_metadata, "/proc/self/uid_map", buf);
 56	write_file(_metadata, "/proc/self/setgroups", "deny");
 57	sprintf(buf, "0 %d 1", gid);
 58	write_file(_metadata, "/proc/self/gid_map", buf);
 59	ASSERT_EQ(mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL), 0);
 60
 61	strcpy(self->fuse_mountpoint, FUSE_MOUNTPOINT);
 62
 63	if (!mkdtemp(self->fuse_mountpoint))
 64		SKIP(return,
 65		     "Failed to create FUSE mountpoint %s",
 66		     strerror(errno));
 67
 68	if (access(FUSECTL_MOUNTPOINT, F_OK))
 69		SKIP(return,
 70		     "FUSE control filesystem not mounted");
 71
 72	pid = fork();
 73	if (pid < 0)
 74		SKIP(return,
 75		     "Failed to fork FUSE daemon process: %s",
 76		     strerror(errno));
 77
 78	if (pid == 0) {
 79		execlp(fuse_mnt_prog, fuse_mnt_prog, self->fuse_mountpoint, NULL);
 80		exit(errno);
 81	}
 82
 83	waitpid(pid, &status, 0);
 84	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
 85		SKIP(return,
 86		     "Failed to start FUSE daemon %s",
 87		     strerror(WEXITSTATUS(status)));
 88	}
 89
 90	if (stat(self->fuse_mountpoint, &statbuf))
 91		SKIP(return,
 92		     "Failed to stat FUSE mountpoint %s",
 93		     strerror(errno));
 94
 95	self->connection = statbuf.st_dev;
 96}
 97
 98FIXTURE_TEARDOWN(fusectl)
 99{
100	umount2(self->fuse_mountpoint, MNT_DETACH);
101	rmdir(self->fuse_mountpoint);
102}
103
104TEST_F(fusectl, abort)
105{
106	char path_buf[PATH_MAX];
107	int abort_fd, test_fd, ret;
108
109	sprintf(path_buf, "/sys/fs/fuse/connections/%d/abort", self->connection);
110
111	ASSERT_EQ(0, access(path_buf, F_OK));
112
113	abort_fd = open(path_buf, O_WRONLY);
114	ASSERT_GE(abort_fd, 0);
115
116	sprintf(path_buf, "%s/test", self->fuse_mountpoint);
117
118	test_fd = open(path_buf, O_RDWR);
119	ASSERT_GE(test_fd, 0);
120
121	ret = read(test_fd, path_buf, sizeof(path_buf));
122	ASSERT_EQ(ret, 0);
123
124	ret = write(test_fd, "test", sizeof("test"));
125	ASSERT_EQ(ret, sizeof("test"));
126
127	ret = lseek(test_fd, 0, SEEK_SET);
128	ASSERT_GE(ret, 0);
129
130	ret = write(abort_fd, FUSECTL_TEST_VALUE, sizeof(FUSECTL_TEST_VALUE));
131	ASSERT_GT(ret, 0);
132
133	close(abort_fd);
134
135	ret = read(test_fd, path_buf, sizeof(path_buf));
136	ASSERT_EQ(ret, -1);
137	ASSERT_EQ(errno, ENOTCONN);
138}
139
140TEST_HARNESS_MAIN
~/ Read-only file preview.