1 /*
2 * Check decoding of fanotify_mark syscall.
3 *
4 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
6 * Copyright (c) 2015-2023 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "tests.h"
13 #include "scno.h"
14
15 #if defined HAVE_SYS_FANOTIFY_H && defined HAVE_FANOTIFY_MARK
16
17 # include <limits.h>
18 # include <stdint.h>
19 # include <stdio.h>
20 # include <unistd.h>
21 # include <sys/fanotify.h>
22
23 # include "secontext.h"
24
25 # if XLAT_RAW
26 # define str_fan_mark_add "0x1"
27 # define str_fan_modify_ondir "0x40000002"
28 # define str_at_fdcwd "-100"
29 # elif XLAT_VERBOSE
30 # define str_fan_mark_add "0x1 /* FAN_MARK_ADD */"
31 # define str_fan_modify_ondir "0x40000002 /* FAN_MODIFY|FAN_ONDIR */"
32 # define str_at_fdcwd "-100 /* AT_FDCWD */"
33 # else
34 # define str_fan_mark_add "FAN_MARK_ADD"
35 # define str_fan_modify_ondir "FAN_MODIFY|FAN_ONDIR"
36 # define str_at_fdcwd "AT_FDCWD"
37 # endif
38
39 # ifndef TEST_SECONTEXT
40 /* Performs fanotify_mark call via the syscall interface. */
41 static void
42 do_call(kernel_ulong_t fd, kernel_ulong_t flags, const char *flags_str,
43 uint64_t mask, const char *mask_str, kernel_ulong_t dirfd,
44 const char *dirfd_str, kernel_ulong_t path, const char *path_str)
45 {
46 long rc;
47
48 rc = syscall(__NR_fanotify_mark, fd, flags,
49 # if (LONG_MAX > INT_MAX) \
50 || (defined __x86_64__ && defined __ILP32__) \
51 || defined LINUX_MIPSN32
52 mask,
53 # else
54 LL_VAL_TO_PAIR(mask),
55 # endif
56 dirfd, path);
57
58 printf("fanotify_mark(%d, %s, %s, %s, %s) = %s\n",
59 (int) fd, flags_str, mask_str, dirfd_str, path_str,
60 sprintrc(rc));
61 }
62
63 struct strval {
64 kernel_ulong_t val;
65 const char *str;
66 };
67
68 # define STR16 "0123456789abcdef"
69 # define STR64 STR16 STR16 STR16 STR16
70 # endif /* !TEST_SECONTEXT */
71
72 int
73 main(void)
74 {
75 # ifndef TEST_SECONTEXT
76 enum {
77 PATH1_SIZE = 64,
78 };
79
80 static const kernel_ulong_t fds[] = {
81 (kernel_ulong_t) 0xdeadfeed12345678ULL,
82 F8ILL_KULONG_MASK,
83 (kernel_ulong_t) 0xdeb0d1edffffffffULL,
84 };
85 static const struct strval flags[] = {
86 { F8ILL_KULONG_MASK, "0" },
87 { (kernel_ulong_t) 0xdec0deddeface800ULL,
88 "0xeface800"
89 # if !XLAT_RAW
90 " /* FAN_MARK_??? */"
91 # endif
92 },
93 { (kernel_ulong_t) 0xda7a105700000040ULL,
94 # if XLAT_RAW
95 "0x40"
96 # elif XLAT_VERBOSE
97 "0x40 /* FAN_MARK_IGNORED_SURV_MODIFY */"
98 # else
99 "FAN_MARK_IGNORED_SURV_MODIFY"
100 # endif
101 },
102 { (kernel_ulong_t) 0xbadc0deddeadffffULL,
103 # if XLAT_RAW || XLAT_VERBOSE
104 "0xdeadffff"
105 # endif
106 # if XLAT_VERBOSE
107 " /* "
108 # endif
109 # if !XLAT_RAW
110 "FAN_MARK_ADD|FAN_MARK_REMOVE|FAN_MARK_DONT_FOLLOW|"
111 "FAN_MARK_ONLYDIR|FAN_MARK_MOUNT|FAN_MARK_IGNORED_MASK|"
112 "FAN_MARK_IGNORED_SURV_MODIFY|FAN_MARK_FLUSH|"
113 "FAN_MARK_FILESYSTEM|FAN_MARK_EVICTABLE|"
114 "FAN_MARK_IGNORE|0xdeadf800"
115 # endif
116 # if XLAT_VERBOSE
117 " */"
118 # endif
119 },
120 };
121 static const struct strval64 masks[] = {
122 { ARG_ULL_STR(0) },
123 { 0xdeadfeedffffffffULL,
124 # if XLAT_RAW || XLAT_VERBOSE
125 "0xdeadfeedffffffff"
126 # endif
127 # if XLAT_VERBOSE
128 " /* "
129 # endif
130 # if !XLAT_RAW
131 "FAN_ACCESS|"
132 "FAN_MODIFY|"
133 "FAN_ATTRIB|"
134 "FAN_CLOSE_WRITE|"
135 "FAN_CLOSE_NOWRITE|"
136 "FAN_OPEN|"
137 "FAN_MOVED_FROM|"
138 "FAN_MOVED_TO|"
139 "FAN_CREATE|"
140 "FAN_DELETE|"
141 "FAN_DELETE_SELF|"
142 "FAN_MOVE_SELF|"
143 "FAN_OPEN_EXEC|"
144 "FAN_Q_OVERFLOW|"
145 "FAN_FS_ERROR|"
146 "FAN_OPEN_PERM|"
147 "FAN_ACCESS_PERM|"
148 "FAN_OPEN_EXEC_PERM|"
149 "FAN_DIR_MODIFY|"
150 "FAN_ONDIR|"
151 "FAN_EVENT_ON_CHILD|"
152 "FAN_RENAME|"
153 "0xdeadfeeda7f02000"
154 # endif
155 # if XLAT_VERBOSE
156 " */"
157 # endif
158 },
159 { ARG_ULL_STR(0xffffffffa7f02000)
160 # if !XLAT_RAW
161 " /* FAN_??? */"
162 # endif
163 },
164 };
165 static const struct strval dirfds[] = {
166 { (kernel_ulong_t) 0xfacefeed00000001ULL, "1" },
167 { (kernel_ulong_t) 0xdec0ded0ffffffffULL,
168 # if XLAT_RAW
169 "-1"
170 # elif XLAT_VERBOSE
171 "-1 /* FAN_NOFD */"
172 # else
173 "FAN_NOFD"
174 # endif
175 },
176 { (kernel_ulong_t) 0xbadfacedffffff9cULL, str_at_fdcwd },
177 { (kernel_ulong_t) 0xdefaced1beeff00dULL, "-1091571699" },
178 };
179 static const char str64[] = STR64;
180
181 static char bogus_path1_addr[sizeof("0x") + sizeof(void *) * 2];
182 static char bogus_path1_after_addr[sizeof("0x") + sizeof(void *) * 2];
183
184 char *bogus_path1 = tail_memdup(str64, PATH1_SIZE);
185 char *bogus_path2 = tail_memdup(str64, sizeof(str64));
186
187 struct strval paths[] = {
188 { (kernel_ulong_t) 0, "NULL" },
189 { (kernel_ulong_t) (uintptr_t) (bogus_path1 + PATH1_SIZE),
190 bogus_path1_after_addr },
191 { (kernel_ulong_t) (uintptr_t) bogus_path1, bogus_path1_addr },
192 { (kernel_ulong_t) (uintptr_t) bogus_path2, "\"" STR64 "\"" },
193 };
194
195 snprintf(bogus_path1_addr, sizeof(bogus_path1_addr), "%p", bogus_path1);
196 snprintf(bogus_path1_after_addr, sizeof(bogus_path1_after_addr), "%p",
197 bogus_path1 + PATH1_SIZE);
198
199 for (unsigned int i = 0;
200 i < ARRAY_SIZE(fds); ++i) {
201 for (unsigned int j = 0;
202 j < ARRAY_SIZE(flags); ++j) {
203 for (unsigned int k = 0;
204 k < ARRAY_SIZE(masks); ++k) {
205 for (unsigned int l = 0;
206 l < ARRAY_SIZE(dirfds); ++l) {
207 for (unsigned int m = 0;
208 m < ARRAY_SIZE(paths); ++m)
209 do_call(fds[i],
210 flags[j].val,
211 flags[j].str,
212 masks[k].val,
213 masks[k].str,
214 dirfds[l].val,
215 dirfds[l].str,
216 paths[m].val,
217 paths[m].str);
218 }
219 }
220 }
221 }
222 # endif
223 /*
224 * Test with AT_FDCWD.
225 */
226
227 char *my_secontext = SECONTEXT_PID_MY();
228 char path[] = ".";
229 char *path_secontext = SECONTEXT_FILE(path);
230
231 int rc = fanotify_mark(-1, FAN_MARK_ADD, FAN_MODIFY | FAN_ONDIR,
232 -100, path);
233 printf("%s%s(-1, %s, %s, %s, \"%s\"%s) = %s\n",
234 my_secontext, "fanotify_mark",
235 str_fan_mark_add, str_fan_modify_ondir, str_at_fdcwd,
236 path, path_secontext,
237 sprintrc(rc));
238
239 /*
240 * Test with dirfd.
241 */
242
243 int cwd_fd = get_dir_fd(".");
244 char *cwd_secontext = SECONTEXT_FILE(".");
245
246 rc = fanotify_mark(-1, FAN_MARK_ADD, FAN_MODIFY | FAN_ONDIR,
247 cwd_fd, path);
248 printf("%s%s(-1, %s, %s, %d%s, \"%s\"%s) = %s\n",
249 my_secontext, "fanotify_mark",
250 str_fan_mark_add, str_fan_modify_ondir,
251 cwd_fd, cwd_secontext,
252 path, path_secontext,
253 sprintrc(rc));
254
255 puts("+++ exited with 0 +++");
256 return 0;
257 }
258
259 #else
260
261 SKIP_MAIN_UNDEFINED("HAVE_SYS_FANOTIFY_H && HAVE_FANOTIFY_MARK")
262
263 #endif