1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker *
5*49cdfc7eSAndroid Build Coastguard Worker * Started by Matthew Bobrowski <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker */
7*49cdfc7eSAndroid Build Coastguard Worker
8*49cdfc7eSAndroid Build Coastguard Worker /*\
9*49cdfc7eSAndroid Build Coastguard Worker * [Description]
10*49cdfc7eSAndroid Build Coastguard Worker * Validate that the values returned within an event when FAN_REPORT_FID is
11*49cdfc7eSAndroid Build Coastguard Worker * specified matches those that are obtained via explicit invocation to system
12*49cdfc7eSAndroid Build Coastguard Worker * calls statfs(2) and name_to_handle_at(2).
13*49cdfc7eSAndroid Build Coastguard Worker */
14*49cdfc7eSAndroid Build Coastguard Worker
15*49cdfc7eSAndroid Build Coastguard Worker /*
16*49cdfc7eSAndroid Build Coastguard Worker * This is also regression test for:
17*49cdfc7eSAndroid Build Coastguard Worker * c285a2f01d69 ("fanotify: update connector fsid cache on add mark")
18*49cdfc7eSAndroid Build Coastguard Worker */
19*49cdfc7eSAndroid Build Coastguard Worker
20*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
21*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
22*49cdfc7eSAndroid Build Coastguard Worker
23*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <sys/statfs.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mount.h>
29*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
30*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_SYS_FANOTIFY_H
34*49cdfc7eSAndroid Build Coastguard Worker #include "fanotify.h"
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker #define PATH_LEN 128
37*49cdfc7eSAndroid Build Coastguard Worker #define BUF_SIZE 256
38*49cdfc7eSAndroid Build Coastguard Worker #define DIR_ONE "dir_one"
39*49cdfc7eSAndroid Build Coastguard Worker #define FILE_ONE "file_one"
40*49cdfc7eSAndroid Build Coastguard Worker #define FILE_TWO "file_two"
41*49cdfc7eSAndroid Build Coastguard Worker #define MOUNT_PATH "tstmnt"
42*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_MAX ARRAY_SIZE(objects)
43*49cdfc7eSAndroid Build Coastguard Worker #define DIR_PATH_ONE MOUNT_PATH"/"DIR_ONE
44*49cdfc7eSAndroid Build Coastguard Worker #define FILE_PATH_ONE MOUNT_PATH"/"FILE_ONE
45*49cdfc7eSAndroid Build Coastguard Worker #define FILE_PATH_TWO MOUNT_PATH"/"FILE_TWO
46*49cdfc7eSAndroid Build Coastguard Worker
47*49cdfc7eSAndroid Build Coastguard Worker #if defined(HAVE_NAME_TO_HANDLE_AT)
48*49cdfc7eSAndroid Build Coastguard Worker struct event_t {
49*49cdfc7eSAndroid Build Coastguard Worker unsigned long long expected_mask;
50*49cdfc7eSAndroid Build Coastguard Worker };
51*49cdfc7eSAndroid Build Coastguard Worker
52*49cdfc7eSAndroid Build Coastguard Worker static struct object_t {
53*49cdfc7eSAndroid Build Coastguard Worker const char *path;
54*49cdfc7eSAndroid Build Coastguard Worker int is_dir;
55*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_fid_t fid;
56*49cdfc7eSAndroid Build Coastguard Worker } objects[] = {
57*49cdfc7eSAndroid Build Coastguard Worker {FILE_PATH_ONE, 0, {}},
58*49cdfc7eSAndroid Build Coastguard Worker {FILE_PATH_TWO, 0, {}},
59*49cdfc7eSAndroid Build Coastguard Worker {DIR_PATH_ONE, 1, {}}
60*49cdfc7eSAndroid Build Coastguard Worker };
61*49cdfc7eSAndroid Build Coastguard Worker
62*49cdfc7eSAndroid Build Coastguard Worker static struct test_case_t {
63*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_mark_type mark;
64*49cdfc7eSAndroid Build Coastguard Worker unsigned long long mask;
65*49cdfc7eSAndroid Build Coastguard Worker } test_cases[] = {
66*49cdfc7eSAndroid Build Coastguard Worker {
67*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(INODE),
68*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE_NOWRITE
69*49cdfc7eSAndroid Build Coastguard Worker },
70*49cdfc7eSAndroid Build Coastguard Worker {
71*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(INODE),
72*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR
73*49cdfc7eSAndroid Build Coastguard Worker },
74*49cdfc7eSAndroid Build Coastguard Worker {
75*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(MOUNT),
76*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE_NOWRITE
77*49cdfc7eSAndroid Build Coastguard Worker },
78*49cdfc7eSAndroid Build Coastguard Worker {
79*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(MOUNT),
80*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR
81*49cdfc7eSAndroid Build Coastguard Worker },
82*49cdfc7eSAndroid Build Coastguard Worker {
83*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(FILESYSTEM),
84*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE_NOWRITE
85*49cdfc7eSAndroid Build Coastguard Worker },
86*49cdfc7eSAndroid Build Coastguard Worker {
87*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(FILESYSTEM),
88*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR
89*49cdfc7eSAndroid Build Coastguard Worker }
90*49cdfc7eSAndroid Build Coastguard Worker };
91*49cdfc7eSAndroid Build Coastguard Worker
92*49cdfc7eSAndroid Build Coastguard Worker static int ovl_mounted;
93*49cdfc7eSAndroid Build Coastguard Worker static int bind_mounted;
94*49cdfc7eSAndroid Build Coastguard Worker static int ovl_bind_mounted;
95*49cdfc7eSAndroid Build Coastguard Worker static int nofid_fd;
96*49cdfc7eSAndroid Build Coastguard Worker static int fanotify_fd;
97*49cdfc7eSAndroid Build Coastguard Worker static int at_handle_fid;
98*49cdfc7eSAndroid Build Coastguard Worker static int filesystem_mark_unsupported;
99*49cdfc7eSAndroid Build Coastguard Worker static char events_buf[BUF_SIZE];
100*49cdfc7eSAndroid Build Coastguard Worker static struct event_t event_set[EVENT_MAX];
101*49cdfc7eSAndroid Build Coastguard Worker
create_objects(void)102*49cdfc7eSAndroid Build Coastguard Worker static void create_objects(void)
103*49cdfc7eSAndroid Build Coastguard Worker {
104*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
105*49cdfc7eSAndroid Build Coastguard Worker
106*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(objects); i++) {
107*49cdfc7eSAndroid Build Coastguard Worker if (objects[i].is_dir)
108*49cdfc7eSAndroid Build Coastguard Worker SAFE_MKDIR(objects[i].path, 0755);
109*49cdfc7eSAndroid Build Coastguard Worker else
110*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(objects[i].path, "0");
111*49cdfc7eSAndroid Build Coastguard Worker }
112*49cdfc7eSAndroid Build Coastguard Worker }
113*49cdfc7eSAndroid Build Coastguard Worker
get_object_stats(void)114*49cdfc7eSAndroid Build Coastguard Worker static void get_object_stats(void)
115*49cdfc7eSAndroid Build Coastguard Worker {
116*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(objects); i++) {
119*49cdfc7eSAndroid Build Coastguard Worker at_handle_fid |=
120*49cdfc7eSAndroid Build Coastguard Worker fanotify_save_fid(objects[i].path, &objects[i].fid);
121*49cdfc7eSAndroid Build Coastguard Worker }
122*49cdfc7eSAndroid Build Coastguard Worker }
123*49cdfc7eSAndroid Build Coastguard Worker
setup_marks(unsigned int fd,struct test_case_t * tc)124*49cdfc7eSAndroid Build Coastguard Worker static int setup_marks(unsigned int fd, struct test_case_t *tc)
125*49cdfc7eSAndroid Build Coastguard Worker {
126*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
127*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_mark_type *mark = &tc->mark;
128*49cdfc7eSAndroid Build Coastguard Worker
129*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(objects); i++) {
130*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd, FAN_MARK_ADD | mark->flag, tc->mask,
131*49cdfc7eSAndroid Build Coastguard Worker AT_FDCWD, objects[i].path);
132*49cdfc7eSAndroid Build Coastguard Worker
133*49cdfc7eSAndroid Build Coastguard Worker /* Setup the expected mask for each generated event */
134*49cdfc7eSAndroid Build Coastguard Worker event_set[i].expected_mask = tc->mask;
135*49cdfc7eSAndroid Build Coastguard Worker if (!objects[i].is_dir)
136*49cdfc7eSAndroid Build Coastguard Worker event_set[i].expected_mask &= ~FAN_ONDIR;
137*49cdfc7eSAndroid Build Coastguard Worker }
138*49cdfc7eSAndroid Build Coastguard Worker return 0;
139*49cdfc7eSAndroid Build Coastguard Worker }
140*49cdfc7eSAndroid Build Coastguard Worker
do_test(unsigned int number)141*49cdfc7eSAndroid Build Coastguard Worker static void do_test(unsigned int number)
142*49cdfc7eSAndroid Build Coastguard Worker {
143*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
144*49cdfc7eSAndroid Build Coastguard Worker int len, fds[ARRAY_SIZE(objects)];
145*49cdfc7eSAndroid Build Coastguard Worker
146*49cdfc7eSAndroid Build Coastguard Worker struct file_handle *event_file_handle;
147*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_event_metadata *metadata;
148*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_event_info_fid *event_fid;
149*49cdfc7eSAndroid Build Coastguard Worker struct test_case_t *tc = &test_cases[number];
150*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_mark_type *mark = &tc->mark;
151*49cdfc7eSAndroid Build Coastguard Worker
152*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO,
153*49cdfc7eSAndroid Build Coastguard Worker "Test #%d.%d: FAN_REPORT_FID with mark flag: %s",
154*49cdfc7eSAndroid Build Coastguard Worker number, tst_variant, mark->name);
155*49cdfc7eSAndroid Build Coastguard Worker
156*49cdfc7eSAndroid Build Coastguard Worker if (tst_variant && !ovl_mounted) {
157*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "overlayfs not supported on %s", tst_device->fs_type);
158*49cdfc7eSAndroid Build Coastguard Worker return;
159*49cdfc7eSAndroid Build Coastguard Worker }
160*49cdfc7eSAndroid Build Coastguard Worker
161*49cdfc7eSAndroid Build Coastguard Worker if (filesystem_mark_unsupported && mark->flag != FAN_MARK_INODE) {
162*49cdfc7eSAndroid Build Coastguard Worker FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported);
163*49cdfc7eSAndroid Build Coastguard Worker return;
164*49cdfc7eSAndroid Build Coastguard Worker }
165*49cdfc7eSAndroid Build Coastguard Worker
166*49cdfc7eSAndroid Build Coastguard Worker fanotify_fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF | FAN_REPORT_FID, O_RDONLY);
167*49cdfc7eSAndroid Build Coastguard Worker
168*49cdfc7eSAndroid Build Coastguard Worker /*
169*49cdfc7eSAndroid Build Coastguard Worker * Place marks on a set of objects and setup the expected masks
170*49cdfc7eSAndroid Build Coastguard Worker * for each event that is expected to be generated.
171*49cdfc7eSAndroid Build Coastguard Worker */
172*49cdfc7eSAndroid Build Coastguard Worker if (setup_marks(fanotify_fd, tc) != 0)
173*49cdfc7eSAndroid Build Coastguard Worker goto out;
174*49cdfc7eSAndroid Build Coastguard Worker
175*49cdfc7eSAndroid Build Coastguard Worker /* Watching base fs - open files on overlayfs */
176*49cdfc7eSAndroid Build Coastguard Worker if (tst_variant && !ovl_bind_mounted) {
177*49cdfc7eSAndroid Build Coastguard Worker if (mark->flag & FAN_MARK_MOUNT) {
178*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "overlayfs base fs cannot be watched with mount mark");
179*49cdfc7eSAndroid Build Coastguard Worker goto out;
180*49cdfc7eSAndroid Build Coastguard Worker }
181*49cdfc7eSAndroid Build Coastguard Worker SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL);
182*49cdfc7eSAndroid Build Coastguard Worker }
183*49cdfc7eSAndroid Build Coastguard Worker
184*49cdfc7eSAndroid Build Coastguard Worker /* Generate sequence of FAN_OPEN events on objects */
185*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(objects); i++)
186*49cdfc7eSAndroid Build Coastguard Worker fds[i] = SAFE_OPEN(objects[i].path, O_RDONLY);
187*49cdfc7eSAndroid Build Coastguard Worker
188*49cdfc7eSAndroid Build Coastguard Worker /*
189*49cdfc7eSAndroid Build Coastguard Worker * Generate sequence of FAN_CLOSE_NOWRITE events on objects. Each
190*49cdfc7eSAndroid Build Coastguard Worker * FAN_CLOSE_NOWRITE event is expected to be merged with its
191*49cdfc7eSAndroid Build Coastguard Worker * respective FAN_OPEN event that was performed on the same object.
192*49cdfc7eSAndroid Build Coastguard Worker */
193*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(objects); i++) {
194*49cdfc7eSAndroid Build Coastguard Worker if (fds[i] > 0)
195*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fds[i]);
196*49cdfc7eSAndroid Build Coastguard Worker }
197*49cdfc7eSAndroid Build Coastguard Worker
198*49cdfc7eSAndroid Build Coastguard Worker if (tst_variant && !ovl_bind_mounted)
199*49cdfc7eSAndroid Build Coastguard Worker SAFE_UMOUNT(MOUNT_PATH);
200*49cdfc7eSAndroid Build Coastguard Worker
201*49cdfc7eSAndroid Build Coastguard Worker /* Read events from event queue */
202*49cdfc7eSAndroid Build Coastguard Worker len = SAFE_READ(0, fanotify_fd, events_buf, BUF_SIZE);
203*49cdfc7eSAndroid Build Coastguard Worker
204*49cdfc7eSAndroid Build Coastguard Worker /* Iterate over event queue */
205*49cdfc7eSAndroid Build Coastguard Worker for (i = 0, metadata = (struct fanotify_event_metadata *) events_buf;
206*49cdfc7eSAndroid Build Coastguard Worker FAN_EVENT_OK(metadata, len);
207*49cdfc7eSAndroid Build Coastguard Worker metadata = FAN_EVENT_NEXT(metadata, len), i++) {
208*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_fid_t *expected_fid = &objects[i].fid;
209*49cdfc7eSAndroid Build Coastguard Worker
210*49cdfc7eSAndroid Build Coastguard Worker event_fid = (struct fanotify_event_info_fid *) (metadata + 1);
211*49cdfc7eSAndroid Build Coastguard Worker event_file_handle = (struct file_handle *) event_fid->handle;
212*49cdfc7eSAndroid Build Coastguard Worker
213*49cdfc7eSAndroid Build Coastguard Worker /* File descriptor is redundant with FAN_REPORT_FID */
214*49cdfc7eSAndroid Build Coastguard Worker if (metadata->fd != FAN_NOFD)
215*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
216*49cdfc7eSAndroid Build Coastguard Worker "Unexpectedly received file descriptor %d in "
217*49cdfc7eSAndroid Build Coastguard Worker "event. Expected to get FAN_NOFD(%d)",
218*49cdfc7eSAndroid Build Coastguard Worker metadata->fd, FAN_NOFD);
219*49cdfc7eSAndroid Build Coastguard Worker
220*49cdfc7eSAndroid Build Coastguard Worker /* Ensure that the correct mask has been reported in event */
221*49cdfc7eSAndroid Build Coastguard Worker if (metadata->mask != event_set[i].expected_mask)
222*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
223*49cdfc7eSAndroid Build Coastguard Worker "Unexpected mask received: %llx (expected: "
224*49cdfc7eSAndroid Build Coastguard Worker "%llx) in event",
225*49cdfc7eSAndroid Build Coastguard Worker metadata->mask,
226*49cdfc7eSAndroid Build Coastguard Worker event_set[i].expected_mask);
227*49cdfc7eSAndroid Build Coastguard Worker
228*49cdfc7eSAndroid Build Coastguard Worker /* Verify handle_bytes returned in event */
229*49cdfc7eSAndroid Build Coastguard Worker if (event_file_handle->handle_bytes !=
230*49cdfc7eSAndroid Build Coastguard Worker expected_fid->handle.handle_bytes) {
231*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
232*49cdfc7eSAndroid Build Coastguard Worker "handle_bytes (%x) returned in event does not "
233*49cdfc7eSAndroid Build Coastguard Worker "equal to handle_bytes (%x) returned in "
234*49cdfc7eSAndroid Build Coastguard Worker "name_to_handle_at(2)",
235*49cdfc7eSAndroid Build Coastguard Worker event_file_handle->handle_bytes,
236*49cdfc7eSAndroid Build Coastguard Worker expected_fid->handle.handle_bytes);
237*49cdfc7eSAndroid Build Coastguard Worker continue;
238*49cdfc7eSAndroid Build Coastguard Worker }
239*49cdfc7eSAndroid Build Coastguard Worker
240*49cdfc7eSAndroid Build Coastguard Worker /* Verify handle_type returned in event */
241*49cdfc7eSAndroid Build Coastguard Worker if (event_file_handle->handle_type !=
242*49cdfc7eSAndroid Build Coastguard Worker expected_fid->handle.handle_type) {
243*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
244*49cdfc7eSAndroid Build Coastguard Worker "handle_type (%x) returned in event does not "
245*49cdfc7eSAndroid Build Coastguard Worker "equal to handle_type (%x) returned in "
246*49cdfc7eSAndroid Build Coastguard Worker "name_to_handle_at(2)",
247*49cdfc7eSAndroid Build Coastguard Worker event_file_handle->handle_type,
248*49cdfc7eSAndroid Build Coastguard Worker expected_fid->handle.handle_type);
249*49cdfc7eSAndroid Build Coastguard Worker continue;
250*49cdfc7eSAndroid Build Coastguard Worker }
251*49cdfc7eSAndroid Build Coastguard Worker
252*49cdfc7eSAndroid Build Coastguard Worker /* Verify file identifier f_handle returned in event */
253*49cdfc7eSAndroid Build Coastguard Worker if (memcmp(event_file_handle->f_handle,
254*49cdfc7eSAndroid Build Coastguard Worker expected_fid->handle.f_handle,
255*49cdfc7eSAndroid Build Coastguard Worker expected_fid->handle.handle_bytes) != 0) {
256*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
257*49cdfc7eSAndroid Build Coastguard Worker "file_handle returned in event does not match "
258*49cdfc7eSAndroid Build Coastguard Worker "the file_handle returned in "
259*49cdfc7eSAndroid Build Coastguard Worker "name_to_handle_at(2)");
260*49cdfc7eSAndroid Build Coastguard Worker continue;
261*49cdfc7eSAndroid Build Coastguard Worker }
262*49cdfc7eSAndroid Build Coastguard Worker
263*49cdfc7eSAndroid Build Coastguard Worker /* Verify filesystem ID fsid returned in event */
264*49cdfc7eSAndroid Build Coastguard Worker if (memcmp(&event_fid->fsid, &expected_fid->fsid,
265*49cdfc7eSAndroid Build Coastguard Worker sizeof(expected_fid->fsid)) != 0) {
266*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
267*49cdfc7eSAndroid Build Coastguard Worker "event_fid.fsid != stat.f_fsid that was "
268*49cdfc7eSAndroid Build Coastguard Worker "obtained via statfs(2)");
269*49cdfc7eSAndroid Build Coastguard Worker continue;
270*49cdfc7eSAndroid Build Coastguard Worker }
271*49cdfc7eSAndroid Build Coastguard Worker
272*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
273*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx, pid=%d, fid=%x.%x.%lx values "
274*49cdfc7eSAndroid Build Coastguard Worker "returned in event match those returned in statfs(2) "
275*49cdfc7eSAndroid Build Coastguard Worker "and name_to_handle_at(2)",
276*49cdfc7eSAndroid Build Coastguard Worker metadata->mask,
277*49cdfc7eSAndroid Build Coastguard Worker getpid(),
278*49cdfc7eSAndroid Build Coastguard Worker FSID_VAL_MEMBER(event_fid->fsid, 0),
279*49cdfc7eSAndroid Build Coastguard Worker FSID_VAL_MEMBER(event_fid->fsid, 1),
280*49cdfc7eSAndroid Build Coastguard Worker *(unsigned long *) event_file_handle->f_handle);
281*49cdfc7eSAndroid Build Coastguard Worker }
282*49cdfc7eSAndroid Build Coastguard Worker out:
283*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fanotify_fd);
284*49cdfc7eSAndroid Build Coastguard Worker }
285*49cdfc7eSAndroid Build Coastguard Worker
do_setup(void)286*49cdfc7eSAndroid Build Coastguard Worker static void do_setup(void)
287*49cdfc7eSAndroid Build Coastguard Worker {
288*49cdfc7eSAndroid Build Coastguard Worker const char *mnt;
289*49cdfc7eSAndroid Build Coastguard Worker
290*49cdfc7eSAndroid Build Coastguard Worker /*
291*49cdfc7eSAndroid Build Coastguard Worker * Bind mount to either base fs or to overlayfs over base fs:
292*49cdfc7eSAndroid Build Coastguard Worker * Variant #0: watch base fs - open files on base fs
293*49cdfc7eSAndroid Build Coastguard Worker * Variant #1: watch lower fs - open lower files on overlayfs
294*49cdfc7eSAndroid Build Coastguard Worker * Variant #2: watch upper fs - open upper files on overlayfs
295*49cdfc7eSAndroid Build Coastguard Worker * Variant #3: watch overlayfs - open lower files on overlayfs
296*49cdfc7eSAndroid Build Coastguard Worker * Variant #4: watch overlayfs - open upper files on overlayfs
297*49cdfc7eSAndroid Build Coastguard Worker *
298*49cdfc7eSAndroid Build Coastguard Worker * Variants 1,2 test a bug whose fix bc2473c90fca ("ovl: enable fsnotify
299*49cdfc7eSAndroid Build Coastguard Worker * events on underlying real files") in kernel 6.5 is not likely to be
300*49cdfc7eSAndroid Build Coastguard Worker * backported to older kernels.
301*49cdfc7eSAndroid Build Coastguard Worker * To avoid waiting for events that won't arrive when testing old kernels,
302*49cdfc7eSAndroid Build Coastguard Worker * require that kernel supports encoding fid with new flag AT_HANDLE_FID,
303*49cdfc7eSAndroid Build Coastguard Worker * also merged to 6.5 and not likely to be backported to older kernels.
304*49cdfc7eSAndroid Build Coastguard Worker * Variants 3,4 test overlayfs watch with FAN_REPORT_FID, which also
305*49cdfc7eSAndroid Build Coastguard Worker * requires kernel with support for AT_HANDLE_FID.
306*49cdfc7eSAndroid Build Coastguard Worker */
307*49cdfc7eSAndroid Build Coastguard Worker if (tst_variant) {
308*49cdfc7eSAndroid Build Coastguard Worker REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(AT_HANDLE_FID);
309*49cdfc7eSAndroid Build Coastguard Worker ovl_mounted = TST_MOUNT_OVERLAY();
310*49cdfc7eSAndroid Build Coastguard Worker if (!ovl_mounted)
311*49cdfc7eSAndroid Build Coastguard Worker return;
312*49cdfc7eSAndroid Build Coastguard Worker
313*49cdfc7eSAndroid Build Coastguard Worker mnt = tst_variant & 1 ? OVL_LOWER : OVL_UPPER;
314*49cdfc7eSAndroid Build Coastguard Worker } else {
315*49cdfc7eSAndroid Build Coastguard Worker mnt = OVL_BASE_MNTPOINT;
316*49cdfc7eSAndroid Build Coastguard Worker
317*49cdfc7eSAndroid Build Coastguard Worker }
318*49cdfc7eSAndroid Build Coastguard Worker REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, mnt);
319*49cdfc7eSAndroid Build Coastguard Worker SAFE_MKDIR(MOUNT_PATH, 0755);
320*49cdfc7eSAndroid Build Coastguard Worker SAFE_MOUNT(mnt, MOUNT_PATH, "none", MS_BIND, NULL);
321*49cdfc7eSAndroid Build Coastguard Worker bind_mounted = 1;
322*49cdfc7eSAndroid Build Coastguard Worker
323*49cdfc7eSAndroid Build Coastguard Worker nofid_fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
324*49cdfc7eSAndroid Build Coastguard Worker
325*49cdfc7eSAndroid Build Coastguard Worker /* Create file and directory objects for testing on base fs */
326*49cdfc7eSAndroid Build Coastguard Worker create_objects();
327*49cdfc7eSAndroid Build Coastguard Worker
328*49cdfc7eSAndroid Build Coastguard Worker if (tst_variant > 2) {
329*49cdfc7eSAndroid Build Coastguard Worker /* Setup watches on overlayfs */
330*49cdfc7eSAndroid Build Coastguard Worker SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL);
331*49cdfc7eSAndroid Build Coastguard Worker ovl_bind_mounted = 1;
332*49cdfc7eSAndroid Build Coastguard Worker }
333*49cdfc7eSAndroid Build Coastguard Worker
334*49cdfc7eSAndroid Build Coastguard Worker filesystem_mark_unsupported =
335*49cdfc7eSAndroid Build Coastguard Worker fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN,
336*49cdfc7eSAndroid Build Coastguard Worker ovl_bind_mounted ? OVL_MNT : MOUNT_PATH);
337*49cdfc7eSAndroid Build Coastguard Worker
338*49cdfc7eSAndroid Build Coastguard Worker /*
339*49cdfc7eSAndroid Build Coastguard Worker * Create a mark on first inode without FAN_REPORT_FID, to test
340*49cdfc7eSAndroid Build Coastguard Worker * uninitialized connector->fsid cache. This mark remains for all test
341*49cdfc7eSAndroid Build Coastguard Worker * cases and is not expected to get any events (no writes in this test).
342*49cdfc7eSAndroid Build Coastguard Worker */
343*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(nofid_fd, FAN_MARK_ADD, FAN_CLOSE_WRITE, AT_FDCWD,
344*49cdfc7eSAndroid Build Coastguard Worker FILE_PATH_ONE);
345*49cdfc7eSAndroid Build Coastguard Worker
346*49cdfc7eSAndroid Build Coastguard Worker /* Get the filesystem fsid and file handle for each created object */
347*49cdfc7eSAndroid Build Coastguard Worker get_object_stats();
348*49cdfc7eSAndroid Build Coastguard Worker }
349*49cdfc7eSAndroid Build Coastguard Worker
do_cleanup(void)350*49cdfc7eSAndroid Build Coastguard Worker static void do_cleanup(void)
351*49cdfc7eSAndroid Build Coastguard Worker {
352*49cdfc7eSAndroid Build Coastguard Worker if (nofid_fd > 0)
353*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(nofid_fd);
354*49cdfc7eSAndroid Build Coastguard Worker if (fanotify_fd > 0)
355*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fanotify_fd);
356*49cdfc7eSAndroid Build Coastguard Worker if (ovl_bind_mounted)
357*49cdfc7eSAndroid Build Coastguard Worker SAFE_UMOUNT(MOUNT_PATH);
358*49cdfc7eSAndroid Build Coastguard Worker if (bind_mounted) {
359*49cdfc7eSAndroid Build Coastguard Worker SAFE_UMOUNT(MOUNT_PATH);
360*49cdfc7eSAndroid Build Coastguard Worker SAFE_RMDIR(MOUNT_PATH);
361*49cdfc7eSAndroid Build Coastguard Worker }
362*49cdfc7eSAndroid Build Coastguard Worker if (ovl_mounted)
363*49cdfc7eSAndroid Build Coastguard Worker SAFE_UMOUNT(OVL_MNT);
364*49cdfc7eSAndroid Build Coastguard Worker }
365*49cdfc7eSAndroid Build Coastguard Worker
366*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
367*49cdfc7eSAndroid Build Coastguard Worker .test = do_test,
368*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(test_cases),
369*49cdfc7eSAndroid Build Coastguard Worker .test_variants = 5,
370*49cdfc7eSAndroid Build Coastguard Worker .setup = do_setup,
371*49cdfc7eSAndroid Build Coastguard Worker .cleanup = do_cleanup,
372*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
373*49cdfc7eSAndroid Build Coastguard Worker .mount_device = 1,
374*49cdfc7eSAndroid Build Coastguard Worker .mntpoint = OVL_BASE_MNTPOINT,
375*49cdfc7eSAndroid Build Coastguard Worker .all_filesystems = 1,
376*49cdfc7eSAndroid Build Coastguard Worker .tags = (const struct tst_tag[]) {
377*49cdfc7eSAndroid Build Coastguard Worker {"linux-git", "c285a2f01d69"},
378*49cdfc7eSAndroid Build Coastguard Worker {"linux-git", "bc2473c90fca"},
379*49cdfc7eSAndroid Build Coastguard Worker {}
380*49cdfc7eSAndroid Build Coastguard Worker }
381*49cdfc7eSAndroid Build Coastguard Worker };
382*49cdfc7eSAndroid Build Coastguard Worker
383*49cdfc7eSAndroid Build Coastguard Worker #else
384*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("System does not have required name_to_handle_at() support");
385*49cdfc7eSAndroid Build Coastguard Worker #endif
386*49cdfc7eSAndroid Build Coastguard Worker #else
387*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("System does not have required fanotify support");
388*49cdfc7eSAndroid Build Coastguard Worker #endif
389