1 /*
2 * Copyright (c) 2014 SUSE Linux. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * Started by Jan Kara <jack@suse.cz>
20 *
21 * DESCRIPTION
22 * Check that fanotify overflow event is properly generated
23 *
24 * ALGORITHM
25 * Generate enough events without reading them and check that overflow
26 * event is generated.
27 */
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/fcntl.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <sys/syscall.h>
37 #include "test.h"
38 #include "linux_syscall_numbers.h"
39 #include "fanotify.h"
40 #include "safe_macros.h"
41
42 char *TCID = "fanotify05";
43 int TST_TOTAL = 1;
44
45 #if defined(HAVE_SYS_FANOTIFY_H)
46 #include <sys/fanotify.h>
47
48 /* Currently this is fixed in kernel... */
49 #define MAX_EVENTS 16384
50
51 static void setup(void);
52 static void cleanup(void);
53
54 #define BUF_SIZE 256
55 static char fname[BUF_SIZE];
56 static int fd, fd_notify;
57
58 struct fanotify_event_metadata event;
59
main(int ac,char ** av)60 int main(int ac, char **av)
61 {
62 int lc, i;
63 int len;
64
65 tst_parse_opts(ac, av, NULL, NULL);
66
67 setup();
68
69 for (lc = 0; TEST_LOOPING(lc); lc++) {
70 /*
71 * generate events
72 */
73 for (i = 0; i < MAX_EVENTS + 1; i++) {
74 sprintf(fname, "fname_%d", i);
75 fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0644);
76 SAFE_CLOSE(cleanup, fd);
77 }
78
79 while (1) {
80 /*
81 * get list on events
82 */
83 len = read(fd_notify, &event, sizeof(event));
84 if (len < 0) {
85 if (errno == -EAGAIN) {
86 tst_resm(TFAIL, "Overflow event not "
87 "generated!\n");
88 break;
89 }
90 tst_brkm(TBROK | TERRNO, cleanup,
91 "read of notification event failed");
92 break;
93 }
94 if (event.fd != FAN_NOFD)
95 close(event.fd);
96
97 /*
98 * check events
99 */
100 if (event.mask != FAN_OPEN &&
101 event.mask != FAN_Q_OVERFLOW) {
102 tst_resm(TFAIL,
103 "get event: mask=%llx (expected %llx)"
104 "pid=%u fd=%d",
105 (unsigned long long)event.mask,
106 (unsigned long long)FAN_OPEN,
107 (unsigned)event.pid, event.fd);
108 break;
109 }
110 if (event.mask == FAN_Q_OVERFLOW) {
111 if (event.fd != FAN_NOFD) {
112 tst_resm(TFAIL,
113 "invalid overflow event: "
114 "mask=%llx pid=%u fd=%d",
115 (unsigned long long)event.mask,
116 (unsigned)event.pid,
117 event.fd);
118 break;
119 }
120 tst_resm(TPASS,
121 "get event: mask=%llx pid=%u fd=%d",
122 (unsigned long long)event.mask,
123 (unsigned)event.pid, event.fd);
124 break;
125 }
126 }
127 }
128
129 cleanup();
130 tst_exit();
131 }
132
setup(void)133 static void setup(void)
134 {
135 tst_sig(NOFORK, DEF_HANDLER, cleanup);
136
137 TEST_PAUSE;
138
139 tst_tmpdir();
140
141 fd_notify = fanotify_init(FAN_CLASS_NOTIF | FAN_NONBLOCK, O_RDONLY);
142 if (fd_notify < 0) {
143 if (errno == ENOSYS) {
144 tst_brkm(TCONF, cleanup,
145 "fanotify is not configured in this kernel.");
146 } else {
147 tst_brkm(TBROK | TERRNO, cleanup,
148 "fanotify_init failed");
149 }
150 }
151
152 if (fanotify_mark(fd_notify, FAN_MARK_MOUNT | FAN_MARK_ADD, FAN_OPEN,
153 AT_FDCWD, ".") < 0) {
154 tst_brkm(TBROK | TERRNO, cleanup,
155 "fanotify_mark (%d, FAN_MARK_MOUNT | FAN_MARK_ADD, "
156 "FAN_OPEN, AT_FDCWD, \".\") failed",
157 fd_notify);
158 }
159 }
160
cleanup(void)161 static void cleanup(void)
162 {
163 if (fd_notify > 0 && close(fd_notify))
164 tst_resm(TWARN | TERRNO, "close(%d) failed", fd_notify);
165
166 tst_rmdir();
167 }
168
169 #else
170
main(void)171 int main(void)
172 {
173 tst_brkm(TCONF, NULL, "system doesn't have required fanotify support");
174 }
175
176 #endif
177