fusectl_test.c 3.2 KB

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