1 /* 2 * Copyright (c) 2013 SUSE. 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 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Started by Jan Kara <jack@suse.cz> 24 * 25 * DESCRIPTION 26 * Check that fanotify permission events work 27 */ 28 #define _GNU_SOURCE 29 #include "config.h" 30 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <sys/stat.h> 34 #include <sys/types.h> 35 #include <fcntl.h> 36 #include <sys/wait.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <signal.h> 40 #include <sys/syscall.h> 41 #include <stdlib.h> 42 #include "tst_test.h" 43 #include "fanotify.h" 44 45 #if defined(HAVE_SYS_FANOTIFY_H) 46 #include <sys/fanotify.h> 47 48 #define EVENT_MAX 1024 49 /* size of the event structure, not counting name */ 50 #define EVENT_SIZE (sizeof (struct fanotify_event_metadata)) 51 /* reasonable guess as to size of 1024 events */ 52 #define EVENT_BUF_LEN (EVENT_MAX * EVENT_SIZE) 53 54 #define BUF_SIZE 256 55 #define TST_TOTAL 3 56 57 static char fname[BUF_SIZE]; 58 static char buf[BUF_SIZE]; 59 static volatile int fd_notify; 60 61 static pid_t child_pid; 62 63 static unsigned long long event_set[EVENT_MAX]; 64 static unsigned int event_resp[EVENT_MAX]; 65 66 static char event_buf[EVENT_BUF_LEN]; 67 68 static void generate_events(void) 69 { 70 int fd; 71 72 /* 73 * generate sequence of events 74 */ 75 if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) 76 exit(1); 77 if (write(fd, fname, 1) == -1) 78 exit(2); 79 80 lseek(fd, 0, SEEK_SET); 81 if (read(fd, buf, BUF_SIZE) != -1) 82 exit(3); 83 84 if (close(fd) == -1) 85 exit(4); 86 } 87 88 static void child_handler(int tmp) 89 { 90 (void)tmp; 91 /* 92 * Close notification fd so that we cannot block while reading 93 * from it 94 */ 95 close(fd_notify); 96 fd_notify = -1; 97 } 98 99 static void run_child(void) 100 { 101 struct sigaction child_action; 102 103 child_action.sa_handler = child_handler; 104 sigemptyset(&child_action.sa_mask); 105 child_action.sa_flags = SA_NOCLDSTOP; 106 107 if (sigaction(SIGCHLD, &child_action, NULL) < 0) { 108 tst_brk(TBROK | TERRNO, 109 "sigaction(SIGCHLD, &child_action, NULL) failed"); 110 } 111 112 child_pid = SAFE_FORK(); 113 if (child_pid == 0) { 114 /* Child will generate events now */ 115 close(fd_notify); 116 generate_events(); 117 exit(0); 118 } 119 } 120 121 static void check_child(void) 122 { 123 struct sigaction child_action; 124 int child_ret; 125 126 child_action.sa_handler = SIG_IGN; 127 sigemptyset(&child_action.sa_mask); 128 child_action.sa_flags = SA_NOCLDSTOP; 129 if (sigaction(SIGCHLD, &child_action, NULL) < 0) { 130 tst_brk(TBROK | TERRNO, 131 "sigaction(SIGCHLD, &child_action, NULL) failed"); 132 } 133 SAFE_WAITPID(-1, &child_ret, 0); 134 135 if (WIFEXITED(child_ret) && WEXITSTATUS(child_ret) == 0) 136 tst_res(TPASS, "child exited correctly"); 137 else 138 tst_res(TFAIL, "child %s", tst_strstatus(child_ret)); 139 } 140 141 void test01(void) 142 { 143 int tst_count, fd_notify_backup = -1; 144 145 int ret, len = 0, i = 0, test_num = 0; 146 147 if (fd_notify_backup == -1) { 148 fd_notify_backup = SAFE_DUP(fd_notify); 149 } 150 run_child(); 151 152 tst_count = 0; 153 154 event_set[tst_count] = FAN_OPEN_PERM; 155 event_resp[tst_count++] = FAN_ALLOW; 156 event_set[tst_count] = FAN_ACCESS_PERM; 157 event_resp[tst_count++] = FAN_DENY; 158 159 /* tst_count + 1 is for checking child return value */ 160 if (TST_TOTAL != tst_count + 1) { 161 tst_brk(TBROK, 162 "TST_TOTAL and tst_count do not match"); 163 } 164 tst_count = 0; 165 166 /* 167 * check events 168 */ 169 while (test_num < TST_TOTAL && fd_notify != -1) { 170 struct fanotify_event_metadata *event; 171 172 if (i == len) { 173 /* Get more events */ 174 ret = read(fd_notify, event_buf + len, 175 EVENT_BUF_LEN - len); 176 if (fd_notify == -1) 177 break; 178 if (ret < 0) { 179 tst_brk(TBROK, 180 "read(%d, buf, %zu) failed", 181 fd_notify, EVENT_BUF_LEN); 182 } 183 len += ret; 184 } 185 186 event = (struct fanotify_event_metadata *)&event_buf[i]; 187 if (!(event->mask & event_set[test_num])) { 188 tst_res(TFAIL, 189 "get event: mask=%llx (expected %llx) " 190 "pid=%u fd=%u", 191 (unsigned long long)event->mask, 192 event_set[test_num], 193 (unsigned)event->pid, event->fd); 194 } else if (event->pid != child_pid) { 195 tst_res(TFAIL, 196 "get event: mask=%llx pid=%u " 197 "(expected %u) fd=%u", 198 (unsigned long long)event->mask, 199 (unsigned)event->pid, 200 (unsigned)child_pid, 201 event->fd); 202 } else { 203 tst_res(TPASS, 204 "get event: mask=%llx pid=%u fd=%u", 205 (unsigned long long)event->mask, 206 (unsigned)event->pid, event->fd); 207 } 208 /* Write response to permission event */ 209 if (event_set[test_num] & FAN_ALL_PERM_EVENTS) { 210 struct fanotify_response resp; 211 212 resp.fd = event->fd; 213 resp.response = event_resp[test_num]; 214 SAFE_WRITE(1, fd_notify, &resp, 215 sizeof(resp)); 216 } 217 event->mask &= ~event_set[test_num]; 218 /* No events left in current mask? Go for next event */ 219 if (event->mask == 0) { 220 i += event->event_len; 221 close(event->fd); 222 } 223 test_num++; 224 } 225 for (; test_num < TST_TOTAL - 1; test_num++) { 226 tst_res(TFAIL, "didn't get event: mask=%llx", 227 event_set[test_num]); 228 229 } 230 check_child(); 231 /* We got SIGCHLD while running, resetup fd_notify */ 232 if (fd_notify == -1) { 233 fd_notify = fd_notify_backup; 234 fd_notify_backup = -1; 235 } 236 } 237 238 static void setup(void) 239 { 240 int fd; 241 242 sprintf(fname, "fname_%d", getpid()); 243 fd = SAFE_OPEN(fname, O_CREAT | O_RDWR, 0644); 244 SAFE_WRITE(1, fd, fname, 1); 245 SAFE_CLOSE(fd); 246 247 fd_notify = SAFE_FANOTIFY_INIT(FAN_CLASS_CONTENT, O_RDONLY); 248 249 if (fanotify_mark(fd_notify, FAN_MARK_ADD, FAN_ACCESS_PERM | 250 FAN_OPEN_PERM, AT_FDCWD, fname) < 0) { 251 if (errno == EINVAL) { 252 tst_brk(TCONF | TERRNO, 253 "CONFIG_FANOTIFY_ACCESS_PERMISSIONS not " 254 "configured in kernel?"); 255 } else { 256 tst_brk(TBROK | TERRNO, 257 "fanotify_mark (%d, FAN_MARK_ADD, FAN_ACCESS_PERM | " 258 "FAN_OPEN_PERM, AT_FDCWD, %s) failed.", fd_notify, fname); 259 } 260 } 261 262 } 263 264 static void cleanup(void) 265 { 266 if (fd_notify > 0) 267 SAFE_CLOSE(fd_notify); 268 } 269 270 static struct tst_test test = { 271 .test_all = test01, 272 .setup = setup, 273 .cleanup = cleanup, 274 .needs_tmpdir = 1, 275 .forks_child = 1, 276 .needs_root = 1 277 }; 278 279 #else 280 TST_TEST_TCONF("system doesn't have required fanotify support"); 281 #endif 282