1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Linux Test Project, 2017-2020
4 * Copyright (C) 2017 Red Hat, Inc.
5 */
6
7 /*
8 * Based on Linux/tools/testing/selftests/memfd/memfd_test.c
9 * by David Herrmann <dh.herrmann@gmail.com>
10 *
11 * 24/02/2017 Port to LTP <jracek@redhat.com>
12 */
13
14 #define _GNU_SOURCE
15
16 #include <errno.h>
17 #include "tst_test.h"
18 #include "memfd_create_common.h"
19
20 /*
21 * Do few basic sealing tests to see whether setting/retrieving seals works.
22 */
test_basic(int fd)23 static void test_basic(int fd)
24 {
25 /* add basic seals */
26 CHECK_MFD_HAS_SEALS(fd, 0);
27 CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
28 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
29
30 /* add them again */
31 CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
32 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
33
34 /* add more seals and seal against sealing */
35 CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW | F_SEAL_SEAL);
36 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW |
37 F_SEAL_WRITE | F_SEAL_SEAL);
38
39 /* verify that sealing no longer works */
40 CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
41 CHECK_MFD_FAIL_ADD_SEALS(fd, 0);
42 }
43
44 /*
45 * Verify that no sealing is possible when memfd is created without
46 * MFD_ALLOW_SEALING flag.
47 */
test_no_sealing_without_flag(int fd)48 static void test_no_sealing_without_flag(int fd)
49 {
50 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SEAL);
51 CHECK_MFD_FAIL_ADD_SEALS(fd,
52 F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
53 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SEAL);
54 }
55
56 /*
57 * Test SEAL_WRITE
58 * Test whether SEAL_WRITE actually prevents modifications.
59 */
test_seal_write(int fd)60 static void test_seal_write(int fd)
61 {
62 CHECK_MFD_HAS_SEALS(fd, 0);
63 CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
64 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
65
66 CHECK_MFD_READABLE(fd);
67 CHECK_MFD_NON_WRITEABLE(fd);
68 CHECK_MFD_SHRINKABLE(fd);
69 CHECK_MFD_GROWABLE(fd);
70 CHECK_MFD_NON_GROWABLE_BY_WRITE(fd);
71 }
72
73 /*
74 * Test SEAL_SHRINK
75 * Test whether SEAL_SHRINK actually prevents shrinking
76 */
test_seal_shrink(int fd)77 static void test_seal_shrink(int fd)
78 {
79 CHECK_MFD_HAS_SEALS(fd, 0);
80 CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
81 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK);
82
83 CHECK_MFD_READABLE(fd);
84 CHECK_MFD_WRITEABLE(fd);
85 CHECK_MFD_NON_SHRINKABLE(fd);
86 CHECK_MFD_GROWABLE(fd);
87 CHECK_MFD_GROWABLE_BY_WRITE(fd);
88 }
89
90 /*
91 * Test SEAL_GROW
92 * Test whether SEAL_GROW actually prevents growing
93 */
test_seal_grow(int fd)94 static void test_seal_grow(int fd)
95 {
96 CHECK_MFD_HAS_SEALS(fd, 0);
97 CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW);
98 CHECK_MFD_HAS_SEALS(fd, F_SEAL_GROW);
99
100 CHECK_MFD_READABLE(fd);
101 CHECK_MFD_WRITEABLE(fd);
102 CHECK_MFD_SHRINKABLE(fd);
103 CHECK_MFD_NON_GROWABLE(fd);
104 CHECK_MFD_NON_GROWABLE_BY_WRITE(fd);
105 }
106
107 /*
108 * Test SEAL_SHRINK | SEAL_GROW
109 * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
110 */
test_seal_resize(int fd)111 static void test_seal_resize(int fd)
112 {
113 CHECK_MFD_HAS_SEALS(fd, 0);
114 CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
115 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
116
117 CHECK_MFD_READABLE(fd);
118 CHECK_MFD_WRITEABLE(fd);
119 CHECK_MFD_NON_SHRINKABLE(fd);
120 CHECK_MFD_NON_GROWABLE(fd);
121 CHECK_MFD_NON_GROWABLE_BY_WRITE(fd);
122 }
123
124 /*
125 * Test sharing via dup()
126 * Test that seals are shared between dupped FDs and they're all equal.
127 */
test_share_dup(int fd)128 static void test_share_dup(int fd)
129 {
130 int fd2;
131
132 CHECK_MFD_HAS_SEALS(fd, 0);
133
134 fd2 = SAFE_DUP(fd);
135 CHECK_MFD_HAS_SEALS(fd2, 0);
136
137 CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
138 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
139 CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
140
141 CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
142 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
143 CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
144
145 CHECK_MFD_ADD_SEALS(fd, F_SEAL_SEAL);
146 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
147 CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
148
149 CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
150 CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_GROW);
151 CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
152 CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_SEAL);
153
154 SAFE_CLOSE(fd2);
155
156 CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
157 }
158
159 /*
160 * Test sealing with active mmap()s
161 * Modifying seals is only allowed if no other mmap() refs exist.
162 */
test_share_mmap(int fd)163 static void test_share_mmap(int fd)
164 {
165 void *p;
166
167 CHECK_MFD_HAS_SEALS(fd, 0);
168
169 /* shared/writable ref prevents sealing WRITE, but allows others */
170 p = SAFE_MMAP(NULL, MFD_DEF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
171 fd, 0);
172
173 CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_WRITE);
174 CHECK_MFD_HAS_SEALS(fd, 0);
175 CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
176 CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK);
177 SAFE_MUNMAP(p, MFD_DEF_SIZE);
178
179 /* readable ref allows sealing */
180 p = SAFE_MMAP(NULL, MFD_DEF_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
181 CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
182 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
183 SAFE_MUNMAP(p, MFD_DEF_SIZE);
184 }
185
186 /*
187 * Test sealing with open(/proc/self/fd/%d)
188 * Via /proc we can get access to a separate file-context for the same memfd.
189 * This is *not* like dup(), but like a real separate open(). Make sure the
190 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
191 */
test_share_open(int fd)192 static void test_share_open(int fd)
193 {
194 int fd2;
195
196 CHECK_MFD_HAS_SEALS(fd, 0);
197
198 fd2 = CHECK_MFD_OPEN(fd, O_RDWR, 0);
199 CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
200 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
201 CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
202
203 CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
204 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
205 CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
206
207 SAFE_CLOSE(fd);
208 fd = CHECK_MFD_OPEN(fd2, O_RDONLY, 0);
209
210 CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
211 CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
212 CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
213
214 SAFE_CLOSE(fd2);
215 }
216
217
218 static const struct tcase {
219 int flags;
220 void (*func)(int fd);
221 const char *desc;
222 } tcases[] = {
223 {MFD_ALLOW_SEALING, &test_basic, "Basic tests + set/get seals"},
224 {0, &test_no_sealing_without_flag, "Disabled sealing"},
225
226 {MFD_ALLOW_SEALING, &test_seal_write, "Write seal"},
227 {MFD_ALLOW_SEALING, &test_seal_shrink, "Shrink seal"},
228 {MFD_ALLOW_SEALING, &test_seal_grow, "Grow seal"},
229 {MFD_ALLOW_SEALING, &test_seal_resize, "Resize seal"},
230
231 {MFD_ALLOW_SEALING, &test_share_dup, "Seals shared for dup"},
232 {MFD_ALLOW_SEALING, &test_share_mmap, "Seals shared for mmap"},
233 {MFD_ALLOW_SEALING, &test_share_open, "Seals shared for open"},
234 };
235
verify_memfd_create(unsigned int n)236 static void verify_memfd_create(unsigned int n)
237 {
238 int fd;
239 const struct tcase *tc;
240
241 tc = &tcases[n];
242
243 tst_res(TINFO, "%s", tc->desc);
244
245 fd = CHECK_MFD_NEW("ltp_memfd_create01", MFD_DEF_SIZE, tc->flags);
246
247 tc->func(fd);
248
249 SAFE_CLOSE(fd);
250 }
251
setup(void)252 static void setup(void)
253 {
254 /*
255 * For now, all tests in this file require MFD_ALLOW_SEALING flag
256 * to be implemented, even though that flag isn't always set when
257 * memfd is created. So don't check anything else and TCONF right away
258 * is this flag is missing.
259 */
260 if (!MFD_FLAGS_AVAILABLE(MFD_ALLOW_SEALING)) {
261 tst_brk(TCONF | TERRNO,
262 "memfd_create(%u) not implemented", MFD_ALLOW_SEALING);
263 }
264 }
265
266 static struct tst_test test = {
267 .test = verify_memfd_create,
268 .tcnt = ARRAY_SIZE(tcases),
269 .setup = setup,
270 };
271