1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2021 Google. All Rights Reserved.
4 *
5 * Started by Matthew Bobrowski <repnop@google.com>
6 */
7
8 /*\
9 * [Description]
10 *
11 * This source file contains a test case which ensures that the fanotify API
12 * returns an expected error code when provided an invalid initialization flag
13 * alongside FAN_REPORT_PIDFD. Additionally, it checks that the operability with
14 * existing FAN_REPORT_* flags is maintained and functioning as intended.
15 *
16 * NOTE: FAN_REPORT_PIDFD support was added in v5.15-rc1 in af579beb666a
17 * ("fanotify: add pidfd support to the fanotify API").
18 */
19
20 #define _GNU_SOURCE
21 #include "tst_test.h"
22 #include <errno.h>
23
24 #ifdef HAVE_SYS_FANOTIFY_H
25 #include "fanotify.h"
26
27 #define MOUNT_PATH "fs_mnt"
28
29 static int fanotify_fd;
30
31 static struct test_case_t {
32 char *name;
33 unsigned int init_flags;
34 int want_err;
35 int want_errno;
36 } test_cases[] = {
37 {
38 "fail on FAN_REPORT_PIDFD | FAN_REPORT_TID",
39 FAN_REPORT_PIDFD | FAN_REPORT_TID,
40 1,
41 EINVAL,
42 },
43 {
44 "pass on FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME",
45 FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME,
46 0,
47 0,
48 },
49 };
50
do_setup(void)51 static void do_setup(void)
52 {
53 /*
54 * An explicit check for FAN_REPORT_PIDFD is performed early on in the
55 * test initialization as it's a prerequisite for all test cases.
56 */
57 REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(FAN_REPORT_PIDFD);
58 }
59
do_test(unsigned int num)60 static void do_test(unsigned int num)
61 {
62 struct test_case_t *tc = &test_cases[num];
63
64 tst_res(TINFO, "Test #%d: %s", num, tc->name);
65
66 fanotify_fd = fanotify_init(tc->init_flags, O_RDONLY);
67 if (fanotify_fd < 0) {
68 if (!tc->want_err) {
69 tst_res(TFAIL,
70 "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) "
71 "failed with error -%d but wanted success",
72 fanotify_fd, tc->init_flags, errno);
73 return;
74 }
75
76 if (errno != tc->want_errno) {
77 tst_res(TFAIL,
78 "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) "
79 "failed with an unexpected error code -%d but "
80 "wanted -%d",
81 fanotify_fd, tc->init_flags,
82 errno, tc->want_errno);
83 return;
84 }
85
86 tst_res(TPASS,
87 "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) "
88 "failed with error -%d as expected",
89 fanotify_fd, tc->init_flags, errno);
90 return;
91 }
92
93 /*
94 * Catch test cases that had expected to receive an error upon calling
95 * fanotify_init() but had unexpectedly resulted in a success.
96 */
97 if (tc->want_err) {
98 tst_res(TFAIL,
99 "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) "
100 "unexpectedly returned successfully, wanted error -%d",
101 fanotify_fd, tc->init_flags, tc->want_errno);
102 return;
103 }
104
105 tst_res(TPASS,
106 "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) "
107 "successfully initialized notification group",
108 fanotify_fd, tc->init_flags);
109
110 SAFE_CLOSE(fanotify_fd);
111 }
112
do_cleanup(void)113 static void do_cleanup(void)
114 {
115 if (fanotify_fd >= 0)
116 SAFE_CLOSE(fanotify_fd);
117 }
118
119 static struct tst_test test = {
120 .setup = do_setup,
121 .test = do_test,
122 .tcnt = ARRAY_SIZE(test_cases),
123 .cleanup = do_cleanup,
124 .all_filesystems = 1,
125 .needs_root = 1,
126 .mntpoint = MOUNT_PATH,
127 };
128
129 #else
130 TST_TEST_TCONF("system doesn't have required fanotify support");
131 #endif /* HAVE_SYS_FANOTIFY_H */
132