1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved. 4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2020-2022 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org> 7f08c3bdfSopenharmony_ci */ 8f08c3bdfSopenharmony_ci 9f08c3bdfSopenharmony_ci/*\ 10f08c3bdfSopenharmony_ci * [Description] 11f08c3bdfSopenharmony_ci * This test file has been designed to ensure that the fanotify 12f08c3bdfSopenharmony_ci * system calls fanotify_init(2) and fanotify_mark(2) return the 13f08c3bdfSopenharmony_ci * correct error code to the calling process when an invalid flag or 14f08c3bdfSopenharmony_ci * mask value has been specified in conjunction with FAN_REPORT_FID. 15f08c3bdfSopenharmony_ci */ 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci/* 18f08c3bdfSopenharmony_ci * The ENOTDIR test cases are regression tests for commits: 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * ceaf69f8eadc fanotify: do not allow setting dirent events in mask of non-dir 21f08c3bdfSopenharmony_ci * 8698e3bab4dd fanotify: refine the validation checks on non-dir inode mask 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * The pipes test cases are regression tests for commit: 24f08c3bdfSopenharmony_ci * 69562eb0bd3e fanotify: disallow mount/sb marks on kernel internal pseudo fs 25f08c3bdfSopenharmony_ci */ 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#define _GNU_SOURCE 28f08c3bdfSopenharmony_ci#include "tst_test.h" 29f08c3bdfSopenharmony_ci#include <errno.h> 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_FANOTIFY_H 32f08c3bdfSopenharmony_ci#include "fanotify.h" 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint" 35f08c3bdfSopenharmony_ci#define FILE1 MNTPOINT"/file1" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci/* 38f08c3bdfSopenharmony_ci * List of inode events that are only available when notification group is 39f08c3bdfSopenharmony_ci * set to report fid. 40f08c3bdfSopenharmony_ci */ 41f08c3bdfSopenharmony_ci#define INODE_EVENTS (FAN_ATTRIB | FAN_CREATE | FAN_DELETE | FAN_MOVE | \ 42f08c3bdfSopenharmony_ci FAN_DELETE_SELF | FAN_MOVE_SELF) 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci#define FLAGS_DESC(flags) {(flags), (#flags)} 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic int pipes[2] = {-1, -1}; 47f08c3bdfSopenharmony_cistatic int fanotify_fd; 48f08c3bdfSopenharmony_cistatic int fan_report_target_fid_unsupported; 49f08c3bdfSopenharmony_cistatic int ignore_mark_unsupported; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistruct test_case_flags_t { 52f08c3bdfSopenharmony_ci unsigned long long flags; 53f08c3bdfSopenharmony_ci const char *desc; 54f08c3bdfSopenharmony_ci}; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci/* 57f08c3bdfSopenharmony_ci * Each test case has been designed in a manner whereby the values defined 58f08c3bdfSopenharmony_ci * within should result in the interface to return an error to the calling 59f08c3bdfSopenharmony_ci * process. 60f08c3bdfSopenharmony_ci */ 61f08c3bdfSopenharmony_cistatic struct test_case_t { 62f08c3bdfSopenharmony_ci struct test_case_flags_t init; 63f08c3bdfSopenharmony_ci struct test_case_flags_t mark; 64f08c3bdfSopenharmony_ci /* when mask.flags == 0, fanotify_init() is expected to fail */ 65f08c3bdfSopenharmony_ci struct test_case_flags_t mask; 66f08c3bdfSopenharmony_ci int expected_errno; 67f08c3bdfSopenharmony_ci int *pfd; 68f08c3bdfSopenharmony_ci} test_cases[] = { 69f08c3bdfSopenharmony_ci /* FAN_REPORT_FID without class FAN_CLASS_NOTIF is not valid */ 70f08c3bdfSopenharmony_ci { 71f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_CONTENT | FAN_REPORT_FID), 72f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 73f08c3bdfSopenharmony_ci }, 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci /* FAN_REPORT_FID without class FAN_CLASS_NOTIF is not valid */ 76f08c3bdfSopenharmony_ci { 77f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_PRE_CONTENT | FAN_REPORT_FID), 78f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 79f08c3bdfSopenharmony_ci }, 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci /* INODE_EVENTS in mask without class FAN_REPORT_FID are not valid */ 82f08c3bdfSopenharmony_ci { 83f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 84f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_INODE), 85f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(INODE_EVENTS), 86f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 87f08c3bdfSopenharmony_ci }, 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci /* INODE_EVENTS in mask with FAN_MARK_MOUNT are not valid */ 90f08c3bdfSopenharmony_ci { 91f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID), 92f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_MOUNT), 93f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(INODE_EVENTS), 94f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 95f08c3bdfSopenharmony_ci }, 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci /* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */ 98f08c3bdfSopenharmony_ci { 99f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_NAME), 100f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 101f08c3bdfSopenharmony_ci }, 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci /* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */ 104f08c3bdfSopenharmony_ci { 105f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID | FAN_REPORT_NAME), 106f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 107f08c3bdfSopenharmony_ci }, 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci /* FAN_REPORT_TARGET_FID without FAN_REPORT_FID is not valid */ 110f08c3bdfSopenharmony_ci { 111f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_NAME), 112f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 113f08c3bdfSopenharmony_ci }, 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci /* FAN_REPORT_TARGET_FID without FAN_REPORT_NAME is not valid */ 116f08c3bdfSopenharmony_ci { 117f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_FID), 118f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 119f08c3bdfSopenharmony_ci }, 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci /* FAN_RENAME without FAN_REPORT_NAME is not valid */ 122f08c3bdfSopenharmony_ci { 123f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_FID), 124f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_INODE), 125f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_RENAME), 126f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 127f08c3bdfSopenharmony_ci }, 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci /* With FAN_MARK_ONLYDIR on non-dir is not valid */ 130f08c3bdfSopenharmony_ci { 131f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 132f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_ONLYDIR), 133f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN), 134f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 135f08c3bdfSopenharmony_ci }, 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci /* With FAN_REPORT_TARGET_FID, FAN_DELETE on non-dir is not valid */ 138f08c3bdfSopenharmony_ci { 139f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET), 140f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_INODE), 141f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_DELETE), 142f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 143f08c3bdfSopenharmony_ci }, 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci /* With FAN_REPORT_TARGET_FID, FAN_RENAME on non-dir is not valid */ 146f08c3bdfSopenharmony_ci { 147f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET), 148f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_INODE), 149f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_RENAME), 150f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 151f08c3bdfSopenharmony_ci }, 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci /* With FAN_REPORT_TARGET_FID, FAN_ONDIR on non-dir is not valid */ 154f08c3bdfSopenharmony_ci { 155f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET), 156f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_INODE), 157f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN | FAN_ONDIR), 158f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 159f08c3bdfSopenharmony_ci }, 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci /* With FAN_REPORT_TARGET_FID, FAN_EVENT_ON_CHILD on non-dir is not valid */ 162f08c3bdfSopenharmony_ci { 163f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET), 164f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_INODE), 165f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD), 166f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 167f08c3bdfSopenharmony_ci }, 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE_SURV with FAN_DELETE on non-dir is not valid */ 170f08c3bdfSopenharmony_ci { 171f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME), 172f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV), 173f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_DELETE), 174f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 175f08c3bdfSopenharmony_ci }, 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE_SURV with FAN_RENAME on non-dir is not valid */ 178f08c3bdfSopenharmony_ci { 179f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME), 180f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV), 181f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_RENAME), 182f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 183f08c3bdfSopenharmony_ci }, 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE_SURV with FAN_ONDIR on non-dir is not valid */ 186f08c3bdfSopenharmony_ci { 187f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME), 188f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV), 189f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN | FAN_ONDIR), 190f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 191f08c3bdfSopenharmony_ci }, 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE_SURV with FAN_EVENT_ON_CHILD on non-dir is not valid */ 194f08c3bdfSopenharmony_ci { 195f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME), 196f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV), 197f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD), 198f08c3bdfSopenharmony_ci .expected_errno = ENOTDIR, 199f08c3bdfSopenharmony_ci }, 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on directory is not valid */ 202f08c3bdfSopenharmony_ci { 203f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 204f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_IGNORE), 205f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN), 206f08c3bdfSopenharmony_ci .expected_errno = EISDIR, 207f08c3bdfSopenharmony_ci }, 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on mount mark is not valid */ 210f08c3bdfSopenharmony_ci { 211f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 212f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_MOUNT | FAN_MARK_IGNORE), 213f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN), 214f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 215f08c3bdfSopenharmony_ci }, 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci /* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on filesystem mark is not valid */ 218f08c3bdfSopenharmony_ci { 219f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 220f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_FILESYSTEM | FAN_MARK_IGNORE), 221f08c3bdfSopenharmony_ci .mask = FLAGS_DESC(FAN_OPEN), 222f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 223f08c3bdfSopenharmony_ci }, 224f08c3bdfSopenharmony_ci /* mount mark on anonymous pipe is not valid */ 225f08c3bdfSopenharmony_ci { 226f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 227f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_MOUNT), 228f08c3bdfSopenharmony_ci .mask = { FAN_ACCESS, "anonymous pipe"}, 229f08c3bdfSopenharmony_ci .pfd = pipes, 230f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 231f08c3bdfSopenharmony_ci }, 232f08c3bdfSopenharmony_ci /* filesystem mark on anonymous pipe is not valid */ 233f08c3bdfSopenharmony_ci { 234f08c3bdfSopenharmony_ci .init = FLAGS_DESC(FAN_CLASS_NOTIF), 235f08c3bdfSopenharmony_ci .mark = FLAGS_DESC(FAN_MARK_FILESYSTEM), 236f08c3bdfSopenharmony_ci .mask = { FAN_ACCESS, "anonymous pipe"}, 237f08c3bdfSopenharmony_ci .pfd = pipes, 238f08c3bdfSopenharmony_ci .expected_errno = EINVAL, 239f08c3bdfSopenharmony_ci }, 240f08c3bdfSopenharmony_ci}; 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_cistatic void do_test(unsigned int number) 243f08c3bdfSopenharmony_ci{ 244f08c3bdfSopenharmony_ci struct test_case_t *tc = &test_cases[number]; 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci tst_res(TINFO, "Test case %d: fanotify_init(%s, O_RDONLY)", number, 247f08c3bdfSopenharmony_ci tc->init.desc); 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_ci if (fan_report_target_fid_unsupported && tc->init.flags & FAN_REPORT_TARGET_FID) { 250f08c3bdfSopenharmony_ci FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_TARGET_FID, 251f08c3bdfSopenharmony_ci fan_report_target_fid_unsupported); 252f08c3bdfSopenharmony_ci return; 253f08c3bdfSopenharmony_ci } 254f08c3bdfSopenharmony_ci 255f08c3bdfSopenharmony_ci if (ignore_mark_unsupported && tc->mark.flags & FAN_MARK_IGNORE) { 256f08c3bdfSopenharmony_ci tst_res(TCONF, "FAN_MARK_IGNORE not supported in kernel?"); 257f08c3bdfSopenharmony_ci return; 258f08c3bdfSopenharmony_ci } 259f08c3bdfSopenharmony_ci 260f08c3bdfSopenharmony_ci if (!tc->mask.flags && tc->expected_errno) { 261f08c3bdfSopenharmony_ci TST_EXP_FAIL(fanotify_init(tc->init.flags, O_RDONLY), 262f08c3bdfSopenharmony_ci tc->expected_errno); 263f08c3bdfSopenharmony_ci } else { 264f08c3bdfSopenharmony_ci TST_EXP_FD(fanotify_init(tc->init.flags, O_RDONLY)); 265f08c3bdfSopenharmony_ci } 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci fanotify_fd = TST_RET; 268f08c3bdfSopenharmony_ci 269f08c3bdfSopenharmony_ci if (fanotify_fd < 0) 270f08c3bdfSopenharmony_ci return; 271f08c3bdfSopenharmony_ci 272f08c3bdfSopenharmony_ci if (!tc->mask.flags) 273f08c3bdfSopenharmony_ci goto out; 274f08c3bdfSopenharmony_ci 275f08c3bdfSopenharmony_ci /* Set mark on non-dir only when expecting error ENOTDIR */ 276f08c3bdfSopenharmony_ci const char *path = tc->expected_errno == ENOTDIR ? FILE1 : MNTPOINT; 277f08c3bdfSopenharmony_ci int dirfd = AT_FDCWD; 278f08c3bdfSopenharmony_ci 279f08c3bdfSopenharmony_ci if (tc->pfd) { 280f08c3bdfSopenharmony_ci dirfd = tc->pfd[0]; 281f08c3bdfSopenharmony_ci path = NULL; 282f08c3bdfSopenharmony_ci } 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing %s with %s", 285f08c3bdfSopenharmony_ci tc->mark.desc, tc->mask.desc); 286f08c3bdfSopenharmony_ci TST_EXP_FD_OR_FAIL(fanotify_mark(fanotify_fd, FAN_MARK_ADD | tc->mark.flags, 287f08c3bdfSopenharmony_ci tc->mask.flags, dirfd, path), 288f08c3bdfSopenharmony_ci tc->expected_errno); 289f08c3bdfSopenharmony_ci 290f08c3bdfSopenharmony_ci /* 291f08c3bdfSopenharmony_ci * ENOTDIR are errors for events/flags not allowed on a non-dir inode. 292f08c3bdfSopenharmony_ci * Try to set an inode mark on a directory and it should succeed. 293f08c3bdfSopenharmony_ci * Try to set directory events in filesystem mark mask on non-dir 294f08c3bdfSopenharmony_ci * and it should succeed. 295f08c3bdfSopenharmony_ci */ 296f08c3bdfSopenharmony_ci if (TST_PASS && tc->expected_errno == ENOTDIR) { 297f08c3bdfSopenharmony_ci SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | tc->mark.flags, 298f08c3bdfSopenharmony_ci tc->mask.flags, AT_FDCWD, MNTPOINT); 299f08c3bdfSopenharmony_ci tst_res(TPASS, 300f08c3bdfSopenharmony_ci "Adding an inode mark on directory did not fail with " 301f08c3bdfSopenharmony_ci "ENOTDIR error as on non-dir inode"); 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_ci if (!(tc->mark.flags & FAN_MARK_ONLYDIR)) { 304f08c3bdfSopenharmony_ci SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | tc->mark.flags | 305f08c3bdfSopenharmony_ci FAN_MARK_FILESYSTEM, tc->mask.flags, 306f08c3bdfSopenharmony_ci AT_FDCWD, FILE1); 307f08c3bdfSopenharmony_ci tst_res(TPASS, 308f08c3bdfSopenharmony_ci "Adding a filesystem mark on non-dir did not fail with " 309f08c3bdfSopenharmony_ci "ENOTDIR error as with an inode mark"); 310f08c3bdfSopenharmony_ci } 311f08c3bdfSopenharmony_ci } 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ciout: 314f08c3bdfSopenharmony_ci if (fanotify_fd > 0) 315f08c3bdfSopenharmony_ci SAFE_CLOSE(fanotify_fd); 316f08c3bdfSopenharmony_ci} 317f08c3bdfSopenharmony_ci 318f08c3bdfSopenharmony_cistatic void do_setup(void) 319f08c3bdfSopenharmony_ci{ 320f08c3bdfSopenharmony_ci /* Require FAN_REPORT_FID support for all tests to simplify per test case requirements */ 321f08c3bdfSopenharmony_ci REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, MNTPOINT); 322f08c3bdfSopenharmony_ci 323f08c3bdfSopenharmony_ci fan_report_target_fid_unsupported = 324f08c3bdfSopenharmony_ci fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME_TARGET, MNTPOINT); 325f08c3bdfSopenharmony_ci ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV); 326f08c3bdfSopenharmony_ci 327f08c3bdfSopenharmony_ci /* Create temporary test file to place marks on */ 328f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(FILE1, "0"); 329f08c3bdfSopenharmony_ci /* Create anonymous pipes to place marks on */ 330f08c3bdfSopenharmony_ci SAFE_PIPE2(pipes, O_CLOEXEC); 331f08c3bdfSopenharmony_ci} 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_cistatic void do_cleanup(void) 334f08c3bdfSopenharmony_ci{ 335f08c3bdfSopenharmony_ci if (fanotify_fd > 0) 336f08c3bdfSopenharmony_ci SAFE_CLOSE(fanotify_fd); 337f08c3bdfSopenharmony_ci if (pipes[0] != -1) 338f08c3bdfSopenharmony_ci SAFE_CLOSE(pipes[0]); 339f08c3bdfSopenharmony_ci if (pipes[1] != -1) 340f08c3bdfSopenharmony_ci SAFE_CLOSE(pipes[1]); 341f08c3bdfSopenharmony_ci} 342f08c3bdfSopenharmony_ci 343f08c3bdfSopenharmony_cistatic struct tst_test test = { 344f08c3bdfSopenharmony_ci .needs_root = 1, 345f08c3bdfSopenharmony_ci .test = do_test, 346f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(test_cases), 347f08c3bdfSopenharmony_ci .setup = do_setup, 348f08c3bdfSopenharmony_ci .cleanup = do_cleanup, 349f08c3bdfSopenharmony_ci .mount_device = 1, 350f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 351f08c3bdfSopenharmony_ci .all_filesystems = 1, 352f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 353f08c3bdfSopenharmony_ci {"linux-git", "ceaf69f8eadc"}, 354f08c3bdfSopenharmony_ci {"linux-git", "8698e3bab4dd"}, 355f08c3bdfSopenharmony_ci {"linux-git", "69562eb0bd3e"}, 356f08c3bdfSopenharmony_ci {} 357f08c3bdfSopenharmony_ci } 358f08c3bdfSopenharmony_ci}; 359f08c3bdfSopenharmony_ci 360f08c3bdfSopenharmony_ci#else 361f08c3bdfSopenharmony_ci TST_TEST_TCONF("System does not have required fanotify support"); 362f08c3bdfSopenharmony_ci#endif 363