xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/fanotify/fanotify13.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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