• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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