Path: blob/master/tools/testing/selftests/filesystems/fuse/fusectl_test.c
29271 views
// SPDX-License-Identifier: GPL-2.0-or-later1// Copyright (c) 2025 Chen Linxuan <[email protected]>23#define _GNU_SOURCE45#include <errno.h>6#include <fcntl.h>7#include <stdio.h>8#include <stdlib.h>9#include <string.h>10#include <sys/mount.h>11#include <sys/stat.h>12#include <sys/types.h>13#include <sys/wait.h>14#include <unistd.h>15#include <dirent.h>16#include <sched.h>17#include <linux/limits.h>1819#include "../../kselftest_harness.h"2021#define FUSECTL_MOUNTPOINT "/sys/fs/fuse/connections"22#define FUSE_MOUNTPOINT "/tmp/fuse_mnt_XXXXXX"23#define FUSE_DEVICE "/dev/fuse"24#define FUSECTL_TEST_VALUE "1"2526static void write_file(struct __test_metadata *const _metadata,27const char *path, const char *val)28{29int fd = open(path, O_WRONLY);30size_t len = strlen(val);3132ASSERT_GE(fd, 0);33ASSERT_EQ(write(fd, val, len), len);34ASSERT_EQ(close(fd), 0);35}3637FIXTURE(fusectl){38char fuse_mountpoint[sizeof(FUSE_MOUNTPOINT)];39int connection;40};4142FIXTURE_SETUP(fusectl)43{44const char *fuse_mnt_prog = "./fuse_mnt";45int status, pid;46struct stat statbuf;47uid_t uid = getuid();48gid_t gid = getgid();49char buf[32];5051/* Setup userns */52ASSERT_EQ(unshare(CLONE_NEWNS|CLONE_NEWUSER), 0);53sprintf(buf, "0 %d 1", uid);54write_file(_metadata, "/proc/self/uid_map", buf);55write_file(_metadata, "/proc/self/setgroups", "deny");56sprintf(buf, "0 %d 1", gid);57write_file(_metadata, "/proc/self/gid_map", buf);58ASSERT_EQ(mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL), 0);5960strcpy(self->fuse_mountpoint, FUSE_MOUNTPOINT);6162if (!mkdtemp(self->fuse_mountpoint))63SKIP(return,64"Failed to create FUSE mountpoint %s",65strerror(errno));6667if (access(FUSECTL_MOUNTPOINT, F_OK))68SKIP(return,69"FUSE control filesystem not mounted");7071pid = fork();72if (pid < 0)73SKIP(return,74"Failed to fork FUSE daemon process: %s",75strerror(errno));7677if (pid == 0) {78execlp(fuse_mnt_prog, fuse_mnt_prog, self->fuse_mountpoint, NULL);79exit(errno);80}8182waitpid(pid, &status, 0);83if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {84SKIP(return,85"Failed to start FUSE daemon %s",86strerror(WEXITSTATUS(status)));87}8889if (stat(self->fuse_mountpoint, &statbuf))90SKIP(return,91"Failed to stat FUSE mountpoint %s",92strerror(errno));9394self->connection = statbuf.st_dev;95}9697FIXTURE_TEARDOWN(fusectl)98{99umount2(self->fuse_mountpoint, MNT_DETACH);100rmdir(self->fuse_mountpoint);101}102103TEST_F(fusectl, abort)104{105char path_buf[PATH_MAX];106int abort_fd, test_fd, ret;107108sprintf(path_buf, "/sys/fs/fuse/connections/%d/abort", self->connection);109110ASSERT_EQ(0, access(path_buf, F_OK));111112abort_fd = open(path_buf, O_WRONLY);113ASSERT_GE(abort_fd, 0);114115sprintf(path_buf, "%s/test", self->fuse_mountpoint);116117test_fd = open(path_buf, O_RDWR);118ASSERT_GE(test_fd, 0);119120ret = read(test_fd, path_buf, sizeof(path_buf));121ASSERT_EQ(ret, 0);122123ret = write(test_fd, "test", sizeof("test"));124ASSERT_EQ(ret, sizeof("test"));125126ret = lseek(test_fd, 0, SEEK_SET);127ASSERT_GE(ret, 0);128129ret = write(abort_fd, FUSECTL_TEST_VALUE, sizeof(FUSECTL_TEST_VALUE));130ASSERT_GT(ret, 0);131132close(abort_fd);133134ret = read(test_fd, path_buf, sizeof(path_buf));135ASSERT_EQ(ret, -1);136ASSERT_EQ(errno, ENOTCONN);137}138139TEST_HARNESS_MAIN140141142