10static int flags_and_paths(
void) {
11 int failed = 0, group = -1, accepted = -1, memory = -1, ram = -1;
12 struct fh_file file = {.fd = -1};
14 char symlink_path[224] = {0}, ram_path[192] = {0};
16 CHECK(!fh_create(&file));
18 CHECK(fanotify_init(FAN_REPORT_FID | 0x80000000U, O_RDONLY) == -1 && errno == EINVAL);
20 CHECK(fanotify_init(FAN_REPORT_FID | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT, O_RDONLY) == -1 &&
23 CHECK(fanotify_init(0, O_RDONLY) == -1 && errno == EOPNOTSUPP);
25 CHECK(fanotify_init(FAN_REPORT_FID | FAN_CLASS_CONTENT, O_RDONLY) == -1 && errno == EOPNOTSUPP);
27 CHECK(fanotify_init(FAN_REPORT_FID, O_ACCMODE) == -1 && errno == EINVAL);
29 CHECK(fanotify_init(FAN_REPORT_FID, 3) == -1 && errno == EINVAL);
31 CHECK(fanotify_init(FAN_REPORT_FID, O_PATH) == -1 && errno == EINVAL);
33 CHECK(fanotify_init(FAN_REPORT_FID, O_CREAT) == -1 && errno == EINVAL);
34 accepted = fanotify_init(FAN_REPORT_FID | FAN_NONBLOCK, O_RDWR | O_APPEND | O_NONBLOCK | O_SYNC |
35 O_DSYNC | O_CLOEXEC | O_LARGEFILE |
43 CHECK(fh_mark(group, &file, FAN_MARK_ADD | FAN_MARK_REMOVE, FAN_MODIFY) == -1 && errno == EINVAL);
45 CHECK(fh_mark(group, &file, FAN_MARK_ADD, FAN_OPEN_PERM) == -1 && errno == EINVAL);
47 CHECK(fh_mark(group, &file, FAN_MARK_ADD, 1ULL << 63) == -1 && errno == EINVAL);
49 CHECK(fh_mark(group, &file, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_MODIFY) == -1 &&
52 CHECK(fh_mark(group, &file, FAN_MARK_ADD | FAN_MARK_ONLYDIR, FAN_MODIFY) == -1 &&
55 CHECK(fanotify_mark(group, FAN_MARK_ADD, FAN_MODIFY, file.fd,
"") == -1 && errno == ENOENT);
56 CHECK(!fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY));
58 CHECK(fanotify_mark(group, FAN_MARK_FLUSH | FAN_MARK_DONT_FOLLOW, 0, -1, NULL) == -1 &&
61 CHECK(fanotify_mark(group, FAN_MARK_FLUSH | FAN_MARK_ONLYDIR, 0, -1, NULL) == -1 &&
63 CHECK(!fh_mark(group, &file, FAN_MARK_REMOVE, FAN_MODIFY));
64 CHECK(!fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY));
66 CHECK(fanotify_mark(group, FAN_MARK_ADD, FAN_MODIFY, AT_FDCWD, NULL) == -1 && errno == EBADF);
67 CHECK(!fanotify_mark(group, FAN_MARK_FLUSH, UINT64_MAX, -1, (
const char*)1));
68 snprintf(symlink_path,
sizeof(symlink_path),
"%s.link", file.path);
69 CHECK(!symlink(file.path, symlink_path));
70 handle.handle_bytes =
sizeof(handle.bytes);
72 CHECK(name_to_handle_at(AT_FDCWD, symlink_path, (
struct file_handle*)&handle, &mount_id, 0) ==
75 handle.handle_bytes =
sizeof(handle.bytes);
76 CHECK(!name_to_handle_at(AT_FDCWD, symlink_path, (
struct file_handle*)&handle, &mount_id,
78 CHECK(fh_equal(&handle, &file.handle));
80 CHECK(fanotify_mark(group, FAN_MARK_ADD | FAN_MARK_DONT_FOLLOW, FAN_MODIFY, AT_FDCWD,
81 symlink_path) == -1 &&
83 CHECK(!fanotify_mark(group, FAN_MARK_ADD, FAN_MODIFY, AT_FDCWD, symlink_path));
84 memory = memfd_create(
"fanotify-unsupported", MFD_CLOEXEC);
87 CHECK(fh_export(memory, &handle, &mount_id) == -1 && errno == EOPNOTSUPP);
89 CHECK(fanotify_mark(group, FAN_MARK_ADD, FAN_MODIFY, memory, NULL) == -1 && errno == EOPNOTSUPP);
90 snprintf(ram_path,
sizeof(ram_path),
"/tmp/fanotify-unsupported-%ld", (
long)getpid());
91 ram = open(ram_path, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600);
94 CHECK(fh_export(ram, &handle, &mount_id) == -1 && errno == EOPNOTSUPP);
96 CHECK(open_by_handle_at(file.fd, (
struct file_handle*)&file.handle, O_PATH) == -1 &&
99 CHECK(open_by_handle_at(-1, (
struct file_handle*)&file.handle, O_RDONLY) == -1 && errno == EBADF);
108 unlink(symlink_path);
117static int copies(
void) {
118 int failed = 0, mount_id;
119 struct fh_file file = {.fd = -1};
121 void* page = MAP_FAILED;
122 CHECK(!fh_create(&file));
123 page = mmap(NULL, fh_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
124 CHECK(page != MAP_FAILED);
125 handle = file.handle;
126 handle.handle_bytes = 129;
128 CHECK(name_to_handle_at(file.fd,
"", (
struct file_handle*)&handle, &mount_id, AT_EMPTY_PATH) ==
131 handle = file.handle;
133 CHECK(name_to_handle_at(file.fd,
"", (
struct file_handle*)&handle, &mount_id,
134 AT_EMPTY_PATH | 0x40000000) == -1 &&
136 handle.handle_bytes = 0;
138 CHECK(open_by_handle_at(file.fd, (
struct file_handle*)&handle, O_RDONLY) == -1 &&
140 CHECK(!mprotect(page, fh_page, PROT_NONE));
142 CHECK(name_to_handle_at(file.fd,
"", page, &mount_id, AT_EMPTY_PATH) == -1 && errno == EFAULT);
144 CHECK(open_by_handle_at(file.fd, page, O_RDONLY) == -1 && errno == EFAULT);
145 memset(&handle, 0x5a,
sizeof(handle));
146 handle.handle_bytes =
sizeof(handle.bytes);
149 CHECK(name_to_handle_at(file.fd,
"", (
struct file_handle*)&handle, page, AT_EMPTY_PATH) == -1 &&
151 CHECK(!memcmp(&handle, &saved,
sizeof(handle)));
152 CHECK(!mprotect(page, fh_page, PROT_READ | PROT_WRITE));
153 memcpy(page, &saved,
sizeof(saved));
154 CHECK(!mprotect(page, fh_page, PROT_READ));
157 CHECK(name_to_handle_at(file.fd,
"", page, &mount_id, AT_EMPTY_PATH) == -1 && errno == EFAULT);
158 CHECK(mount_id == file.mount_id && !memcmp(page, &saved,
sizeof(saved)));
160 if (page != MAP_FAILED)
161 munmap(page, fh_page);
166static int permissions(
void) {
167 int failed = 0, group = -1;
169 struct fh_file file = {.fd = -1};
170 CHECK(!fh_create(&file));
171 CHECK(!fchmod(file.fd, 0644));
180 if (setgroups(0, NULL) || setgid(65534) || setuid(65534))
183 if (fh_group(1) != -1 || errno != EPERM)
185 handle.handle_bytes =
sizeof(handle.bytes);
186 if (name_to_handle_at(AT_FDCWD, file.path, (
struct file_handle*)&handle, &mount_id, 0) ||
187 !fh_equal(&handle, &file.handle))
190 if (open_by_handle_at(file.fd, (
struct file_handle*)&handle, O_RDONLY) != -1 || errno != EPERM)
192 if (fanotify_mark(group, FAN_MARK_ADD, FAN_MODIFY, AT_FDCWD, file.path))
196 CHECK(!fh_reap(child, 12000));
198 CHECK(!fh_mark(group, &file, FAN_MARK_REMOVE, FAN_MODIFY));
199 CHECK(!fchmod(file.fd, 0600));
204 if (setgroups(0, NULL) || setgid(65534) || setuid(65534))
207 _exit(fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY) == -1 && errno == EACCES ? 0 : 21);
209 CHECK(!fh_reap(child, 12000));
219int fh_admission(
void) {
220 return flags_and_paths() || copies() || permissions();