xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/fanotify/fanotify14.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  * Copyright (c) Linux Test Project, 2020-2022
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * Started by Matthew Bobrowski <[email protected]>
7*49cdfc7eSAndroid Build Coastguard Worker  */
8*49cdfc7eSAndroid Build Coastguard Worker 
9*49cdfc7eSAndroid Build Coastguard Worker /*\
10*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
11*49cdfc7eSAndroid Build Coastguard Worker  * This test file has been designed to ensure that the fanotify
12*49cdfc7eSAndroid Build Coastguard Worker  * system calls fanotify_init(2) and fanotify_mark(2) return the
13*49cdfc7eSAndroid Build Coastguard Worker  * correct error code to the calling process when an invalid flag or
14*49cdfc7eSAndroid Build Coastguard Worker  * mask value has been specified in conjunction with FAN_REPORT_FID.
15*49cdfc7eSAndroid Build Coastguard Worker  */
16*49cdfc7eSAndroid Build Coastguard Worker 
17*49cdfc7eSAndroid Build Coastguard Worker /*
18*49cdfc7eSAndroid Build Coastguard Worker  * The ENOTDIR test cases are regression tests for commits:
19*49cdfc7eSAndroid Build Coastguard Worker  *
20*49cdfc7eSAndroid Build Coastguard Worker  *     ceaf69f8eadc fanotify: do not allow setting dirent events in mask of non-dir
21*49cdfc7eSAndroid Build Coastguard Worker  *     8698e3bab4dd fanotify: refine the validation checks on non-dir inode mask
22*49cdfc7eSAndroid Build Coastguard Worker  *
23*49cdfc7eSAndroid Build Coastguard Worker  * The pipes test cases are regression tests for commit:
24*49cdfc7eSAndroid Build Coastguard Worker  *     69562eb0bd3e fanotify: disallow mount/sb marks on kernel internal pseudo fs
25*49cdfc7eSAndroid Build Coastguard Worker  */
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
28*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
29*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
30*49cdfc7eSAndroid Build Coastguard Worker 
31*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_SYS_FANOTIFY_H
32*49cdfc7eSAndroid Build Coastguard Worker #include "fanotify.h"
33*49cdfc7eSAndroid Build Coastguard Worker 
34*49cdfc7eSAndroid Build Coastguard Worker #define MNTPOINT "mntpoint"
35*49cdfc7eSAndroid Build Coastguard Worker #define FILE1 MNTPOINT"/file1"
36*49cdfc7eSAndroid Build Coastguard Worker 
37*49cdfc7eSAndroid Build Coastguard Worker /*
38*49cdfc7eSAndroid Build Coastguard Worker  * List of inode events that are only available when notification group is
39*49cdfc7eSAndroid Build Coastguard Worker  * set to report fid.
40*49cdfc7eSAndroid Build Coastguard Worker  */
41*49cdfc7eSAndroid Build Coastguard Worker #define INODE_EVENTS (FAN_ATTRIB | FAN_CREATE | FAN_DELETE | FAN_MOVE | \
42*49cdfc7eSAndroid Build Coastguard Worker 		      FAN_DELETE_SELF | FAN_MOVE_SELF)
43*49cdfc7eSAndroid Build Coastguard Worker 
44*49cdfc7eSAndroid Build Coastguard Worker #define FLAGS_DESC(flags) {(flags), (#flags)}
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker static int pipes[2] = {-1, -1};
47*49cdfc7eSAndroid Build Coastguard Worker static int fanotify_fd;
48*49cdfc7eSAndroid Build Coastguard Worker static int ignore_mark_unsupported;
49*49cdfc7eSAndroid Build Coastguard Worker static int filesystem_mark_unsupported;
50*49cdfc7eSAndroid Build Coastguard Worker static int se_enforcing;
51*49cdfc7eSAndroid Build Coastguard Worker static unsigned int supported_init_flags;
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker struct test_case_flags_t {
54*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long flags;
55*49cdfc7eSAndroid Build Coastguard Worker 	const char *desc;
56*49cdfc7eSAndroid Build Coastguard Worker };
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker /*
59*49cdfc7eSAndroid Build Coastguard Worker  * Each test case has been designed in a manner whereby the values defined
60*49cdfc7eSAndroid Build Coastguard Worker  * within should result in the interface to return an error to the calling
61*49cdfc7eSAndroid Build Coastguard Worker  * process.
62*49cdfc7eSAndroid Build Coastguard Worker  */
63*49cdfc7eSAndroid Build Coastguard Worker static struct test_case_t {
64*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case_flags_t init;
65*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case_flags_t mark;
66*49cdfc7eSAndroid Build Coastguard Worker 	/* when mask.flags == 0, fanotify_init() is expected to fail */
67*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case_flags_t mask;
68*49cdfc7eSAndroid Build Coastguard Worker 	int expected_errno;
69*49cdfc7eSAndroid Build Coastguard Worker 	int *pfd;
70*49cdfc7eSAndroid Build Coastguard Worker } test_cases[] = {
71*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_REPORT_FID without class FAN_CLASS_NOTIF is not valid */
72*49cdfc7eSAndroid Build Coastguard Worker 	{
73*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_CONTENT | FAN_REPORT_FID),
74*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
75*49cdfc7eSAndroid Build Coastguard Worker 	},
76*49cdfc7eSAndroid Build Coastguard Worker 
77*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_REPORT_FID without class FAN_CLASS_NOTIF is not valid */
78*49cdfc7eSAndroid Build Coastguard Worker 	{
79*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_PRE_CONTENT | FAN_REPORT_FID),
80*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
81*49cdfc7eSAndroid Build Coastguard Worker 	},
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 	/* INODE_EVENTS in mask without class FAN_REPORT_FID are not valid */
84*49cdfc7eSAndroid Build Coastguard Worker 	{
85*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
86*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_INODE),
87*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(INODE_EVENTS),
88*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
89*49cdfc7eSAndroid Build Coastguard Worker 	},
90*49cdfc7eSAndroid Build Coastguard Worker 
91*49cdfc7eSAndroid Build Coastguard Worker 	/* INODE_EVENTS in mask with FAN_MARK_MOUNT are not valid */
92*49cdfc7eSAndroid Build Coastguard Worker 	{
93*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID),
94*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_MOUNT),
95*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(INODE_EVENTS),
96*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
97*49cdfc7eSAndroid Build Coastguard Worker 	},
98*49cdfc7eSAndroid Build Coastguard Worker 
99*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */
100*49cdfc7eSAndroid Build Coastguard Worker 	{
101*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_NAME),
102*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
103*49cdfc7eSAndroid Build Coastguard Worker 	},
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */
106*49cdfc7eSAndroid Build Coastguard Worker 	{
107*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID | FAN_REPORT_NAME),
108*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
109*49cdfc7eSAndroid Build Coastguard Worker 	},
110*49cdfc7eSAndroid Build Coastguard Worker 
111*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_REPORT_TARGET_FID without FAN_REPORT_FID is not valid */
112*49cdfc7eSAndroid Build Coastguard Worker 	{
113*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_NAME),
114*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
115*49cdfc7eSAndroid Build Coastguard Worker 	},
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_REPORT_TARGET_FID without FAN_REPORT_NAME is not valid */
118*49cdfc7eSAndroid Build Coastguard Worker 	{
119*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_FID),
120*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
121*49cdfc7eSAndroid Build Coastguard Worker 	},
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_RENAME without FAN_REPORT_NAME is not valid */
124*49cdfc7eSAndroid Build Coastguard Worker 	{
125*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_FID),
126*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_INODE),
127*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_RENAME),
128*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
129*49cdfc7eSAndroid Build Coastguard Worker 	},
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 	/* With FAN_MARK_ONLYDIR on non-dir is not valid */
132*49cdfc7eSAndroid Build Coastguard Worker 	{
133*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
134*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_ONLYDIR),
135*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN),
136*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
137*49cdfc7eSAndroid Build Coastguard Worker 	},
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker 	/* With FAN_REPORT_TARGET_FID, FAN_DELETE on non-dir is not valid */
140*49cdfc7eSAndroid Build Coastguard Worker 	{
141*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
142*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_INODE),
143*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_DELETE),
144*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
145*49cdfc7eSAndroid Build Coastguard Worker 	},
146*49cdfc7eSAndroid Build Coastguard Worker 
147*49cdfc7eSAndroid Build Coastguard Worker 	/* With FAN_REPORT_TARGET_FID, FAN_RENAME on non-dir is not valid */
148*49cdfc7eSAndroid Build Coastguard Worker 	{
149*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
150*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_INODE),
151*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_RENAME),
152*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
153*49cdfc7eSAndroid Build Coastguard Worker 	},
154*49cdfc7eSAndroid Build Coastguard Worker 
155*49cdfc7eSAndroid Build Coastguard Worker 	/* With FAN_REPORT_TARGET_FID, FAN_ONDIR on non-dir is not valid */
156*49cdfc7eSAndroid Build Coastguard Worker 	{
157*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
158*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_INODE),
159*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN | FAN_ONDIR),
160*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
161*49cdfc7eSAndroid Build Coastguard Worker 	},
162*49cdfc7eSAndroid Build Coastguard Worker 
163*49cdfc7eSAndroid Build Coastguard Worker 	/* With FAN_REPORT_TARGET_FID, FAN_EVENT_ON_CHILD on non-dir is not valid */
164*49cdfc7eSAndroid Build Coastguard Worker 	{
165*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
166*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_INODE),
167*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD),
168*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
169*49cdfc7eSAndroid Build Coastguard Worker 	},
170*49cdfc7eSAndroid Build Coastguard Worker 
171*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE_SURV with FAN_DELETE on non-dir is not valid */
172*49cdfc7eSAndroid Build Coastguard Worker 	{
173*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
174*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
175*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_DELETE),
176*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
177*49cdfc7eSAndroid Build Coastguard Worker 	},
178*49cdfc7eSAndroid Build Coastguard Worker 
179*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE_SURV with FAN_RENAME on non-dir is not valid */
180*49cdfc7eSAndroid Build Coastguard Worker 	{
181*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
182*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
183*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_RENAME),
184*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
185*49cdfc7eSAndroid Build Coastguard Worker 	},
186*49cdfc7eSAndroid Build Coastguard Worker 
187*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE_SURV with FAN_ONDIR on non-dir is not valid */
188*49cdfc7eSAndroid Build Coastguard Worker 	{
189*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
190*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
191*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN | FAN_ONDIR),
192*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
193*49cdfc7eSAndroid Build Coastguard Worker 	},
194*49cdfc7eSAndroid Build Coastguard Worker 
195*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE_SURV with FAN_EVENT_ON_CHILD on non-dir is not valid */
196*49cdfc7eSAndroid Build Coastguard Worker 	{
197*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
198*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
199*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD),
200*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = ENOTDIR,
201*49cdfc7eSAndroid Build Coastguard Worker 	},
202*49cdfc7eSAndroid Build Coastguard Worker 
203*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on directory is not valid */
204*49cdfc7eSAndroid Build Coastguard Worker 	{
205*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
206*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_IGNORE),
207*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN),
208*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EISDIR,
209*49cdfc7eSAndroid Build Coastguard Worker 	},
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on mount mark is not valid */
212*49cdfc7eSAndroid Build Coastguard Worker 	{
213*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
214*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_MOUNT | FAN_MARK_IGNORE),
215*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN),
216*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
217*49cdfc7eSAndroid Build Coastguard Worker 	},
218*49cdfc7eSAndroid Build Coastguard Worker 
219*49cdfc7eSAndroid Build Coastguard Worker 	/* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on filesystem mark is not valid */
220*49cdfc7eSAndroid Build Coastguard Worker 	{
221*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
222*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_FILESYSTEM | FAN_MARK_IGNORE),
223*49cdfc7eSAndroid Build Coastguard Worker 		.mask = FLAGS_DESC(FAN_OPEN),
224*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
225*49cdfc7eSAndroid Build Coastguard Worker 	},
226*49cdfc7eSAndroid Build Coastguard Worker 	/* mount mark on anonymous pipe is not valid */
227*49cdfc7eSAndroid Build Coastguard Worker 	{
228*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
229*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_MOUNT),
230*49cdfc7eSAndroid Build Coastguard Worker 		.mask = { FAN_ACCESS, "anonymous pipe"},
231*49cdfc7eSAndroid Build Coastguard Worker 		.pfd = pipes,
232*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
233*49cdfc7eSAndroid Build Coastguard Worker 	},
234*49cdfc7eSAndroid Build Coastguard Worker 	/* filesystem mark on anonymous pipe is not valid */
235*49cdfc7eSAndroid Build Coastguard Worker 	{
236*49cdfc7eSAndroid Build Coastguard Worker 		.init = FLAGS_DESC(FAN_CLASS_NOTIF),
237*49cdfc7eSAndroid Build Coastguard Worker 		.mark = FLAGS_DESC(FAN_MARK_FILESYSTEM),
238*49cdfc7eSAndroid Build Coastguard Worker 		.mask = { FAN_ACCESS, "anonymous pipe"},
239*49cdfc7eSAndroid Build Coastguard Worker 		.pfd = pipes,
240*49cdfc7eSAndroid Build Coastguard Worker 		.expected_errno = EINVAL,
241*49cdfc7eSAndroid Build Coastguard Worker 	},
242*49cdfc7eSAndroid Build Coastguard Worker };
243*49cdfc7eSAndroid Build Coastguard Worker 
do_test(unsigned int number)244*49cdfc7eSAndroid Build Coastguard Worker static void do_test(unsigned int number)
245*49cdfc7eSAndroid Build Coastguard Worker {
246*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case_t *tc = &test_cases[number];
247*49cdfc7eSAndroid Build Coastguard Worker 
248*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Test case %d: fanotify_init(%s, O_RDONLY)", number,
249*49cdfc7eSAndroid Build Coastguard Worker 		tc->init.desc);
250*49cdfc7eSAndroid Build Coastguard Worker 
251*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->init.flags & ~supported_init_flags) {
252*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TCONF, "Unsupported init flags");
253*49cdfc7eSAndroid Build Coastguard Worker 		return;
254*49cdfc7eSAndroid Build Coastguard Worker 	}
255*49cdfc7eSAndroid Build Coastguard Worker 
256*49cdfc7eSAndroid Build Coastguard Worker 	if (ignore_mark_unsupported && tc->mark.flags & FAN_MARK_IGNORE) {
257*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TCONF, "FAN_MARK_IGNORE not supported in kernel?");
258*49cdfc7eSAndroid Build Coastguard Worker 		return;
259*49cdfc7eSAndroid Build Coastguard Worker 	}
260*49cdfc7eSAndroid Build Coastguard Worker 
261*49cdfc7eSAndroid Build Coastguard Worker 	if (!tc->mask.flags && tc->expected_errno) {
262*49cdfc7eSAndroid Build Coastguard Worker 		TST_EXP_FAIL(fanotify_init(tc->init.flags, O_RDONLY),
263*49cdfc7eSAndroid Build Coastguard Worker 			tc->expected_errno);
264*49cdfc7eSAndroid Build Coastguard Worker 	} else {
265*49cdfc7eSAndroid Build Coastguard Worker 		TST_EXP_FD(fanotify_init(tc->init.flags, O_RDONLY));
266*49cdfc7eSAndroid Build Coastguard Worker 	}
267*49cdfc7eSAndroid Build Coastguard Worker 
268*49cdfc7eSAndroid Build Coastguard Worker 	fanotify_fd = TST_RET;
269*49cdfc7eSAndroid Build Coastguard Worker 
270*49cdfc7eSAndroid Build Coastguard Worker 	if (fanotify_fd < 0)
271*49cdfc7eSAndroid Build Coastguard Worker 		return;
272*49cdfc7eSAndroid Build Coastguard Worker 
273*49cdfc7eSAndroid Build Coastguard Worker 	if (!tc->mask.flags)
274*49cdfc7eSAndroid Build Coastguard Worker 		goto out;
275*49cdfc7eSAndroid Build Coastguard Worker 
276*49cdfc7eSAndroid Build Coastguard Worker 	/* Set mark on non-dir only when expecting error ENOTDIR */
277*49cdfc7eSAndroid Build Coastguard Worker 	const char *path = tc->expected_errno == ENOTDIR ? FILE1 : MNTPOINT;
278*49cdfc7eSAndroid Build Coastguard Worker 	const int exp_errs[] = {tc->expected_errno, EACCES};
279*49cdfc7eSAndroid Build Coastguard Worker 	int dirfd = AT_FDCWD;
280*49cdfc7eSAndroid Build Coastguard Worker 
281*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->pfd) {
282*49cdfc7eSAndroid Build Coastguard Worker 		dirfd = tc->pfd[0];
283*49cdfc7eSAndroid Build Coastguard Worker 		path = NULL;
284*49cdfc7eSAndroid Build Coastguard Worker 	}
285*49cdfc7eSAndroid Build Coastguard Worker 
286*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Testing %s with %s",
287*49cdfc7eSAndroid Build Coastguard Worker 		tc->mark.desc, tc->mask.desc);
288*49cdfc7eSAndroid Build Coastguard Worker 
289*49cdfc7eSAndroid Build Coastguard Worker 	TST_EXP_FAIL_ARR(fanotify_mark(fanotify_fd, FAN_MARK_ADD | tc->mark.flags,
290*49cdfc7eSAndroid Build Coastguard Worker 			 tc->mask.flags, dirfd, path), exp_errs, se_enforcing ? 2 : 1);
291*49cdfc7eSAndroid Build Coastguard Worker 
292*49cdfc7eSAndroid Build Coastguard Worker 	/*
293*49cdfc7eSAndroid Build Coastguard Worker 	 * ENOTDIR are errors for events/flags not allowed on a non-dir inode.
294*49cdfc7eSAndroid Build Coastguard Worker 	 * Try to set an inode mark on a directory and it should succeed.
295*49cdfc7eSAndroid Build Coastguard Worker 	 * Try to set directory events in filesystem mark mask on non-dir
296*49cdfc7eSAndroid Build Coastguard Worker 	 * and it should succeed.
297*49cdfc7eSAndroid Build Coastguard Worker 	 */
298*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_PASS && tc->expected_errno == ENOTDIR) {
299*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | tc->mark.flags,
300*49cdfc7eSAndroid Build Coastguard Worker 				   tc->mask.flags, AT_FDCWD, MNTPOINT);
301*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS,
302*49cdfc7eSAndroid Build Coastguard Worker 			"Adding an inode mark on directory did not fail with "
303*49cdfc7eSAndroid Build Coastguard Worker 			"ENOTDIR error as on non-dir inode");
304*49cdfc7eSAndroid Build Coastguard Worker 
305*49cdfc7eSAndroid Build Coastguard Worker 		if (!(tc->mark.flags & FAN_MARK_ONLYDIR) && !filesystem_mark_unsupported) {
306*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | tc->mark.flags |
307*49cdfc7eSAndroid Build Coastguard Worker 					   FAN_MARK_FILESYSTEM, tc->mask.flags,
308*49cdfc7eSAndroid Build Coastguard Worker 					   AT_FDCWD, FILE1);
309*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TPASS,
310*49cdfc7eSAndroid Build Coastguard Worker 				"Adding a filesystem mark on non-dir did not fail with "
311*49cdfc7eSAndroid Build Coastguard Worker 				"ENOTDIR error as with an inode mark");
312*49cdfc7eSAndroid Build Coastguard Worker 		}
313*49cdfc7eSAndroid Build Coastguard Worker 	}
314*49cdfc7eSAndroid Build Coastguard Worker 
315*49cdfc7eSAndroid Build Coastguard Worker out:
316*49cdfc7eSAndroid Build Coastguard Worker 	if (fanotify_fd > 0)
317*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fanotify_fd);
318*49cdfc7eSAndroid Build Coastguard Worker }
319*49cdfc7eSAndroid Build Coastguard Worker 
do_setup(void)320*49cdfc7eSAndroid Build Coastguard Worker static void do_setup(void)
321*49cdfc7eSAndroid Build Coastguard Worker {
322*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int all_init_flags = FAN_REPORT_DFID_NAME_TARGET |
323*49cdfc7eSAndroid Build Coastguard Worker 		FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT;
324*49cdfc7eSAndroid Build Coastguard Worker 
325*49cdfc7eSAndroid Build Coastguard Worker 	/* Require FAN_REPORT_FID support for all tests to simplify per test case requirements */
326*49cdfc7eSAndroid Build Coastguard Worker 	REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, MNTPOINT);
327*49cdfc7eSAndroid Build Coastguard Worker 	supported_init_flags = fanotify_get_supported_init_flags(all_init_flags, MNTPOINT);
328*49cdfc7eSAndroid Build Coastguard Worker 
329*49cdfc7eSAndroid Build Coastguard Worker 	ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV,
330*49cdfc7eSAndroid Build Coastguard Worker 								MNTPOINT);
331*49cdfc7eSAndroid Build Coastguard Worker 	filesystem_mark_unsupported =
332*49cdfc7eSAndroid Build Coastguard Worker 		fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN,
333*49cdfc7eSAndroid Build Coastguard Worker 						MNTPOINT);
334*49cdfc7eSAndroid Build Coastguard Worker 
335*49cdfc7eSAndroid Build Coastguard Worker 	/* Create temporary test file to place marks on */
336*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_PRINTF(FILE1, "0");
337*49cdfc7eSAndroid Build Coastguard Worker 	/* Create anonymous pipes to place marks on */
338*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_PIPE2(pipes, O_CLOEXEC);
339*49cdfc7eSAndroid Build Coastguard Worker 
340*49cdfc7eSAndroid Build Coastguard Worker 	se_enforcing = tst_selinux_enforcing();
341*49cdfc7eSAndroid Build Coastguard Worker }
342*49cdfc7eSAndroid Build Coastguard Worker 
do_cleanup(void)343*49cdfc7eSAndroid Build Coastguard Worker static void do_cleanup(void)
344*49cdfc7eSAndroid Build Coastguard Worker {
345*49cdfc7eSAndroid Build Coastguard Worker 	if (fanotify_fd > 0)
346*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fanotify_fd);
347*49cdfc7eSAndroid Build Coastguard Worker 	if (pipes[0] != -1)
348*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(pipes[0]);
349*49cdfc7eSAndroid Build Coastguard Worker 	if (pipes[1] != -1)
350*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(pipes[1]);
351*49cdfc7eSAndroid Build Coastguard Worker }
352*49cdfc7eSAndroid Build Coastguard Worker 
353*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
354*49cdfc7eSAndroid Build Coastguard Worker 	.needs_root = 1,
355*49cdfc7eSAndroid Build Coastguard Worker 	.test = do_test,
356*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(test_cases),
357*49cdfc7eSAndroid Build Coastguard Worker 	.setup = do_setup,
358*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = do_cleanup,
359*49cdfc7eSAndroid Build Coastguard Worker 	.mount_device = 1,
360*49cdfc7eSAndroid Build Coastguard Worker 	.mntpoint = MNTPOINT,
361*49cdfc7eSAndroid Build Coastguard Worker 	.all_filesystems = 1,
362*49cdfc7eSAndroid Build Coastguard Worker 	.tags = (const struct tst_tag[]) {
363*49cdfc7eSAndroid Build Coastguard Worker 		{"linux-git", "ceaf69f8eadc"},
364*49cdfc7eSAndroid Build Coastguard Worker 		{"linux-git", "8698e3bab4dd"},
365*49cdfc7eSAndroid Build Coastguard Worker 		{"linux-git", "69562eb0bd3e"},
366*49cdfc7eSAndroid Build Coastguard Worker 		{}
367*49cdfc7eSAndroid Build Coastguard Worker 	}
368*49cdfc7eSAndroid Build Coastguard Worker };
369*49cdfc7eSAndroid Build Coastguard Worker 
370*49cdfc7eSAndroid Build Coastguard Worker #else
371*49cdfc7eSAndroid Build Coastguard Worker 	TST_TEST_TCONF("System does not have required fanotify support");
372*49cdfc7eSAndroid Build Coastguard Worker #endif
373