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) 2013 SUSE. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker *
5*49cdfc7eSAndroid Build Coastguard Worker * Started by Jan Kara <[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 * Check that fanotify work for a file.
11*49cdfc7eSAndroid Build Coastguard Worker */
12*49cdfc7eSAndroid Build Coastguard Worker
13*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
14*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
15*49cdfc7eSAndroid Build Coastguard Worker
16*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <sys/syscall.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
23*49cdfc7eSAndroid Build Coastguard Worker
24*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_SYS_FANOTIFY_H
25*49cdfc7eSAndroid Build Coastguard Worker #include "fanotify.h"
26*49cdfc7eSAndroid Build Coastguard Worker
27*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_MAX 1024
28*49cdfc7eSAndroid Build Coastguard Worker /* size of the event structure, not counting name */
29*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_SIZE (sizeof(struct fanotify_event_metadata))
30*49cdfc7eSAndroid Build Coastguard Worker /* reasonable guess as to size of 1024 events */
31*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_BUF_LEN (EVENT_MAX * EVENT_SIZE)
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker #define BUF_SIZE 256
34*49cdfc7eSAndroid Build Coastguard Worker #define TST_TOTAL 12
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker #define MOUNT_PATH "fs_mnt"
37*49cdfc7eSAndroid Build Coastguard Worker
38*49cdfc7eSAndroid Build Coastguard Worker static struct tcase {
39*49cdfc7eSAndroid Build Coastguard Worker const char *tname;
40*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_mark_type mark;
41*49cdfc7eSAndroid Build Coastguard Worker unsigned int init_flags;
42*49cdfc7eSAndroid Build Coastguard Worker } tcases[] = {
43*49cdfc7eSAndroid Build Coastguard Worker {
44*49cdfc7eSAndroid Build Coastguard Worker "inode mark events",
45*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(INODE),
46*49cdfc7eSAndroid Build Coastguard Worker FAN_CLASS_NOTIF
47*49cdfc7eSAndroid Build Coastguard Worker },
48*49cdfc7eSAndroid Build Coastguard Worker {
49*49cdfc7eSAndroid Build Coastguard Worker "mount mark events",
50*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(MOUNT),
51*49cdfc7eSAndroid Build Coastguard Worker FAN_CLASS_NOTIF
52*49cdfc7eSAndroid Build Coastguard Worker },
53*49cdfc7eSAndroid Build Coastguard Worker {
54*49cdfc7eSAndroid Build Coastguard Worker "filesystem mark events",
55*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(FILESYSTEM),
56*49cdfc7eSAndroid Build Coastguard Worker FAN_CLASS_NOTIF
57*49cdfc7eSAndroid Build Coastguard Worker },
58*49cdfc7eSAndroid Build Coastguard Worker {
59*49cdfc7eSAndroid Build Coastguard Worker "inode mark events (FAN_REPORT_FID)",
60*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(INODE),
61*49cdfc7eSAndroid Build Coastguard Worker FAN_CLASS_NOTIF|FAN_REPORT_FID
62*49cdfc7eSAndroid Build Coastguard Worker },
63*49cdfc7eSAndroid Build Coastguard Worker {
64*49cdfc7eSAndroid Build Coastguard Worker "mount mark events (FAN_REPORT_FID)",
65*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(MOUNT),
66*49cdfc7eSAndroid Build Coastguard Worker FAN_CLASS_NOTIF|FAN_REPORT_FID
67*49cdfc7eSAndroid Build Coastguard Worker },
68*49cdfc7eSAndroid Build Coastguard Worker {
69*49cdfc7eSAndroid Build Coastguard Worker "filesystem mark events (FAN_REPORT_FID)",
70*49cdfc7eSAndroid Build Coastguard Worker INIT_FANOTIFY_MARK_TYPE(FILESYSTEM),
71*49cdfc7eSAndroid Build Coastguard Worker FAN_CLASS_NOTIF|FAN_REPORT_FID
72*49cdfc7eSAndroid Build Coastguard Worker },
73*49cdfc7eSAndroid Build Coastguard Worker };
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker static char fname[BUF_SIZE];
76*49cdfc7eSAndroid Build Coastguard Worker static char buf[BUF_SIZE];
77*49cdfc7eSAndroid Build Coastguard Worker static int fd_notify;
78*49cdfc7eSAndroid Build Coastguard Worker static int fan_report_fid_unsupported;
79*49cdfc7eSAndroid Build Coastguard Worker static int mount_mark_fid_unsupported;
80*49cdfc7eSAndroid Build Coastguard Worker static int inode_mark_fid_xdev;
81*49cdfc7eSAndroid Build Coastguard Worker static int filesystem_mark_unsupported;
82*49cdfc7eSAndroid Build Coastguard Worker
83*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long event_set[EVENT_MAX];
84*49cdfc7eSAndroid Build Coastguard Worker
85*49cdfc7eSAndroid Build Coastguard Worker static char event_buf[EVENT_BUF_LEN];
86*49cdfc7eSAndroid Build Coastguard Worker
test_fanotify(unsigned int n)87*49cdfc7eSAndroid Build Coastguard Worker static void test_fanotify(unsigned int n)
88*49cdfc7eSAndroid Build Coastguard Worker {
89*49cdfc7eSAndroid Build Coastguard Worker struct tcase *tc = &tcases[n];
90*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_mark_type *mark = &tc->mark;
91*49cdfc7eSAndroid Build Coastguard Worker int fd, ret, len, i = 0, test_num = 0;
92*49cdfc7eSAndroid Build Coastguard Worker int tst_count = 0;
93*49cdfc7eSAndroid Build Coastguard Worker int report_fid = (tc->init_flags & FAN_REPORT_FID);
94*49cdfc7eSAndroid Build Coastguard Worker
95*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Test #%d: %s", n, tc->tname);
96*49cdfc7eSAndroid Build Coastguard Worker
97*49cdfc7eSAndroid Build Coastguard Worker if (fan_report_fid_unsupported && report_fid) {
98*49cdfc7eSAndroid Build Coastguard Worker FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_FID, fan_report_fid_unsupported);
99*49cdfc7eSAndroid Build Coastguard Worker return;
100*49cdfc7eSAndroid Build Coastguard Worker }
101*49cdfc7eSAndroid Build Coastguard Worker
102*49cdfc7eSAndroid Build Coastguard Worker if (filesystem_mark_unsupported && mark->flag == FAN_MARK_FILESYSTEM) {
103*49cdfc7eSAndroid Build Coastguard Worker FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported);
104*49cdfc7eSAndroid Build Coastguard Worker return;
105*49cdfc7eSAndroid Build Coastguard Worker }
106*49cdfc7eSAndroid Build Coastguard Worker
107*49cdfc7eSAndroid Build Coastguard Worker if (mount_mark_fid_unsupported && report_fid && mark->flag != FAN_MARK_INODE) {
108*49cdfc7eSAndroid Build Coastguard Worker FANOTIFY_MARK_FLAGS_ERR_MSG(mark, mount_mark_fid_unsupported);
109*49cdfc7eSAndroid Build Coastguard Worker return;
110*49cdfc7eSAndroid Build Coastguard Worker }
111*49cdfc7eSAndroid Build Coastguard Worker
112*49cdfc7eSAndroid Build Coastguard Worker fd_notify = SAFE_FANOTIFY_INIT(tc->init_flags, O_RDONLY);
113*49cdfc7eSAndroid Build Coastguard Worker
114*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD | mark->flag,
115*49cdfc7eSAndroid Build Coastguard Worker FAN_ACCESS | FAN_MODIFY | FAN_CLOSE | FAN_OPEN, AT_FDCWD, fname);
116*49cdfc7eSAndroid Build Coastguard Worker
117*49cdfc7eSAndroid Build Coastguard Worker /*
118*49cdfc7eSAndroid Build Coastguard Worker * generate sequence of events
119*49cdfc7eSAndroid Build Coastguard Worker */
120*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDONLY);
121*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_OPEN;
122*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
123*49cdfc7eSAndroid Build Coastguard Worker
124*49cdfc7eSAndroid Build Coastguard Worker SAFE_READ(0, fd, buf, BUF_SIZE);
125*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_ACCESS;
126*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
127*49cdfc7eSAndroid Build Coastguard Worker
128*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
129*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_NOWRITE;
130*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
131*49cdfc7eSAndroid Build Coastguard Worker
132*49cdfc7eSAndroid Build Coastguard Worker /*
133*49cdfc7eSAndroid Build Coastguard Worker * Get list of events so far. We get events here to avoid
134*49cdfc7eSAndroid Build Coastguard Worker * merging of following events with the previous ones.
135*49cdfc7eSAndroid Build Coastguard Worker */
136*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf, EVENT_BUF_LEN);
137*49cdfc7eSAndroid Build Coastguard Worker len = ret;
138*49cdfc7eSAndroid Build Coastguard Worker
139*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
140*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_OPEN;
141*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
142*49cdfc7eSAndroid Build Coastguard Worker
143*49cdfc7eSAndroid Build Coastguard Worker SAFE_WRITE(SAFE_WRITE_ALL, fd, fname, strlen(fname));
144*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_MODIFY;
145*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
146*49cdfc7eSAndroid Build Coastguard Worker
147*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
148*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_WRITE;
149*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
150*49cdfc7eSAndroid Build Coastguard Worker
151*49cdfc7eSAndroid Build Coastguard Worker /*
152*49cdfc7eSAndroid Build Coastguard Worker * get another list of events
153*49cdfc7eSAndroid Build Coastguard Worker */
154*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
155*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
156*49cdfc7eSAndroid Build Coastguard Worker len += ret;
157*49cdfc7eSAndroid Build Coastguard Worker
158*49cdfc7eSAndroid Build Coastguard Worker /*
159*49cdfc7eSAndroid Build Coastguard Worker * Ignore mask testing
160*49cdfc7eSAndroid Build Coastguard Worker */
161*49cdfc7eSAndroid Build Coastguard Worker
162*49cdfc7eSAndroid Build Coastguard Worker /* Ignore access events */
163*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify,
164*49cdfc7eSAndroid Build Coastguard Worker FAN_MARK_ADD | mark->flag | FAN_MARK_IGNORED_MASK,
165*49cdfc7eSAndroid Build Coastguard Worker FAN_ACCESS, AT_FDCWD, fname);
166*49cdfc7eSAndroid Build Coastguard Worker
167*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDWR);
168*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_OPEN;
169*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
170*49cdfc7eSAndroid Build Coastguard Worker
171*49cdfc7eSAndroid Build Coastguard Worker /* This event should be ignored */
172*49cdfc7eSAndroid Build Coastguard Worker SAFE_READ(0, fd, buf, BUF_SIZE);
173*49cdfc7eSAndroid Build Coastguard Worker
174*49cdfc7eSAndroid Build Coastguard Worker /*
175*49cdfc7eSAndroid Build Coastguard Worker * get another list of events to verify the last one got ignored
176*49cdfc7eSAndroid Build Coastguard Worker */
177*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
178*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
179*49cdfc7eSAndroid Build Coastguard Worker len += ret;
180*49cdfc7eSAndroid Build Coastguard Worker
181*49cdfc7eSAndroid Build Coastguard Worker SAFE_LSEEK(fd, 0, SEEK_SET);
182*49cdfc7eSAndroid Build Coastguard Worker /* Generate modify event to clear ignore mask */
183*49cdfc7eSAndroid Build Coastguard Worker SAFE_WRITE(SAFE_WRITE_ALL, fd, fname, 1);
184*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_MODIFY;
185*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
186*49cdfc7eSAndroid Build Coastguard Worker
187*49cdfc7eSAndroid Build Coastguard Worker /*
188*49cdfc7eSAndroid Build Coastguard Worker * This event shouldn't be ignored because previous modification
189*49cdfc7eSAndroid Build Coastguard Worker * should have removed the ignore mask
190*49cdfc7eSAndroid Build Coastguard Worker */
191*49cdfc7eSAndroid Build Coastguard Worker SAFE_READ(0, fd, buf, BUF_SIZE);
192*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_ACCESS;
193*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
194*49cdfc7eSAndroid Build Coastguard Worker
195*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
196*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_WRITE;
197*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
198*49cdfc7eSAndroid Build Coastguard Worker
199*49cdfc7eSAndroid Build Coastguard Worker /* Read events to verify previous access was properly generated */
200*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
201*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
202*49cdfc7eSAndroid Build Coastguard Worker len += ret;
203*49cdfc7eSAndroid Build Coastguard Worker
204*49cdfc7eSAndroid Build Coastguard Worker /*
205*49cdfc7eSAndroid Build Coastguard Worker * Now ignore open & close events regardless of file
206*49cdfc7eSAndroid Build Coastguard Worker * modifications
207*49cdfc7eSAndroid Build Coastguard Worker */
208*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD | mark->flag |
209*49cdfc7eSAndroid Build Coastguard Worker FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY,
210*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE, AT_FDCWD, fname);
211*49cdfc7eSAndroid Build Coastguard Worker
212*49cdfc7eSAndroid Build Coastguard Worker /* This event should be ignored */
213*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDWR);
214*49cdfc7eSAndroid Build Coastguard Worker
215*49cdfc7eSAndroid Build Coastguard Worker SAFE_WRITE(SAFE_WRITE_ALL, fd, fname, 1);
216*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_MODIFY;
217*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
218*49cdfc7eSAndroid Build Coastguard Worker
219*49cdfc7eSAndroid Build Coastguard Worker /* This event should be still ignored */
220*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
221*49cdfc7eSAndroid Build Coastguard Worker
222*49cdfc7eSAndroid Build Coastguard Worker /* This event should still be ignored */
223*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDWR);
224*49cdfc7eSAndroid Build Coastguard Worker
225*49cdfc7eSAndroid Build Coastguard Worker /* Read events to verify open & close were ignored */
226*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
227*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
228*49cdfc7eSAndroid Build Coastguard Worker len += ret;
229*49cdfc7eSAndroid Build Coastguard Worker
230*49cdfc7eSAndroid Build Coastguard Worker /* Now remove open and close from ignored mask */
231*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify,
232*49cdfc7eSAndroid Build Coastguard Worker FAN_MARK_REMOVE | mark->flag | FAN_MARK_IGNORED_MASK,
233*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN | FAN_CLOSE, AT_FDCWD, fname);
234*49cdfc7eSAndroid Build Coastguard Worker
235*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
236*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_WRITE;
237*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
238*49cdfc7eSAndroid Build Coastguard Worker
239*49cdfc7eSAndroid Build Coastguard Worker /* Read events to verify close was generated */
240*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
241*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
242*49cdfc7eSAndroid Build Coastguard Worker len += ret;
243*49cdfc7eSAndroid Build Coastguard Worker
244*49cdfc7eSAndroid Build Coastguard Worker if (TST_TOTAL != tst_count) {
245*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
246*49cdfc7eSAndroid Build Coastguard Worker "TST_TOTAL (%d) and tst_count (%d) are not "
247*49cdfc7eSAndroid Build Coastguard Worker "equal", TST_TOTAL, tst_count);
248*49cdfc7eSAndroid Build Coastguard Worker }
249*49cdfc7eSAndroid Build Coastguard Worker tst_count = 0;
250*49cdfc7eSAndroid Build Coastguard Worker
251*49cdfc7eSAndroid Build Coastguard Worker /*
252*49cdfc7eSAndroid Build Coastguard Worker * check events
253*49cdfc7eSAndroid Build Coastguard Worker */
254*49cdfc7eSAndroid Build Coastguard Worker while (i < len) {
255*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_event_metadata *event;
256*49cdfc7eSAndroid Build Coastguard Worker
257*49cdfc7eSAndroid Build Coastguard Worker event = (struct fanotify_event_metadata *)&event_buf[i];
258*49cdfc7eSAndroid Build Coastguard Worker if (test_num >= TST_TOTAL) {
259*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
260*49cdfc7eSAndroid Build Coastguard Worker "got unnecessary event: mask=%llx "
261*49cdfc7eSAndroid Build Coastguard Worker "pid=%u fd=%d",
262*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
263*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid, event->fd);
264*49cdfc7eSAndroid Build Coastguard Worker } else if (!(event->mask & event_set[test_num])) {
265*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
266*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx (expected %llx) "
267*49cdfc7eSAndroid Build Coastguard Worker "pid=%u fd=%d",
268*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
269*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num],
270*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid, event->fd);
271*49cdfc7eSAndroid Build Coastguard Worker } else if (event->pid != getpid()) {
272*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
273*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx pid=%u "
274*49cdfc7eSAndroid Build Coastguard Worker "(expected %u) fd=%d",
275*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
276*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid,
277*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)getpid(),
278*49cdfc7eSAndroid Build Coastguard Worker event->fd);
279*49cdfc7eSAndroid Build Coastguard Worker } else {
280*49cdfc7eSAndroid Build Coastguard Worker if (event->fd == -2 || (event->fd == FAN_NOFD &&
281*49cdfc7eSAndroid Build Coastguard Worker (tc->init_flags & FAN_REPORT_FID)))
282*49cdfc7eSAndroid Build Coastguard Worker goto pass;
283*49cdfc7eSAndroid Build Coastguard Worker ret = read(event->fd, buf, BUF_SIZE);
284*49cdfc7eSAndroid Build Coastguard Worker if (ret != (int)strlen(fname)) {
285*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
286*49cdfc7eSAndroid Build Coastguard Worker "cannot read from returned fd "
287*49cdfc7eSAndroid Build Coastguard Worker "of event: mask=%llx pid=%u "
288*49cdfc7eSAndroid Build Coastguard Worker "fd=%d ret=%d (errno=%d)",
289*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
290*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid,
291*49cdfc7eSAndroid Build Coastguard Worker event->fd, ret, errno);
292*49cdfc7eSAndroid Build Coastguard Worker } else if (memcmp(buf, fname, strlen(fname))) {
293*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
294*49cdfc7eSAndroid Build Coastguard Worker "wrong data read from returned fd "
295*49cdfc7eSAndroid Build Coastguard Worker "of event: mask=%llx pid=%u "
296*49cdfc7eSAndroid Build Coastguard Worker "fd=%d",
297*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
298*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid,
299*49cdfc7eSAndroid Build Coastguard Worker event->fd);
300*49cdfc7eSAndroid Build Coastguard Worker } else {
301*49cdfc7eSAndroid Build Coastguard Worker pass:
302*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
303*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx pid=%u fd=%d",
304*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
305*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid, event->fd);
306*49cdfc7eSAndroid Build Coastguard Worker }
307*49cdfc7eSAndroid Build Coastguard Worker }
308*49cdfc7eSAndroid Build Coastguard Worker
309*49cdfc7eSAndroid Build Coastguard Worker /*
310*49cdfc7eSAndroid Build Coastguard Worker * We have verified the data now so close fd and
311*49cdfc7eSAndroid Build Coastguard Worker * invalidate it so that we don't check it again
312*49cdfc7eSAndroid Build Coastguard Worker * unnecessarily
313*49cdfc7eSAndroid Build Coastguard Worker */
314*49cdfc7eSAndroid Build Coastguard Worker if (event->fd >= 0)
315*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(event->fd);
316*49cdfc7eSAndroid Build Coastguard Worker event->fd = -2;
317*49cdfc7eSAndroid Build Coastguard Worker event->mask &= ~event_set[test_num];
318*49cdfc7eSAndroid Build Coastguard Worker
319*49cdfc7eSAndroid Build Coastguard Worker /* No events left in current mask? Go for next event */
320*49cdfc7eSAndroid Build Coastguard Worker if (event->mask == 0)
321*49cdfc7eSAndroid Build Coastguard Worker i += event->event_len;
322*49cdfc7eSAndroid Build Coastguard Worker
323*49cdfc7eSAndroid Build Coastguard Worker test_num++;
324*49cdfc7eSAndroid Build Coastguard Worker }
325*49cdfc7eSAndroid Build Coastguard Worker
326*49cdfc7eSAndroid Build Coastguard Worker for (; test_num < TST_TOTAL; test_num++) {
327*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "didn't get event: mask=%llx",
328*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num]);
329*49cdfc7eSAndroid Build Coastguard Worker
330*49cdfc7eSAndroid Build Coastguard Worker }
331*49cdfc7eSAndroid Build Coastguard Worker
332*49cdfc7eSAndroid Build Coastguard Worker
333*49cdfc7eSAndroid Build Coastguard Worker /*
334*49cdfc7eSAndroid Build Coastguard Worker * Try to setup a bogus mark on test tmp dir, to check if marks on
335*49cdfc7eSAndroid Build Coastguard Worker * different filesystems are supported.
336*49cdfc7eSAndroid Build Coastguard Worker * When tested fs has zero fsid (e.g. fuse) and events are reported
337*49cdfc7eSAndroid Build Coastguard Worker * with fsid+fid, watching different filesystems is not supported.
338*49cdfc7eSAndroid Build Coastguard Worker */
339*49cdfc7eSAndroid Build Coastguard Worker ret = report_fid ? inode_mark_fid_xdev : 0;
340*49cdfc7eSAndroid Build Coastguard Worker TST_EXP_FD_OR_FAIL(fanotify_mark(fd_notify, FAN_MARK_ADD, FAN_CLOSE_WRITE,
341*49cdfc7eSAndroid Build Coastguard Worker AT_FDCWD, "."), ret);
342*49cdfc7eSAndroid Build Coastguard Worker
343*49cdfc7eSAndroid Build Coastguard Worker /* Remove mark to clear FAN_MARK_IGNORED_SURV_MODIFY */
344*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_REMOVE | mark->flag,
345*49cdfc7eSAndroid Build Coastguard Worker FAN_ACCESS | FAN_MODIFY | FAN_CLOSE | FAN_OPEN,
346*49cdfc7eSAndroid Build Coastguard Worker AT_FDCWD, fname);
347*49cdfc7eSAndroid Build Coastguard Worker
348*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd_notify);
349*49cdfc7eSAndroid Build Coastguard Worker }
350*49cdfc7eSAndroid Build Coastguard Worker
setup(void)351*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
352*49cdfc7eSAndroid Build Coastguard Worker {
353*49cdfc7eSAndroid Build Coastguard Worker int fd;
354*49cdfc7eSAndroid Build Coastguard Worker
355*49cdfc7eSAndroid Build Coastguard Worker /* Check for kernel fanotify support */
356*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
357*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
358*49cdfc7eSAndroid Build Coastguard Worker
359*49cdfc7eSAndroid Build Coastguard Worker sprintf(fname, MOUNT_PATH"/tfile_%d", getpid());
360*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(fname, "1");
361*49cdfc7eSAndroid Build Coastguard Worker
362*49cdfc7eSAndroid Build Coastguard Worker fan_report_fid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_FID, fname);
363*49cdfc7eSAndroid Build Coastguard Worker filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM, fname);
364*49cdfc7eSAndroid Build Coastguard Worker mount_mark_fid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_FID,
365*49cdfc7eSAndroid Build Coastguard Worker FAN_MARK_MOUNT,
366*49cdfc7eSAndroid Build Coastguard Worker FAN_OPEN, fname);
367*49cdfc7eSAndroid Build Coastguard Worker /*
368*49cdfc7eSAndroid Build Coastguard Worker * When mount mark is not supported due to zero fsid (e.g. fuse) or if TMPDIR has
369*49cdfc7eSAndroid Build Coastguard Worker * non-uniform fsid (e.g. btrfs subvol), multi fs inode marks are not supported.
370*49cdfc7eSAndroid Build Coastguard Worker */
371*49cdfc7eSAndroid Build Coastguard Worker if (mount_mark_fid_unsupported && errno == ENODEV) {
372*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "filesystem %s does not support reporting events with fid from multi fs",
373*49cdfc7eSAndroid Build Coastguard Worker tst_device->fs_type);
374*49cdfc7eSAndroid Build Coastguard Worker inode_mark_fid_xdev = EXDEV;
375*49cdfc7eSAndroid Build Coastguard Worker }
376*49cdfc7eSAndroid Build Coastguard Worker
377*49cdfc7eSAndroid Build Coastguard Worker if (fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_MOUNT, FAN_OPEN, ".")) {
378*49cdfc7eSAndroid Build Coastguard Worker inode_mark_fid_xdev = errno;
379*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "TMPDIR does not support reporting events with fid from multi fs");
380*49cdfc7eSAndroid Build Coastguard Worker }
381*49cdfc7eSAndroid Build Coastguard Worker }
382*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)383*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
384*49cdfc7eSAndroid Build Coastguard Worker {
385*49cdfc7eSAndroid Build Coastguard Worker if (fd_notify > 0)
386*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd_notify);
387*49cdfc7eSAndroid Build Coastguard Worker }
388*49cdfc7eSAndroid Build Coastguard Worker
389*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
390*49cdfc7eSAndroid Build Coastguard Worker .test = test_fanotify,
391*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(tcases),
392*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
393*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
394*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
395*49cdfc7eSAndroid Build Coastguard Worker .mount_device = 1,
396*49cdfc7eSAndroid Build Coastguard Worker .mntpoint = MOUNT_PATH,
397*49cdfc7eSAndroid Build Coastguard Worker .all_filesystems = 1,
398*49cdfc7eSAndroid Build Coastguard Worker };
399*49cdfc7eSAndroid Build Coastguard Worker
400*49cdfc7eSAndroid Build Coastguard Worker #else
401*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("system doesn't have required fanotify support");
402*49cdfc7eSAndroid Build Coastguard Worker #endif
403