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 children of a directory.
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 8
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker static char fname[BUF_SIZE];
37*49cdfc7eSAndroid Build Coastguard Worker static char buf[BUF_SIZE];
38*49cdfc7eSAndroid Build Coastguard Worker static int fd, fd_notify;
39*49cdfc7eSAndroid Build Coastguard Worker
40*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long event_set[EVENT_MAX];
41*49cdfc7eSAndroid Build Coastguard Worker
42*49cdfc7eSAndroid Build Coastguard Worker static char event_buf[EVENT_BUF_LEN];
43*49cdfc7eSAndroid Build Coastguard Worker
test01(void)44*49cdfc7eSAndroid Build Coastguard Worker static void test01(void)
45*49cdfc7eSAndroid Build Coastguard Worker {
46*49cdfc7eSAndroid Build Coastguard Worker int ret, len, i = 0, test_num = 0;
47*49cdfc7eSAndroid Build Coastguard Worker
48*49cdfc7eSAndroid Build Coastguard Worker int tst_count = 0;
49*49cdfc7eSAndroid Build Coastguard Worker
50*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD, FAN_ACCESS |
51*49cdfc7eSAndroid Build Coastguard Worker FAN_MODIFY | FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD |
52*49cdfc7eSAndroid Build Coastguard Worker FAN_ONDIR, AT_FDCWD, ".");
53*49cdfc7eSAndroid Build Coastguard Worker
54*49cdfc7eSAndroid Build Coastguard Worker /*
55*49cdfc7eSAndroid Build Coastguard Worker * generate sequence of events
56*49cdfc7eSAndroid Build Coastguard Worker */
57*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
58*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_OPEN;
59*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
60*49cdfc7eSAndroid Build Coastguard Worker
61*49cdfc7eSAndroid Build Coastguard Worker SAFE_WRITE(SAFE_WRITE_ALL, fd, fname, strlen(fname));
62*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_MODIFY;
63*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
64*49cdfc7eSAndroid Build Coastguard Worker
65*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
66*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_WRITE;
67*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
68*49cdfc7eSAndroid Build Coastguard Worker
69*49cdfc7eSAndroid Build Coastguard Worker /*
70*49cdfc7eSAndroid Build Coastguard Worker * Get list of events so far. We get events here to avoid
71*49cdfc7eSAndroid Build Coastguard Worker * merging of following events with the previous ones.
72*49cdfc7eSAndroid Build Coastguard Worker */
73*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf,
74*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN);
75*49cdfc7eSAndroid Build Coastguard Worker len = ret;
76*49cdfc7eSAndroid Build Coastguard Worker
77*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDONLY);
78*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_OPEN;
79*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
80*49cdfc7eSAndroid Build Coastguard Worker
81*49cdfc7eSAndroid Build Coastguard Worker SAFE_READ(0, fd, buf, BUF_SIZE);
82*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_ACCESS;
83*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
84*49cdfc7eSAndroid Build Coastguard Worker
85*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
86*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_NOWRITE;
87*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
88*49cdfc7eSAndroid Build Coastguard Worker
89*49cdfc7eSAndroid Build Coastguard Worker /*
90*49cdfc7eSAndroid Build Coastguard Worker * get next events
91*49cdfc7eSAndroid Build Coastguard Worker */
92*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
93*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
94*49cdfc7eSAndroid Build Coastguard Worker len += ret;
95*49cdfc7eSAndroid Build Coastguard Worker
96*49cdfc7eSAndroid Build Coastguard Worker /*
97*49cdfc7eSAndroid Build Coastguard Worker * now remove child mark
98*49cdfc7eSAndroid Build Coastguard Worker */
99*49cdfc7eSAndroid Build Coastguard Worker SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_REMOVE,
100*49cdfc7eSAndroid Build Coastguard Worker FAN_EVENT_ON_CHILD, AT_FDCWD, ".");
101*49cdfc7eSAndroid Build Coastguard Worker
102*49cdfc7eSAndroid Build Coastguard Worker /*
103*49cdfc7eSAndroid Build Coastguard Worker * Do something to verify events didn't get generated
104*49cdfc7eSAndroid Build Coastguard Worker */
105*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDONLY);
106*49cdfc7eSAndroid Build Coastguard Worker
107*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
108*49cdfc7eSAndroid Build Coastguard Worker
109*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(".", O_RDONLY | O_DIRECTORY);
110*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_OPEN;
111*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
112*49cdfc7eSAndroid Build Coastguard Worker
113*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
114*49cdfc7eSAndroid Build Coastguard Worker event_set[tst_count] = FAN_CLOSE_NOWRITE;
115*49cdfc7eSAndroid Build Coastguard Worker tst_count++;
116*49cdfc7eSAndroid Build Coastguard Worker
117*49cdfc7eSAndroid Build Coastguard Worker /*
118*49cdfc7eSAndroid Build Coastguard Worker * Check events got generated only for the directory
119*49cdfc7eSAndroid Build Coastguard Worker */
120*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_READ(0, fd_notify, event_buf + len,
121*49cdfc7eSAndroid Build Coastguard Worker EVENT_BUF_LEN - len);
122*49cdfc7eSAndroid Build Coastguard Worker len += ret;
123*49cdfc7eSAndroid Build Coastguard Worker
124*49cdfc7eSAndroid Build Coastguard Worker if (TST_TOTAL != tst_count) {
125*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
126*49cdfc7eSAndroid Build Coastguard Worker "TST_TOTAL and tst_count are not equal");
127*49cdfc7eSAndroid Build Coastguard Worker }
128*49cdfc7eSAndroid Build Coastguard Worker tst_count = 0;
129*49cdfc7eSAndroid Build Coastguard Worker
130*49cdfc7eSAndroid Build Coastguard Worker /*
131*49cdfc7eSAndroid Build Coastguard Worker * check events
132*49cdfc7eSAndroid Build Coastguard Worker */
133*49cdfc7eSAndroid Build Coastguard Worker while (i < len) {
134*49cdfc7eSAndroid Build Coastguard Worker struct fanotify_event_metadata *event;
135*49cdfc7eSAndroid Build Coastguard Worker
136*49cdfc7eSAndroid Build Coastguard Worker event = (struct fanotify_event_metadata *)&event_buf[i];
137*49cdfc7eSAndroid Build Coastguard Worker if (test_num >= TST_TOTAL) {
138*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
139*49cdfc7eSAndroid Build Coastguard Worker "get unnecessary event: mask=%llx "
140*49cdfc7eSAndroid Build Coastguard Worker "pid=%u fd=%d",
141*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
142*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid, event->fd);
143*49cdfc7eSAndroid Build Coastguard Worker } else if (!(event->mask & event_set[test_num])) {
144*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
145*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx (expected %llx) "
146*49cdfc7eSAndroid Build Coastguard Worker "pid=%u fd=%d",
147*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
148*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num],
149*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid, event->fd);
150*49cdfc7eSAndroid Build Coastguard Worker } else if (event->pid != getpid()) {
151*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
152*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx pid=%u "
153*49cdfc7eSAndroid Build Coastguard Worker "(expected %u) fd=%d",
154*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
155*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid,
156*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)getpid(),
157*49cdfc7eSAndroid Build Coastguard Worker event->fd);
158*49cdfc7eSAndroid Build Coastguard Worker } else {
159*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
160*49cdfc7eSAndroid Build Coastguard Worker "got event: mask=%llx pid=%u fd=%u",
161*49cdfc7eSAndroid Build Coastguard Worker (unsigned long long)event->mask,
162*49cdfc7eSAndroid Build Coastguard Worker (unsigned int)event->pid, event->fd);
163*49cdfc7eSAndroid Build Coastguard Worker }
164*49cdfc7eSAndroid Build Coastguard Worker event->mask &= ~event_set[test_num];
165*49cdfc7eSAndroid Build Coastguard Worker /* No events left in current mask? Go for next event */
166*49cdfc7eSAndroid Build Coastguard Worker if (event->mask == 0) {
167*49cdfc7eSAndroid Build Coastguard Worker i += event->event_len;
168*49cdfc7eSAndroid Build Coastguard Worker if (event->fd != FAN_NOFD)
169*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(event->fd);
170*49cdfc7eSAndroid Build Coastguard Worker }
171*49cdfc7eSAndroid Build Coastguard Worker test_num++;
172*49cdfc7eSAndroid Build Coastguard Worker }
173*49cdfc7eSAndroid Build Coastguard Worker for (; test_num < TST_TOTAL; test_num++) {
174*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "didn't get event: mask=%llx",
175*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num]);
176*49cdfc7eSAndroid Build Coastguard Worker
177*49cdfc7eSAndroid Build Coastguard Worker }
178*49cdfc7eSAndroid Build Coastguard Worker }
179*49cdfc7eSAndroid Build Coastguard Worker
setup(void)180*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
181*49cdfc7eSAndroid Build Coastguard Worker {
182*49cdfc7eSAndroid Build Coastguard Worker sprintf(fname, "fname_%d", getpid());
183*49cdfc7eSAndroid Build Coastguard Worker fd_notify = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
184*49cdfc7eSAndroid Build Coastguard Worker }
185*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)186*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
187*49cdfc7eSAndroid Build Coastguard Worker {
188*49cdfc7eSAndroid Build Coastguard Worker if (fd_notify > 0)
189*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd_notify);
190*49cdfc7eSAndroid Build Coastguard Worker }
191*49cdfc7eSAndroid Build Coastguard Worker
192*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
193*49cdfc7eSAndroid Build Coastguard Worker .test_all = test01,
194*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
195*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
196*49cdfc7eSAndroid Build Coastguard Worker .needs_tmpdir = 1,
197*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1
198*49cdfc7eSAndroid Build Coastguard Worker };
199*49cdfc7eSAndroid Build Coastguard Worker
200*49cdfc7eSAndroid Build Coastguard Worker #else
201*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("system doesn't have required fanotify support");
202*49cdfc7eSAndroid Build Coastguard Worker #endif
203