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 <fcntl.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <sys/syscall.h>
37 #include "tst_test.h"
38 #include "fanotify.h"
39
40 #if defined(HAVE_SYS_FANOTIFY_H)
41 #include <sys/fanotify.h>
42
43 /* Currently this is fixed in kernel... */
44 #define MAX_EVENTS 16384
45
46 #define BUF_SIZE 256
47 static char fname[BUF_SIZE];
48 static int fd, fd_notify;
49
50 struct fanotify_event_metadata event;
51
test01(void)52 void test01(void)
53 {
54 int i;
55 int len;
56
57 /*
58 * generate events
59 */
60 for (i = 0; i < MAX_EVENTS + 1; i++) {
61 sprintf(fname, "fname_%d", i);
62 fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0644);
63 SAFE_CLOSE(fd);
64 }
65
66 while (1) {
67 /*
68 * get list on events
69 */
70 len = read(fd_notify, &event, sizeof(event));
71 if (len < 0) {
72 if (errno == -EAGAIN) {
73 tst_res(TFAIL, "Overflow event not "
74 "generated!\n");
75 break;
76 }
77 tst_brk(TBROK | TERRNO,
78 "read of notification event failed");
79 break;
80 }
81 if (event.fd != FAN_NOFD)
82 close(event.fd);
83
84 /*
85 * check events
86 */
87 if (event.mask != FAN_OPEN &&
88 event.mask != FAN_Q_OVERFLOW) {
89 tst_res(TFAIL,
90 "get event: mask=%llx (expected %llx)"
91 "pid=%u fd=%d",
92 (unsigned long long)event.mask,
93 (unsigned long long)FAN_OPEN,
94 (unsigned)event.pid, event.fd);
95 break;
96 }
97 if (event.mask == FAN_Q_OVERFLOW) {
98 if (event.fd != FAN_NOFD) {
99 tst_res(TFAIL,
100 "invalid overflow event: "
101 "mask=%llx pid=%u fd=%d",
102 (unsigned long long)event.mask,
103 (unsigned)event.pid,
104 event.fd);
105 break;
106 }
107 tst_res(TPASS,
108 "get event: mask=%llx pid=%u fd=%d",
109 (unsigned long long)event.mask,
110 (unsigned)event.pid, event.fd);
111 break;
112 }
113 }
114 }
115
setup(void)116 static void setup(void)
117 {
118 fd_notify = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF | FAN_NONBLOCK,
119 O_RDONLY);
120
121 if (fanotify_mark(fd_notify, FAN_MARK_MOUNT | FAN_MARK_ADD, FAN_OPEN,
122 AT_FDCWD, ".") < 0) {
123 tst_brk(TBROK | TERRNO,
124 "fanotify_mark (%d, FAN_MARK_MOUNT | FAN_MARK_ADD, "
125 "FAN_OPEN, AT_FDCWD, \".\") failed",
126 fd_notify);
127 }
128 }
129
cleanup(void)130 static void cleanup(void)
131 {
132 if (fd_notify > 0)
133 SAFE_CLOSE(fd_notify);
134 }
135
136 static struct tst_test test = {
137 .test_all = test01,
138 .setup = setup,
139 .cleanup = cleanup,
140 .needs_root = 1,
141 .needs_tmpdir = 1,
142 };
143 #else
144 TST_TEST_TCONF("system doesn't have required fanotify support");
145 #endif
146