1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2013 SUSE. All Rights Reserved. 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * Started by Jan Kara <jack@suse.cz> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * Check that fanotify permission events work. 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci#define _GNU_SOURCE 14f08c3bdfSopenharmony_ci#include "config.h" 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci#include <stdio.h> 17f08c3bdfSopenharmony_ci#include <unistd.h> 18f08c3bdfSopenharmony_ci#include <sys/stat.h> 19f08c3bdfSopenharmony_ci#include <sys/types.h> 20f08c3bdfSopenharmony_ci#include <sys/wait.h> 21f08c3bdfSopenharmony_ci#include <errno.h> 22f08c3bdfSopenharmony_ci#include <string.h> 23f08c3bdfSopenharmony_ci#include <signal.h> 24f08c3bdfSopenharmony_ci#include <sys/syscall.h> 25f08c3bdfSopenharmony_ci#include <stdlib.h> 26f08c3bdfSopenharmony_ci#include "tst_test.h" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_FANOTIFY_H 29f08c3bdfSopenharmony_ci# include "fanotify.h" 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#define EVENT_MAX 1024 32f08c3bdfSopenharmony_ci/* size of the event structure, not counting name */ 33f08c3bdfSopenharmony_ci#define EVENT_SIZE (sizeof(struct fanotify_event_metadata)) 34f08c3bdfSopenharmony_ci/* reasonable guess as to size of 1024 events */ 35f08c3bdfSopenharmony_ci#define EVENT_BUF_LEN (EVENT_MAX * EVENT_SIZE) 36f08c3bdfSopenharmony_ci/* Size large enough to hold a reasonable amount of expected event objects */ 37f08c3bdfSopenharmony_ci#define EVENT_SET_MAX 16 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci#define BUF_SIZE 256 40f08c3bdfSopenharmony_ci#define TST_TOTAL 3 41f08c3bdfSopenharmony_ci#define TEST_APP "fanotify_child" 42f08c3bdfSopenharmony_ci#define MOUNT_PATH "fs_mnt" 43f08c3bdfSopenharmony_ci#define FILE_EXEC_PATH MOUNT_PATH"/"TEST_APP 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic char fname[BUF_SIZE]; 46f08c3bdfSopenharmony_cistatic char buf[BUF_SIZE]; 47f08c3bdfSopenharmony_cistatic volatile int fd_notify; 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_cistatic pid_t child_pid; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistatic char event_buf[EVENT_BUF_LEN]; 52f08c3bdfSopenharmony_cistatic int exec_events_unsupported; 53f08c3bdfSopenharmony_cistatic int filesystem_mark_unsupported; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cistruct event { 56f08c3bdfSopenharmony_ci unsigned long long mask; 57f08c3bdfSopenharmony_ci unsigned int response; 58f08c3bdfSopenharmony_ci}; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic struct tcase { 61f08c3bdfSopenharmony_ci const char *tname; 62f08c3bdfSopenharmony_ci struct fanotify_mark_type mark; 63f08c3bdfSopenharmony_ci unsigned long long mask; 64f08c3bdfSopenharmony_ci int event_count; 65f08c3bdfSopenharmony_ci struct event event_set[EVENT_SET_MAX]; 66f08c3bdfSopenharmony_ci} tcases[] = { 67f08c3bdfSopenharmony_ci { 68f08c3bdfSopenharmony_ci "inode mark, FAN_OPEN_PERM | FAN_ACCESS_PERM events", 69f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 70f08c3bdfSopenharmony_ci FAN_OPEN_PERM | FAN_ACCESS_PERM, 3, 71f08c3bdfSopenharmony_ci { 72f08c3bdfSopenharmony_ci {FAN_OPEN_PERM, FAN_ALLOW}, 73f08c3bdfSopenharmony_ci {FAN_ACCESS_PERM, FAN_DENY}, 74f08c3bdfSopenharmony_ci {FAN_OPEN_PERM, FAN_DENY} 75f08c3bdfSopenharmony_ci } 76f08c3bdfSopenharmony_ci }, 77f08c3bdfSopenharmony_ci { 78f08c3bdfSopenharmony_ci "inode mark, FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM events", 79f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 80f08c3bdfSopenharmony_ci FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM, 2, 81f08c3bdfSopenharmony_ci { 82f08c3bdfSopenharmony_ci {FAN_ACCESS_PERM, FAN_DENY}, 83f08c3bdfSopenharmony_ci {FAN_OPEN_EXEC_PERM, FAN_DENY} 84f08c3bdfSopenharmony_ci } 85f08c3bdfSopenharmony_ci }, 86f08c3bdfSopenharmony_ci { 87f08c3bdfSopenharmony_ci "mount mark, FAN_OPEN_PERM | FAN_ACCESS_PERM events", 88f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 89f08c3bdfSopenharmony_ci FAN_OPEN_PERM | FAN_ACCESS_PERM, 3, 90f08c3bdfSopenharmony_ci { 91f08c3bdfSopenharmony_ci {FAN_OPEN_PERM, FAN_ALLOW}, 92f08c3bdfSopenharmony_ci {FAN_ACCESS_PERM, FAN_DENY}, 93f08c3bdfSopenharmony_ci {FAN_OPEN_PERM, FAN_DENY} 94f08c3bdfSopenharmony_ci } 95f08c3bdfSopenharmony_ci }, 96f08c3bdfSopenharmony_ci { 97f08c3bdfSopenharmony_ci "mount mark, FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM events", 98f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 99f08c3bdfSopenharmony_ci FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM, 2, 100f08c3bdfSopenharmony_ci { 101f08c3bdfSopenharmony_ci {FAN_ACCESS_PERM, FAN_DENY}, 102f08c3bdfSopenharmony_ci {FAN_OPEN_EXEC_PERM, FAN_DENY} 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci }, 105f08c3bdfSopenharmony_ci { 106f08c3bdfSopenharmony_ci "filesystem mark, FAN_OPEN_PERM | FAN_ACCESS_PERM events", 107f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 108f08c3bdfSopenharmony_ci FAN_OPEN_PERM | FAN_ACCESS_PERM, 3, 109f08c3bdfSopenharmony_ci { 110f08c3bdfSopenharmony_ci {FAN_OPEN_PERM, FAN_ALLOW}, 111f08c3bdfSopenharmony_ci {FAN_ACCESS_PERM, FAN_DENY}, 112f08c3bdfSopenharmony_ci {FAN_OPEN_PERM, FAN_DENY} 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci }, 115f08c3bdfSopenharmony_ci { 116f08c3bdfSopenharmony_ci "filesystem mark, FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM events", 117f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 118f08c3bdfSopenharmony_ci FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM, 2, 119f08c3bdfSopenharmony_ci { 120f08c3bdfSopenharmony_ci {FAN_ACCESS_PERM, FAN_DENY}, 121f08c3bdfSopenharmony_ci {FAN_OPEN_EXEC_PERM, FAN_DENY} 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci }, 124f08c3bdfSopenharmony_ci}; 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_cistatic void generate_events(void) 127f08c3bdfSopenharmony_ci{ 128f08c3bdfSopenharmony_ci int fd; 129f08c3bdfSopenharmony_ci char *const argv[] = {FILE_EXEC_PATH, NULL}; 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci /* 132f08c3bdfSopenharmony_ci * Generate sequence of events 133f08c3bdfSopenharmony_ci */ 134f08c3bdfSopenharmony_ci fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700); 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ANY, fd, fname, 1); 137f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, 0, SEEK_SET); 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci if (read(fd, buf, BUF_SIZE) != -1) 140f08c3bdfSopenharmony_ci exit(3); 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci if (execve(FILE_EXEC_PATH, argv, environ) != -1) 145f08c3bdfSopenharmony_ci exit(5); 146f08c3bdfSopenharmony_ci} 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_cistatic void child_handler(int tmp) 149f08c3bdfSopenharmony_ci{ 150f08c3bdfSopenharmony_ci (void)tmp; 151f08c3bdfSopenharmony_ci /* 152f08c3bdfSopenharmony_ci * Close notification fd so that we cannot block while reading 153f08c3bdfSopenharmony_ci * from it 154f08c3bdfSopenharmony_ci */ 155f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_notify); 156f08c3bdfSopenharmony_ci fd_notify = -1; 157f08c3bdfSopenharmony_ci} 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_cistatic void run_child(void) 160f08c3bdfSopenharmony_ci{ 161f08c3bdfSopenharmony_ci struct sigaction child_action; 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci child_action.sa_handler = child_handler; 164f08c3bdfSopenharmony_ci sigemptyset(&child_action.sa_mask); 165f08c3bdfSopenharmony_ci child_action.sa_flags = SA_NOCLDSTOP; 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci if (sigaction(SIGCHLD, &child_action, NULL) < 0) { 168f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, 169f08c3bdfSopenharmony_ci "sigaction(SIGCHLD, &child_action, NULL) failed"); 170f08c3bdfSopenharmony_ci } 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_ci child_pid = SAFE_FORK(); 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci if (child_pid == 0) { 175f08c3bdfSopenharmony_ci /* Child will generate events now */ 176f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_notify); 177f08c3bdfSopenharmony_ci generate_events(); 178f08c3bdfSopenharmony_ci exit(0); 179f08c3bdfSopenharmony_ci } 180f08c3bdfSopenharmony_ci} 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_cistatic void check_child(void) 183f08c3bdfSopenharmony_ci{ 184f08c3bdfSopenharmony_ci struct sigaction child_action; 185f08c3bdfSopenharmony_ci int child_ret; 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci child_action.sa_handler = SIG_IGN; 188f08c3bdfSopenharmony_ci sigemptyset(&child_action.sa_mask); 189f08c3bdfSopenharmony_ci child_action.sa_flags = SA_NOCLDSTOP; 190f08c3bdfSopenharmony_ci if (sigaction(SIGCHLD, &child_action, NULL) < 0) { 191f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, 192f08c3bdfSopenharmony_ci "sigaction(SIGCHLD, &child_action, NULL) failed"); 193f08c3bdfSopenharmony_ci } 194f08c3bdfSopenharmony_ci SAFE_WAITPID(-1, &child_ret, 0); 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_ci if (WIFEXITED(child_ret) && WEXITSTATUS(child_ret) == 0) 197f08c3bdfSopenharmony_ci tst_res(TPASS, "child exited correctly"); 198f08c3bdfSopenharmony_ci else 199f08c3bdfSopenharmony_ci tst_res(TFAIL, "child %s", tst_strstatus(child_ret)); 200f08c3bdfSopenharmony_ci} 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_cistatic int setup_mark(unsigned int n) 203f08c3bdfSopenharmony_ci{ 204f08c3bdfSopenharmony_ci unsigned int i = 0; 205f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 206f08c3bdfSopenharmony_ci struct fanotify_mark_type *mark = &tc->mark; 207f08c3bdfSopenharmony_ci char *const files[] = {fname, FILE_EXEC_PATH}; 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci tst_res(TINFO, "Test #%d: %s", n, tc->tname); 210f08c3bdfSopenharmony_ci 211f08c3bdfSopenharmony_ci if (exec_events_unsupported && tc->mask & FAN_OPEN_EXEC_PERM) { 212f08c3bdfSopenharmony_ci tst_res(TCONF, "FAN_OPEN_EXEC_PERM not supported in kernel?"); 213f08c3bdfSopenharmony_ci return -1; 214f08c3bdfSopenharmony_ci } 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci if (filesystem_mark_unsupported && mark->flag == FAN_MARK_FILESYSTEM) { 217f08c3bdfSopenharmony_ci tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?"); 218f08c3bdfSopenharmony_ci return -1; 219f08c3bdfSopenharmony_ci } 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci fd_notify = SAFE_FANOTIFY_INIT(FAN_CLASS_CONTENT, O_RDONLY); 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci for (; i < ARRAY_SIZE(files); i++) { 224f08c3bdfSopenharmony_ci SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD | mark->flag, 225f08c3bdfSopenharmony_ci tc->mask, AT_FDCWD, files[i]); 226f08c3bdfSopenharmony_ci } 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci return 0; 229f08c3bdfSopenharmony_ci} 230f08c3bdfSopenharmony_ci 231f08c3bdfSopenharmony_cistatic void test_fanotify(unsigned int n) 232f08c3bdfSopenharmony_ci{ 233f08c3bdfSopenharmony_ci int ret, len = 0, i = 0, test_num = 0; 234f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 235f08c3bdfSopenharmony_ci struct event *event_set = tc->event_set; 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci if (setup_mark(n) != 0) 238f08c3bdfSopenharmony_ci return; 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_ci run_child(); 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_ci /* 243f08c3bdfSopenharmony_ci * Process events 244f08c3bdfSopenharmony_ci * 245f08c3bdfSopenharmony_ci * tc->count + 1 is to accommodate for checking the child process 246f08c3bdfSopenharmony_ci * return value 247f08c3bdfSopenharmony_ci */ 248f08c3bdfSopenharmony_ci while (test_num < tc->event_count + 1 && fd_notify != -1) { 249f08c3bdfSopenharmony_ci struct fanotify_event_metadata *event; 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci if (i == len) { 252f08c3bdfSopenharmony_ci /* Get more events */ 253f08c3bdfSopenharmony_ci ret = read(fd_notify, event_buf + len, 254f08c3bdfSopenharmony_ci EVENT_BUF_LEN - len); 255f08c3bdfSopenharmony_ci if (fd_notify == -1) 256f08c3bdfSopenharmony_ci break; 257f08c3bdfSopenharmony_ci if (ret < 0) { 258f08c3bdfSopenharmony_ci tst_brk(TBROK, 259f08c3bdfSopenharmony_ci "read(%d, buf, %zu) failed", 260f08c3bdfSopenharmony_ci fd_notify, EVENT_BUF_LEN); 261f08c3bdfSopenharmony_ci } 262f08c3bdfSopenharmony_ci len += ret; 263f08c3bdfSopenharmony_ci } 264f08c3bdfSopenharmony_ci 265f08c3bdfSopenharmony_ci event = (struct fanotify_event_metadata *)&event_buf[i]; 266f08c3bdfSopenharmony_ci /* Permission events cannot be merged, so the event mask 267f08c3bdfSopenharmony_ci * reported should exactly match the event mask within the 268f08c3bdfSopenharmony_ci * event set. 269f08c3bdfSopenharmony_ci */ 270f08c3bdfSopenharmony_ci if (event->mask != event_set[test_num].mask) { 271f08c3bdfSopenharmony_ci tst_res(TFAIL, 272f08c3bdfSopenharmony_ci "got event: mask=%llx (expected %llx) " 273f08c3bdfSopenharmony_ci "pid=%u fd=%d", 274f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 275f08c3bdfSopenharmony_ci event_set[test_num].mask, 276f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd); 277f08c3bdfSopenharmony_ci } else if (event->pid != child_pid) { 278f08c3bdfSopenharmony_ci tst_res(TFAIL, 279f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u " 280f08c3bdfSopenharmony_ci "(expected %u) fd=%d", 281f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 282f08c3bdfSopenharmony_ci (unsigned int)event->pid, 283f08c3bdfSopenharmony_ci (unsigned int)child_pid, 284f08c3bdfSopenharmony_ci event->fd); 285f08c3bdfSopenharmony_ci } else { 286f08c3bdfSopenharmony_ci tst_res(TPASS, 287f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u fd=%d", 288f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 289f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd); 290f08c3bdfSopenharmony_ci } 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci /* Write response to the permission event */ 293f08c3bdfSopenharmony_ci if (event_set[test_num].mask & LTP_ALL_PERM_EVENTS) { 294f08c3bdfSopenharmony_ci struct fanotify_response resp; 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_ci resp.fd = event->fd; 297f08c3bdfSopenharmony_ci resp.response = event_set[test_num].response; 298f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd_notify, &resp, sizeof(resp)); 299f08c3bdfSopenharmony_ci } 300f08c3bdfSopenharmony_ci 301f08c3bdfSopenharmony_ci i += event->event_len; 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_ci if (event->fd != FAN_NOFD) 304f08c3bdfSopenharmony_ci SAFE_CLOSE(event->fd); 305f08c3bdfSopenharmony_ci 306f08c3bdfSopenharmony_ci test_num++; 307f08c3bdfSopenharmony_ci } 308f08c3bdfSopenharmony_ci 309f08c3bdfSopenharmony_ci for (; test_num < tc->event_count; test_num++) { 310f08c3bdfSopenharmony_ci tst_res(TFAIL, "didn't get event: mask=%llx", 311f08c3bdfSopenharmony_ci event_set[test_num].mask); 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci } 314f08c3bdfSopenharmony_ci 315f08c3bdfSopenharmony_ci check_child(); 316f08c3bdfSopenharmony_ci 317f08c3bdfSopenharmony_ci if (fd_notify > 0) 318f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_notify); 319f08c3bdfSopenharmony_ci} 320f08c3bdfSopenharmony_ci 321f08c3bdfSopenharmony_cistatic void setup(void) 322f08c3bdfSopenharmony_ci{ 323f08c3bdfSopenharmony_ci require_fanotify_access_permissions_supported_by_kernel(); 324f08c3bdfSopenharmony_ci 325f08c3bdfSopenharmony_ci filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM); 326f08c3bdfSopenharmony_ci exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC_PERM, 327f08c3bdfSopenharmony_ci FAN_CLASS_CONTENT, 0); 328f08c3bdfSopenharmony_ci sprintf(fname, MOUNT_PATH"/fname_%d", getpid()); 329f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(fname, "1"); 330f08c3bdfSopenharmony_ci 331f08c3bdfSopenharmony_ci SAFE_CP(TEST_APP, FILE_EXEC_PATH); 332f08c3bdfSopenharmony_ci} 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_cistatic void cleanup(void) 335f08c3bdfSopenharmony_ci{ 336f08c3bdfSopenharmony_ci if (fd_notify > 0) 337f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_notify); 338f08c3bdfSopenharmony_ci} 339f08c3bdfSopenharmony_ci 340f08c3bdfSopenharmony_cistatic const char *const resource_files[] = { 341f08c3bdfSopenharmony_ci TEST_APP, 342f08c3bdfSopenharmony_ci NULL 343f08c3bdfSopenharmony_ci}; 344f08c3bdfSopenharmony_ci 345f08c3bdfSopenharmony_cistatic struct tst_test test = { 346f08c3bdfSopenharmony_ci .test = test_fanotify, 347f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 348f08c3bdfSopenharmony_ci .setup = setup, 349f08c3bdfSopenharmony_ci .cleanup = cleanup, 350f08c3bdfSopenharmony_ci .forks_child = 1, 351f08c3bdfSopenharmony_ci .needs_root = 1, 352f08c3bdfSopenharmony_ci .mount_device = 1, 353f08c3bdfSopenharmony_ci .mntpoint = MOUNT_PATH, 354f08c3bdfSopenharmony_ci .resource_files = resource_files 355f08c3bdfSopenharmony_ci}; 356f08c3bdfSopenharmony_ci 357f08c3bdfSopenharmony_ci#else 358f08c3bdfSopenharmony_ci TST_TEST_TCONF("system doesn't have required fanotify support"); 359f08c3bdfSopenharmony_ci#endif 360