Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/filesystems/fuse/fusectl_test.c
29271 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
// Copyright (c) 2025 Chen Linxuan <[email protected]>
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
27
static 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
38
FIXTURE(fusectl){
39
char fuse_mountpoint[sizeof(FUSE_MOUNTPOINT)];
40
int connection;
41
};
42
43
FIXTURE_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
98
FIXTURE_TEARDOWN(fusectl)
99
{
100
umount2(self->fuse_mountpoint, MNT_DETACH);
101
rmdir(self->fuse_mountpoint);
102
}
103
104
TEST_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
140
TEST_HARNESS_MAIN
141
142