1 | /* SPDX-License-Identifier: GPL-2.0 */ |
---|---|
2 | #include <linux/fsnotify_backend.h> |
3 | #include <linux/path.h> |
4 | #include <linux/slab.h> |
5 | #include <linux/exportfs.h> |
6 | #include <linux/hashtable.h> |
7 | |
8 | extern struct kmem_cache *fanotify_mark_cache; |
9 | extern struct kmem_cache *fanotify_fid_event_cachep; |
10 | extern struct kmem_cache *fanotify_path_event_cachep; |
11 | extern struct kmem_cache *fanotify_perm_event_cachep; |
12 | extern struct kmem_cache *fanotify_mnt_event_cachep; |
13 | |
14 | /* Possible states of the permission event */ |
15 | enum { |
16 | FAN_EVENT_INIT, |
17 | FAN_EVENT_REPORTED, |
18 | FAN_EVENT_ANSWERED, |
19 | FAN_EVENT_CANCELED, |
20 | }; |
21 | |
22 | /* |
23 | * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation). |
24 | * fh buf should be dword aligned. On 64bit arch, the ext_buf pointer is |
25 | * stored in either the first or last 2 dwords. |
26 | */ |
27 | #define FANOTIFY_INLINE_FH_LEN (3 << 2) |
28 | #define FANOTIFY_FH_HDR_LEN sizeof(struct fanotify_fh) |
29 | |
30 | /* Fixed size struct for file handle */ |
31 | struct fanotify_fh { |
32 | u8 type; |
33 | u8 len; |
34 | #define FANOTIFY_FH_FLAG_EXT_BUF 1 |
35 | u8 flags; |
36 | u8 pad; |
37 | } __aligned(4); |
38 | |
39 | /* Variable size struct for dir file handle + child file handle + name */ |
40 | struct fanotify_info { |
41 | /* size of dir_fh/file_fh including fanotify_fh hdr size */ |
42 | u8 dir_fh_totlen; |
43 | u8 dir2_fh_totlen; |
44 | u8 file_fh_totlen; |
45 | u8 name_len; |
46 | u8 name2_len; |
47 | u8 pad[3]; |
48 | unsigned char buf[]; |
49 | /* |
50 | * (struct fanotify_fh) dir_fh starts at buf[0] |
51 | * (optional) dir2_fh starts at buf[dir_fh_totlen] |
52 | * (optional) file_fh starts at buf[dir_fh_totlen + dir2_fh_totlen] |
53 | * name starts at buf[dir_fh_totlen + dir2_fh_totlen + file_fh_totlen] |
54 | * ... |
55 | */ |
56 | #define FANOTIFY_DIR_FH_SIZE(info) ((info)->dir_fh_totlen) |
57 | #define FANOTIFY_DIR2_FH_SIZE(info) ((info)->dir2_fh_totlen) |
58 | #define FANOTIFY_FILE_FH_SIZE(info) ((info)->file_fh_totlen) |
59 | #define FANOTIFY_NAME_SIZE(info) ((info)->name_len + 1) |
60 | #define FANOTIFY_NAME2_SIZE(info) ((info)->name2_len + 1) |
61 | |
62 | #define FANOTIFY_DIR_FH_OFFSET(info) 0 |
63 | #define FANOTIFY_DIR2_FH_OFFSET(info) \ |
64 | (FANOTIFY_DIR_FH_OFFSET(info) + FANOTIFY_DIR_FH_SIZE(info)) |
65 | #define FANOTIFY_FILE_FH_OFFSET(info) \ |
66 | (FANOTIFY_DIR2_FH_OFFSET(info) + FANOTIFY_DIR2_FH_SIZE(info)) |
67 | #define FANOTIFY_NAME_OFFSET(info) \ |
68 | (FANOTIFY_FILE_FH_OFFSET(info) + FANOTIFY_FILE_FH_SIZE(info)) |
69 | #define FANOTIFY_NAME2_OFFSET(info) \ |
70 | (FANOTIFY_NAME_OFFSET(info) + FANOTIFY_NAME_SIZE(info)) |
71 | |
72 | #define FANOTIFY_DIR_FH_BUF(info) \ |
73 | ((info)->buf + FANOTIFY_DIR_FH_OFFSET(info)) |
74 | #define FANOTIFY_DIR2_FH_BUF(info) \ |
75 | ((info)->buf + FANOTIFY_DIR2_FH_OFFSET(info)) |
76 | #define FANOTIFY_FILE_FH_BUF(info) \ |
77 | ((info)->buf + FANOTIFY_FILE_FH_OFFSET(info)) |
78 | #define FANOTIFY_NAME_BUF(info) \ |
79 | ((info)->buf + FANOTIFY_NAME_OFFSET(info)) |
80 | #define FANOTIFY_NAME2_BUF(info) \ |
81 | ((info)->buf + FANOTIFY_NAME2_OFFSET(info)) |
82 | } __aligned(4); |
83 | |
84 | static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) |
85 | { |
86 | return (fh->flags & FANOTIFY_FH_FLAG_EXT_BUF); |
87 | } |
88 | |
89 | static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh) |
90 | { |
91 | BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN % 4); |
92 | BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) > |
93 | FANOTIFY_INLINE_FH_LEN); |
94 | return (char **)ALIGN((unsigned long)(fh + 1), __alignof__(char *)); |
95 | } |
96 | |
97 | static inline void *fanotify_fh_ext_buf(struct fanotify_fh *fh) |
98 | { |
99 | return *fanotify_fh_ext_buf_ptr(fh); |
100 | } |
101 | |
102 | static inline void *fanotify_fh_buf(struct fanotify_fh *fh) |
103 | { |
104 | return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh + 1; |
105 | } |
106 | |
107 | static inline int fanotify_info_dir_fh_len(struct fanotify_info *info) |
108 | { |
109 | if (!info->dir_fh_totlen || |
110 | WARN_ON_ONCE(info->dir_fh_totlen < FANOTIFY_FH_HDR_LEN)) |
111 | return 0; |
112 | |
113 | return info->dir_fh_totlen - FANOTIFY_FH_HDR_LEN; |
114 | } |
115 | |
116 | static inline struct fanotify_fh *fanotify_info_dir_fh(struct fanotify_info *info) |
117 | { |
118 | BUILD_BUG_ON(offsetof(struct fanotify_info, buf) % 4); |
119 | |
120 | return (struct fanotify_fh *)FANOTIFY_DIR_FH_BUF(info); |
121 | } |
122 | |
123 | static inline int fanotify_info_dir2_fh_len(struct fanotify_info *info) |
124 | { |
125 | if (!info->dir2_fh_totlen || |
126 | WARN_ON_ONCE(info->dir2_fh_totlen < FANOTIFY_FH_HDR_LEN)) |
127 | return 0; |
128 | |
129 | return info->dir2_fh_totlen - FANOTIFY_FH_HDR_LEN; |
130 | } |
131 | |
132 | static inline struct fanotify_fh *fanotify_info_dir2_fh(struct fanotify_info *info) |
133 | { |
134 | return (struct fanotify_fh *)FANOTIFY_DIR2_FH_BUF(info); |
135 | } |
136 | |
137 | static inline int fanotify_info_file_fh_len(struct fanotify_info *info) |
138 | { |
139 | if (!info->file_fh_totlen || |
140 | WARN_ON_ONCE(info->file_fh_totlen < FANOTIFY_FH_HDR_LEN)) |
141 | return 0; |
142 | |
143 | return info->file_fh_totlen - FANOTIFY_FH_HDR_LEN; |
144 | } |
145 | |
146 | static inline struct fanotify_fh *fanotify_info_file_fh(struct fanotify_info *info) |
147 | { |
148 | return (struct fanotify_fh *)FANOTIFY_FILE_FH_BUF(info); |
149 | } |
150 | |
151 | static inline char *fanotify_info_name(struct fanotify_info *info) |
152 | { |
153 | if (!info->name_len) |
154 | return NULL; |
155 | |
156 | return FANOTIFY_NAME_BUF(info); |
157 | } |
158 | |
159 | static inline char *fanotify_info_name2(struct fanotify_info *info) |
160 | { |
161 | if (!info->name2_len) |
162 | return NULL; |
163 | |
164 | return FANOTIFY_NAME2_BUF(info); |
165 | } |
166 | |
167 | static inline void fanotify_info_init(struct fanotify_info *info) |
168 | { |
169 | BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN + MAX_HANDLE_SZ > U8_MAX); |
170 | BUILD_BUG_ON(NAME_MAX > U8_MAX); |
171 | |
172 | info->dir_fh_totlen = 0; |
173 | info->dir2_fh_totlen = 0; |
174 | info->file_fh_totlen = 0; |
175 | info->name_len = 0; |
176 | info->name2_len = 0; |
177 | } |
178 | |
179 | /* These set/copy helpers MUST be called by order */ |
180 | static inline void fanotify_info_set_dir_fh(struct fanotify_info *info, |
181 | unsigned int totlen) |
182 | { |
183 | if (WARN_ON_ONCE(info->dir2_fh_totlen > 0) || |
184 | WARN_ON_ONCE(info->file_fh_totlen > 0) || |
185 | WARN_ON_ONCE(info->name_len > 0) || |
186 | WARN_ON_ONCE(info->name2_len > 0)) |
187 | return; |
188 | |
189 | info->dir_fh_totlen = totlen; |
190 | } |
191 | |
192 | static inline void fanotify_info_set_dir2_fh(struct fanotify_info *info, |
193 | unsigned int totlen) |
194 | { |
195 | if (WARN_ON_ONCE(info->file_fh_totlen > 0) || |
196 | WARN_ON_ONCE(info->name_len > 0) || |
197 | WARN_ON_ONCE(info->name2_len > 0)) |
198 | return; |
199 | |
200 | info->dir2_fh_totlen = totlen; |
201 | } |
202 | |
203 | static inline void fanotify_info_set_file_fh(struct fanotify_info *info, |
204 | unsigned int totlen) |
205 | { |
206 | if (WARN_ON_ONCE(info->name_len > 0) || |
207 | WARN_ON_ONCE(info->name2_len > 0)) |
208 | return; |
209 | |
210 | info->file_fh_totlen = totlen; |
211 | } |
212 | |
213 | static inline void fanotify_info_copy_name(struct fanotify_info *info, |
214 | const struct qstr *name) |
215 | { |
216 | if (WARN_ON_ONCE(name->len > NAME_MAX) || |
217 | WARN_ON_ONCE(info->name2_len > 0)) |
218 | return; |
219 | |
220 | info->name_len = name->len; |
221 | strcpy(p: fanotify_info_name(info), q: name->name); |
222 | } |
223 | |
224 | static inline void fanotify_info_copy_name2(struct fanotify_info *info, |
225 | const struct qstr *name) |
226 | { |
227 | if (WARN_ON_ONCE(name->len > NAME_MAX)) |
228 | return; |
229 | |
230 | info->name2_len = name->len; |
231 | strcpy(p: fanotify_info_name2(info), q: name->name); |
232 | } |
233 | |
234 | /* |
235 | * Common structure for fanotify events. Concrete structs are allocated in |
236 | * fanotify_handle_event() and freed when the information is retrieved by |
237 | * userspace. The type of event determines how it was allocated, how it will |
238 | * be freed and which concrete struct it may be cast to. |
239 | */ |
240 | enum fanotify_event_type { |
241 | FANOTIFY_EVENT_TYPE_FID, /* fixed length */ |
242 | FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */ |
243 | FANOTIFY_EVENT_TYPE_PATH, |
244 | FANOTIFY_EVENT_TYPE_PATH_PERM, |
245 | FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */ |
246 | FANOTIFY_EVENT_TYPE_FS_ERROR, /* struct fanotify_error_event */ |
247 | FANOTIFY_EVENT_TYPE_MNT, |
248 | __FANOTIFY_EVENT_TYPE_NUM |
249 | }; |
250 | |
251 | #define FANOTIFY_EVENT_TYPE_BITS \ |
252 | (ilog2(__FANOTIFY_EVENT_TYPE_NUM - 1) + 1) |
253 | #define FANOTIFY_EVENT_HASH_BITS \ |
254 | (32 - FANOTIFY_EVENT_TYPE_BITS) |
255 | |
256 | struct fanotify_event { |
257 | struct fsnotify_event fse; |
258 | struct hlist_node merge_list; /* List for hashed merge */ |
259 | u32 mask; |
260 | struct { |
261 | unsigned int type : FANOTIFY_EVENT_TYPE_BITS; |
262 | unsigned int hash : FANOTIFY_EVENT_HASH_BITS; |
263 | }; |
264 | struct pid *pid; |
265 | }; |
266 | |
267 | static inline void fanotify_init_event(struct fanotify_event *event, |
268 | unsigned int hash, u32 mask) |
269 | { |
270 | fsnotify_init_event(event: &event->fse); |
271 | INIT_HLIST_NODE(h: &event->merge_list); |
272 | event->hash = hash; |
273 | event->mask = mask; |
274 | event->pid = NULL; |
275 | } |
276 | |
277 | #define FANOTIFY_INLINE_FH(name, size) \ |
278 | struct { \ |
279 | struct fanotify_fh name; \ |
280 | /* Space for filehandle - access with fanotify_fh_buf() */ \ |
281 | unsigned char _inline_fh_buf[size]; \ |
282 | } |
283 | |
284 | struct fanotify_fid_event { |
285 | struct fanotify_event fae; |
286 | __kernel_fsid_t fsid; |
287 | |
288 | FANOTIFY_INLINE_FH(object_fh, FANOTIFY_INLINE_FH_LEN); |
289 | }; |
290 | |
291 | static inline struct fanotify_fid_event * |
292 | FANOTIFY_FE(struct fanotify_event *event) |
293 | { |
294 | return container_of(event, struct fanotify_fid_event, fae); |
295 | } |
296 | |
297 | struct fanotify_name_event { |
298 | struct fanotify_event fae; |
299 | __kernel_fsid_t fsid; |
300 | struct fanotify_info info; |
301 | }; |
302 | |
303 | static inline struct fanotify_name_event * |
304 | FANOTIFY_NE(struct fanotify_event *event) |
305 | { |
306 | return container_of(event, struct fanotify_name_event, fae); |
307 | } |
308 | |
309 | struct fanotify_error_event { |
310 | struct fanotify_event fae; |
311 | s32 error; /* Error reported by the Filesystem. */ |
312 | u32 err_count; /* Suppressed errors count */ |
313 | |
314 | __kernel_fsid_t fsid; /* FSID this error refers to. */ |
315 | |
316 | FANOTIFY_INLINE_FH(object_fh, MAX_HANDLE_SZ); |
317 | }; |
318 | |
319 | static inline struct fanotify_error_event * |
320 | FANOTIFY_EE(struct fanotify_event *event) |
321 | { |
322 | return container_of(event, struct fanotify_error_event, fae); |
323 | } |
324 | |
325 | static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event) |
326 | { |
327 | if (event->type == FANOTIFY_EVENT_TYPE_FID) |
328 | return &FANOTIFY_FE(event)->fsid; |
329 | else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) |
330 | return &FANOTIFY_NE(event)->fsid; |
331 | else if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) |
332 | return &FANOTIFY_EE(event)->fsid; |
333 | else |
334 | return NULL; |
335 | } |
336 | |
337 | static inline struct fanotify_fh *fanotify_event_object_fh( |
338 | struct fanotify_event *event) |
339 | { |
340 | if (event->type == FANOTIFY_EVENT_TYPE_FID) |
341 | return &FANOTIFY_FE(event)->object_fh; |
342 | else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) |
343 | return fanotify_info_file_fh(info: &FANOTIFY_NE(event)->info); |
344 | else if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) |
345 | return &FANOTIFY_EE(event)->object_fh; |
346 | else |
347 | return NULL; |
348 | } |
349 | |
350 | static inline struct fanotify_info *fanotify_event_info( |
351 | struct fanotify_event *event) |
352 | { |
353 | if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) |
354 | return &FANOTIFY_NE(event)->info; |
355 | else |
356 | return NULL; |
357 | } |
358 | |
359 | static inline int fanotify_event_object_fh_len(struct fanotify_event *event) |
360 | { |
361 | struct fanotify_info *info = fanotify_event_info(event); |
362 | struct fanotify_fh *fh = fanotify_event_object_fh(event); |
363 | |
364 | if (info) |
365 | return info->file_fh_totlen ? fh->len : 0; |
366 | else |
367 | return fh ? fh->len : 0; |
368 | } |
369 | |
370 | static inline int fanotify_event_dir_fh_len(struct fanotify_event *event) |
371 | { |
372 | struct fanotify_info *info = fanotify_event_info(event); |
373 | |
374 | return info ? fanotify_info_dir_fh_len(info) : 0; |
375 | } |
376 | |
377 | static inline int fanotify_event_dir2_fh_len(struct fanotify_event *event) |
378 | { |
379 | struct fanotify_info *info = fanotify_event_info(event); |
380 | |
381 | return info ? fanotify_info_dir2_fh_len(info) : 0; |
382 | } |
383 | |
384 | static inline bool fanotify_event_has_object_fh(struct fanotify_event *event) |
385 | { |
386 | /* For error events, even zeroed fh are reported. */ |
387 | if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) |
388 | return true; |
389 | return fanotify_event_object_fh_len(event) > 0; |
390 | } |
391 | |
392 | static inline bool fanotify_event_has_dir_fh(struct fanotify_event *event) |
393 | { |
394 | return fanotify_event_dir_fh_len(event) > 0; |
395 | } |
396 | |
397 | static inline bool fanotify_event_has_dir2_fh(struct fanotify_event *event) |
398 | { |
399 | return fanotify_event_dir2_fh_len(event) > 0; |
400 | } |
401 | |
402 | static inline bool fanotify_event_has_any_dir_fh(struct fanotify_event *event) |
403 | { |
404 | return fanotify_event_has_dir_fh(event) || |
405 | fanotify_event_has_dir2_fh(event); |
406 | } |
407 | |
408 | struct fanotify_path_event { |
409 | struct fanotify_event fae; |
410 | struct path path; |
411 | }; |
412 | |
413 | struct fanotify_mnt_event { |
414 | struct fanotify_event fae; |
415 | u64 mnt_id; |
416 | }; |
417 | |
418 | static inline struct fanotify_path_event * |
419 | FANOTIFY_PE(struct fanotify_event *event) |
420 | { |
421 | return container_of(event, struct fanotify_path_event, fae); |
422 | } |
423 | |
424 | static inline struct fanotify_mnt_event * |
425 | FANOTIFY_ME(struct fanotify_event *event) |
426 | { |
427 | return container_of(event, struct fanotify_mnt_event, fae); |
428 | } |
429 | |
430 | /* |
431 | * Structure for permission fanotify events. It gets allocated and freed in |
432 | * fanotify_handle_event() since we wait there for user response. When the |
433 | * information is retrieved by userspace the structure is moved from |
434 | * group->notification_list to group->fanotify_data.access_list to wait for |
435 | * user response. |
436 | */ |
437 | struct fanotify_perm_event { |
438 | struct fanotify_event fae; |
439 | struct path path; |
440 | const loff_t *ppos; /* optional file range info */ |
441 | size_t count; |
442 | u32 response; /* userspace answer to the event */ |
443 | unsigned short state; /* state of the event */ |
444 | int fd; /* fd we passed to userspace for this event */ |
445 | union { |
446 | struct fanotify_response_info_header hdr; |
447 | struct fanotify_response_info_audit_rule audit_rule; |
448 | }; |
449 | }; |
450 | |
451 | static inline struct fanotify_perm_event * |
452 | FANOTIFY_PERM(struct fanotify_event *event) |
453 | { |
454 | return container_of(event, struct fanotify_perm_event, fae); |
455 | } |
456 | |
457 | static inline bool fanotify_is_perm_event(u32 mask) |
458 | { |
459 | return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) && |
460 | mask & FANOTIFY_PERM_EVENTS; |
461 | } |
462 | |
463 | static inline bool fanotify_event_has_access_range(struct fanotify_event *event) |
464 | { |
465 | if (!(event->mask & FANOTIFY_PRE_CONTENT_EVENTS)) |
466 | return false; |
467 | |
468 | return FANOTIFY_PERM(event)->ppos; |
469 | } |
470 | |
471 | static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) |
472 | { |
473 | return container_of(fse, struct fanotify_event, fse); |
474 | } |
475 | |
476 | static inline bool fanotify_is_error_event(u32 mask) |
477 | { |
478 | return mask & FAN_FS_ERROR; |
479 | } |
480 | |
481 | static inline bool fanotify_is_mnt_event(u32 mask) |
482 | { |
483 | return mask & (FAN_MNT_ATTACH | FAN_MNT_DETACH); |
484 | } |
485 | |
486 | static inline const struct path *fanotify_event_path(struct fanotify_event *event) |
487 | { |
488 | if (event->type == FANOTIFY_EVENT_TYPE_PATH) |
489 | return &FANOTIFY_PE(event)->path; |
490 | else if (event->type == FANOTIFY_EVENT_TYPE_PATH_PERM) |
491 | return &FANOTIFY_PERM(event)->path; |
492 | else |
493 | return NULL; |
494 | } |
495 | |
496 | /* |
497 | * Use 128 size hash table to speed up events merge. |
498 | */ |
499 | #define FANOTIFY_HTABLE_BITS (7) |
500 | #define FANOTIFY_HTABLE_SIZE (1 << FANOTIFY_HTABLE_BITS) |
501 | #define FANOTIFY_HTABLE_MASK (FANOTIFY_HTABLE_SIZE - 1) |
502 | |
503 | /* |
504 | * Permission events and overflow event do not get merged - don't hash them. |
505 | */ |
506 | static inline bool fanotify_is_hashed_event(u32 mask) |
507 | { |
508 | return !(fanotify_is_perm_event(mask) || |
509 | fsnotify_is_overflow_event(mask)); |
510 | } |
511 | |
512 | static inline unsigned int fanotify_event_hash_bucket( |
513 | struct fsnotify_group *group, |
514 | struct fanotify_event *event) |
515 | { |
516 | return event->hash & FANOTIFY_HTABLE_MASK; |
517 | } |
518 | |
519 | struct fanotify_mark { |
520 | struct fsnotify_mark fsn_mark; |
521 | __kernel_fsid_t fsid; |
522 | }; |
523 | |
524 | static inline struct fanotify_mark *FANOTIFY_MARK(struct fsnotify_mark *mark) |
525 | { |
526 | return container_of(mark, struct fanotify_mark, fsn_mark); |
527 | } |
528 | |
529 | static inline bool fanotify_fsid_equal(__kernel_fsid_t *fsid1, |
530 | __kernel_fsid_t *fsid2) |
531 | { |
532 | return fsid1->val[0] == fsid2->val[0] && fsid1->val[1] == fsid2->val[1]; |
533 | } |
534 | |
535 | static inline unsigned int fanotify_mark_user_flags(struct fsnotify_mark *mark) |
536 | { |
537 | unsigned int mflags = 0; |
538 | |
539 | if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) |
540 | mflags |= FAN_MARK_IGNORED_SURV_MODIFY; |
541 | if (mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF) |
542 | mflags |= FAN_MARK_EVICTABLE; |
543 | if (mark->flags & FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS) |
544 | mflags |= FAN_MARK_IGNORE; |
545 | |
546 | return mflags; |
547 | } |
548 | |
549 | static inline u32 fanotify_get_response_errno(int res) |
550 | { |
551 | return (res >> FAN_ERRNO_SHIFT) & FAN_ERRNO_MASK; |
552 | } |
553 |
Definitions
- fanotify_fh
- fanotify_info
- fanotify_fh_has_ext_buf
- fanotify_fh_ext_buf_ptr
- fanotify_fh_ext_buf
- fanotify_fh_buf
- fanotify_info_dir_fh_len
- fanotify_info_dir_fh
- fanotify_info_dir2_fh_len
- fanotify_info_dir2_fh
- fanotify_info_file_fh_len
- fanotify_info_file_fh
- fanotify_info_name
- fanotify_info_name2
- fanotify_info_init
- fanotify_info_set_dir_fh
- fanotify_info_set_dir2_fh
- fanotify_info_set_file_fh
- fanotify_info_copy_name
- fanotify_info_copy_name2
- fanotify_event_type
- fanotify_event
- fanotify_init_event
- fanotify_fid_event
- FANOTIFY_FE
- fanotify_name_event
- FANOTIFY_NE
- fanotify_error_event
- FANOTIFY_EE
- fanotify_event_fsid
- fanotify_event_object_fh
- fanotify_event_info
- fanotify_event_object_fh_len
- fanotify_event_dir_fh_len
- fanotify_event_dir2_fh_len
- fanotify_event_has_object_fh
- fanotify_event_has_dir_fh
- fanotify_event_has_dir2_fh
- fanotify_event_has_any_dir_fh
- fanotify_path_event
- fanotify_mnt_event
- FANOTIFY_PE
- FANOTIFY_ME
- fanotify_perm_event
- FANOTIFY_PERM
- fanotify_is_perm_event
- fanotify_event_has_access_range
- FANOTIFY_E
- fanotify_is_error_event
- fanotify_is_mnt_event
- fanotify_event_path
- fanotify_is_hashed_event
- fanotify_event_hash_bucket
- fanotify_mark
- FANOTIFY_MARK
- fanotify_fsid_equal
- fanotify_mark_user_flags
Improve your Profiling and Debugging skills
Find out more