1 // SPDX-License-Identifier: GPL-2.0
2 #include <kunit/test.h>
3 #include <linux/fcntl.h>
4 #include <linux/file.h>
5 #include <linux/fs.h>
6 #include <linux/fs_struct.h>
7 #include <linux/init.h>
8 #include <linux/init_syscalls.h>
9 #include <linux/initrd.h>
10 #include <linux/stringify.h>
11 #include <linux/timekeeping.h>
12 #include "initramfs_internal.h"
13
14 struct initramfs_test_cpio {
15 char *magic;
16 unsigned int ino;
17 unsigned int mode;
18 unsigned int uid;
19 unsigned int gid;
20 unsigned int nlink;
21 unsigned int mtime;
22 unsigned int filesize;
23 unsigned int devmajor;
24 unsigned int devminor;
25 unsigned int rdevmajor;
26 unsigned int rdevminor;
27 unsigned int namesize;
28 unsigned int csum;
29 char *fname;
30 char *data;
31 };
32
33 /* regular newc header format */
34 #define CPIO_HDR_FMT "%s%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%s"
35 /*
36 * Bogus newc header with "0x" prefixes on the uid, gid, and namesize values.
37 * parse_header()/simple_str[n]toul() accepted this, contrary to the initramfs
38 * specification. hex2bin() now fails.
39 */
40 #define CPIO_HDR_OX_INJECT \
41 "%s%08x%08x0x%06x0X%06x%08x%08x%08x%08x%08x%08x%08x0x%06x%08x%s"
42
fill_cpio(struct initramfs_test_cpio * cs,size_t csz,bool inject_ox,char * out)43 static size_t fill_cpio(struct initramfs_test_cpio *cs, size_t csz,
44 bool inject_ox, char *out)
45 {
46 int i;
47 size_t off = 0;
48
49 for (i = 0; i < csz; i++) {
50 char *pos = &out[off];
51 struct initramfs_test_cpio *c = &cs[i];
52 size_t thislen;
53
54 /* +1 to account for nulterm */
55 thislen = sprintf(pos,
56 inject_ox ? CPIO_HDR_OX_INJECT : CPIO_HDR_FMT,
57 c->magic, c->ino, c->mode, c->uid, c->gid, c->nlink,
58 c->mtime, c->filesize, c->devmajor, c->devminor,
59 c->rdevmajor, c->rdevminor, c->namesize, c->csum,
60 c->fname) + 1;
61
62 pr_debug("packing (%zu): %.*s\n", thislen, (int)thislen, pos);
63 if (thislen != CPIO_HDRLEN + c->namesize)
64 pr_debug("padded to: %u\n", CPIO_HDRLEN + c->namesize);
65 off += CPIO_HDRLEN + c->namesize;
66 while (off & 3)
67 out[off++] = '\0';
68
69 memcpy(&out[off], c->data, c->filesize);
70 off += c->filesize;
71 while (off & 3)
72 out[off++] = '\0';
73 }
74
75 return off;
76 }
77
initramfs_test_extract(struct kunit * test)78 static void __init initramfs_test_extract(struct kunit *test)
79 {
80 char *err, *cpio_srcbuf;
81 size_t len;
82 struct timespec64 ts_before, ts_after;
83 struct kstat st = {};
84 struct initramfs_test_cpio c[] = { {
85 .magic = "070701",
86 .ino = 1,
87 .mode = S_IFREG | 0777,
88 .uid = 12,
89 .gid = 34,
90 .nlink = 1,
91 .mtime = 56,
92 .filesize = 0,
93 .devmajor = 0,
94 .devminor = 1,
95 .rdevmajor = 0,
96 .rdevminor = 0,
97 .namesize = sizeof("initramfs_test_extract"),
98 .csum = 0,
99 .fname = "initramfs_test_extract",
100 }, {
101 .magic = "070701",
102 .ino = 2,
103 .mode = S_IFDIR | 0777,
104 .nlink = 1,
105 .mtime = 57,
106 .devminor = 1,
107 .namesize = sizeof("initramfs_test_extract_dir"),
108 .fname = "initramfs_test_extract_dir",
109 }, {
110 .magic = "070701",
111 .namesize = sizeof("TRAILER!!!"),
112 .fname = "TRAILER!!!",
113 } };
114
115 /* +3 to cater for any 4-byte end-alignment */
116 cpio_srcbuf = kzalloc(ARRAY_SIZE(c) * (CPIO_HDRLEN + PATH_MAX + 3),
117 GFP_KERNEL);
118 len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
119
120 ktime_get_real_ts64(&ts_before);
121 err = unpack_to_rootfs(cpio_srcbuf, len);
122 ktime_get_real_ts64(&ts_after);
123 if (err) {
124 KUNIT_FAIL(test, "unpack failed %s", err);
125 goto out;
126 }
127
128 KUNIT_EXPECT_EQ(test, init_stat(c[0].fname, &st, 0), 0);
129 KUNIT_EXPECT_TRUE(test, S_ISREG(st.mode));
130 KUNIT_EXPECT_TRUE(test, uid_eq(st.uid, KUIDT_INIT(c[0].uid)));
131 KUNIT_EXPECT_TRUE(test, gid_eq(st.gid, KGIDT_INIT(c[0].gid)));
132 KUNIT_EXPECT_EQ(test, st.nlink, 1);
133 if (IS_ENABLED(CONFIG_INITRAMFS_PRESERVE_MTIME)) {
134 KUNIT_EXPECT_EQ(test, st.mtime.tv_sec, c[0].mtime);
135 } else {
136 KUNIT_EXPECT_GE(test, st.mtime.tv_sec, ts_before.tv_sec);
137 KUNIT_EXPECT_LE(test, st.mtime.tv_sec, ts_after.tv_sec);
138 }
139 KUNIT_EXPECT_EQ(test, st.blocks, c[0].filesize);
140
141 KUNIT_EXPECT_EQ(test, init_stat(c[1].fname, &st, 0), 0);
142 KUNIT_EXPECT_TRUE(test, S_ISDIR(st.mode));
143 if (IS_ENABLED(CONFIG_INITRAMFS_PRESERVE_MTIME)) {
144 KUNIT_EXPECT_EQ(test, st.mtime.tv_sec, c[1].mtime);
145 } else {
146 KUNIT_EXPECT_GE(test, st.mtime.tv_sec, ts_before.tv_sec);
147 KUNIT_EXPECT_LE(test, st.mtime.tv_sec, ts_after.tv_sec);
148 }
149
150 KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0);
151 KUNIT_EXPECT_EQ(test, init_rmdir(c[1].fname), 0);
152 out:
153 kfree(cpio_srcbuf);
154 }
155
156 /*
157 * Don't terminate filename. Previously, the cpio filename field was passed
158 * directly to filp_open(collected, O_CREAT|..) without nulterm checks. See
159 * https://lore.kernel.org/linux-fsdevel/20241030035509.20194-2-ddiss@suse.de
160 */
initramfs_test_fname_overrun(struct kunit * test)161 static void __init initramfs_test_fname_overrun(struct kunit *test)
162 {
163 char *err, *cpio_srcbuf;
164 size_t len, suffix_off;
165 struct initramfs_test_cpio c[] = { {
166 .magic = "070701",
167 .ino = 1,
168 .mode = S_IFREG | 0777,
169 .uid = 0,
170 .gid = 0,
171 .nlink = 1,
172 .mtime = 1,
173 .filesize = 0,
174 .devmajor = 0,
175 .devminor = 1,
176 .rdevmajor = 0,
177 .rdevminor = 0,
178 .namesize = sizeof("initramfs_test_fname_overrun"),
179 .csum = 0,
180 .fname = "initramfs_test_fname_overrun",
181 } };
182
183 /*
184 * poison cpio source buffer, so we can detect overrun. source
185 * buffer is used by read_into() when hdr or fname
186 * are already available (e.g. no compression).
187 */
188 cpio_srcbuf = kmalloc(CPIO_HDRLEN + PATH_MAX + 3, GFP_KERNEL);
189 memset(cpio_srcbuf, 'B', CPIO_HDRLEN + PATH_MAX + 3);
190 /* limit overrun to avoid crashes / filp_open() ENAMETOOLONG */
191 cpio_srcbuf[CPIO_HDRLEN + strlen(c[0].fname) + 20] = '\0';
192
193 len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
194 /* overwrite trailing fname terminator and padding */
195 suffix_off = len - 1;
196 while (cpio_srcbuf[suffix_off] == '\0') {
197 cpio_srcbuf[suffix_off] = 'P';
198 suffix_off--;
199 }
200
201 err = unpack_to_rootfs(cpio_srcbuf, len);
202 KUNIT_EXPECT_NOT_NULL(test, err);
203
204 kfree(cpio_srcbuf);
205 }
206
initramfs_test_data(struct kunit * test)207 static void __init initramfs_test_data(struct kunit *test)
208 {
209 char *err, *cpio_srcbuf;
210 size_t len;
211 struct file *file;
212 struct initramfs_test_cpio c[] = { {
213 .magic = "070701",
214 .ino = 1,
215 .mode = S_IFREG | 0777,
216 .uid = 0,
217 .gid = 0,
218 .nlink = 1,
219 .mtime = 1,
220 .filesize = sizeof("ASDF") - 1,
221 .devmajor = 0,
222 .devminor = 1,
223 .rdevmajor = 0,
224 .rdevminor = 0,
225 .namesize = sizeof("initramfs_test_data"),
226 .csum = 0,
227 .fname = "initramfs_test_data",
228 .data = "ASDF",
229 } };
230
231 /* +6 for max name and data 4-byte padding */
232 cpio_srcbuf = kmalloc(CPIO_HDRLEN + c[0].namesize + c[0].filesize + 6,
233 GFP_KERNEL);
234
235 len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
236
237 err = unpack_to_rootfs(cpio_srcbuf, len);
238 KUNIT_EXPECT_NULL(test, err);
239
240 file = filp_open(c[0].fname, O_RDONLY, 0);
241 if (IS_ERR(file)) {
242 KUNIT_FAIL(test, "open failed");
243 goto out;
244 }
245
246 /* read back file contents into @cpio_srcbuf and confirm match */
247 len = kernel_read(file, cpio_srcbuf, c[0].filesize, NULL);
248 KUNIT_EXPECT_EQ(test, len, c[0].filesize);
249 KUNIT_EXPECT_MEMEQ(test, cpio_srcbuf, c[0].data, len);
250
251 fput(file);
252 KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0);
253 out:
254 kfree(cpio_srcbuf);
255 }
256
initramfs_test_csum(struct kunit * test)257 static void __init initramfs_test_csum(struct kunit *test)
258 {
259 char *err, *cpio_srcbuf;
260 size_t len;
261 struct initramfs_test_cpio c[] = { {
262 /* 070702 magic indicates a valid csum is present */
263 .magic = "070702",
264 .ino = 1,
265 .mode = S_IFREG | 0777,
266 .nlink = 1,
267 .filesize = sizeof("ASDF") - 1,
268 .devminor = 1,
269 .namesize = sizeof("initramfs_test_csum"),
270 .csum = 'A' + 'S' + 'D' + 'F',
271 .fname = "initramfs_test_csum",
272 .data = "ASDF",
273 }, {
274 /* mix csum entry above with no-csum entry below */
275 .magic = "070701",
276 .ino = 2,
277 .mode = S_IFREG | 0777,
278 .nlink = 1,
279 .filesize = sizeof("ASDF") - 1,
280 .devminor = 1,
281 .namesize = sizeof("initramfs_test_csum_not_here"),
282 /* csum ignored */
283 .csum = 5555,
284 .fname = "initramfs_test_csum_not_here",
285 .data = "ASDF",
286 } };
287
288 cpio_srcbuf = kmalloc(8192, GFP_KERNEL);
289
290 len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
291
292 err = unpack_to_rootfs(cpio_srcbuf, len);
293 KUNIT_EXPECT_NULL(test, err);
294
295 KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0);
296 KUNIT_EXPECT_EQ(test, init_unlink(c[1].fname), 0);
297
298 /* mess up the csum and confirm that unpack fails */
299 c[0].csum--;
300 len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
301
302 err = unpack_to_rootfs(cpio_srcbuf, len);
303 KUNIT_EXPECT_NOT_NULL(test, err);
304
305 /*
306 * file (with content) is still retained in case of bad-csum abort.
307 * Perhaps we should change this.
308 */
309 KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0);
310 KUNIT_EXPECT_EQ(test, init_unlink(c[1].fname), -ENOENT);
311 kfree(cpio_srcbuf);
312 }
313
314 /*
315 * hardlink hashtable may leak when the archive omits a trailer:
316 * https://lore.kernel.org/r/20241107002044.16477-10-ddiss@suse.de/
317 */
initramfs_test_hardlink(struct kunit * test)318 static void __init initramfs_test_hardlink(struct kunit *test)
319 {
320 char *err, *cpio_srcbuf;
321 size_t len;
322 struct kstat st0 = {}, st1 = {};
323 struct initramfs_test_cpio c[] = { {
324 .magic = "070701",
325 .ino = 1,
326 .mode = S_IFREG | 0777,
327 .nlink = 2,
328 .devminor = 1,
329 .namesize = sizeof("initramfs_test_hardlink"),
330 .fname = "initramfs_test_hardlink",
331 }, {
332 /* hardlink data is present in last archive entry */
333 .magic = "070701",
334 .ino = 1,
335 .mode = S_IFREG | 0777,
336 .nlink = 2,
337 .filesize = sizeof("ASDF") - 1,
338 .devminor = 1,
339 .namesize = sizeof("initramfs_test_hardlink_link"),
340 .fname = "initramfs_test_hardlink_link",
341 .data = "ASDF",
342 } };
343
344 cpio_srcbuf = kmalloc(8192, GFP_KERNEL);
345
346 len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
347
348 err = unpack_to_rootfs(cpio_srcbuf, len);
349 KUNIT_EXPECT_NULL(test, err);
350
351 KUNIT_EXPECT_EQ(test, init_stat(c[0].fname, &st0, 0), 0);
352 KUNIT_EXPECT_EQ(test, init_stat(c[1].fname, &st1, 0), 0);
353 KUNIT_EXPECT_EQ(test, st0.ino, st1.ino);
354 KUNIT_EXPECT_EQ(test, st0.nlink, 2);
355 KUNIT_EXPECT_EQ(test, st1.nlink, 2);
356
357 KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0);
358 KUNIT_EXPECT_EQ(test, init_unlink(c[1].fname), 0);
359
360 kfree(cpio_srcbuf);
361 }
362
363 #define INITRAMFS_TEST_MANY_LIMIT 1000
364 #define INITRAMFS_TEST_MANY_PATH_MAX (sizeof("initramfs_test_many-") \
365 + sizeof(__stringify(INITRAMFS_TEST_MANY_LIMIT)))
initramfs_test_many(struct kunit * test)366 static void __init initramfs_test_many(struct kunit *test)
367 {
368 char *err, *cpio_srcbuf, *p;
369 size_t len = INITRAMFS_TEST_MANY_LIMIT *
370 (CPIO_HDRLEN + INITRAMFS_TEST_MANY_PATH_MAX + 3);
371 char thispath[INITRAMFS_TEST_MANY_PATH_MAX];
372 int i;
373
374 p = cpio_srcbuf = kmalloc(len, GFP_KERNEL);
375
376 for (i = 0; i < INITRAMFS_TEST_MANY_LIMIT; i++) {
377 struct initramfs_test_cpio c = {
378 .magic = "070701",
379 .ino = i,
380 .mode = S_IFREG | 0777,
381 .nlink = 1,
382 .devminor = 1,
383 .fname = thispath,
384 };
385
386 c.namesize = 1 + sprintf(thispath, "initramfs_test_many-%d", i);
387 p += fill_cpio(&c, 1, false, p);
388 }
389
390 len = p - cpio_srcbuf;
391 err = unpack_to_rootfs(cpio_srcbuf, len);
392 KUNIT_EXPECT_NULL(test, err);
393
394 for (i = 0; i < INITRAMFS_TEST_MANY_LIMIT; i++) {
395 sprintf(thispath, "initramfs_test_many-%d", i);
396 KUNIT_EXPECT_EQ(test, init_unlink(thispath), 0);
397 }
398
399 kfree(cpio_srcbuf);
400 }
401
402 /*
403 * An initramfs filename is namesize in length, including the zero-terminator.
404 * A filename can be zero-terminated prior to namesize, with the remainder used
405 * as padding. This can be useful for e.g. alignment of file data segments with
406 * a 4KB filesystem block, allowing for extent sharing (reflinks) between cpio
407 * source and destination. This hack works with both GNU cpio and initramfs, as
408 * long as PATH_MAX isn't exceeded.
409 */
initramfs_test_fname_pad(struct kunit * test)410 static void __init initramfs_test_fname_pad(struct kunit *test)
411 {
412 char *err;
413 size_t len;
414 struct file *file;
415 char fdata[] = "this file data is aligned at 4K in the archive";
416 struct test_fname_pad {
417 char padded_fname[4096 - CPIO_HDRLEN];
418 char cpio_srcbuf[CPIO_HDRLEN + PATH_MAX + 3 + sizeof(fdata)];
419 } *tbufs = kzalloc_obj(struct test_fname_pad);
420 struct initramfs_test_cpio c[] = { {
421 .magic = "070701",
422 .ino = 1,
423 .mode = S_IFREG | 0777,
424 .uid = 0,
425 .gid = 0,
426 .nlink = 1,
427 .mtime = 1,
428 .filesize = sizeof(fdata),
429 .devmajor = 0,
430 .devminor = 1,
431 .rdevmajor = 0,
432 .rdevminor = 0,
433 /* align file data at 4K archive offset via padded fname */
434 .namesize = 4096 - CPIO_HDRLEN,
435 .csum = 0,
436 .fname = tbufs->padded_fname,
437 .data = fdata,
438 } };
439
440 memcpy(tbufs->padded_fname, "padded_fname", sizeof("padded_fname"));
441 len = fill_cpio(c, ARRAY_SIZE(c), false, tbufs->cpio_srcbuf);
442
443 err = unpack_to_rootfs(tbufs->cpio_srcbuf, len);
444 KUNIT_EXPECT_NULL(test, err);
445
446 file = filp_open(c[0].fname, O_RDONLY, 0);
447 if (IS_ERR(file)) {
448 KUNIT_FAIL(test, "open failed");
449 goto out;
450 }
451
452 /* read back file contents into @cpio_srcbuf and confirm match */
453 len = kernel_read(file, tbufs->cpio_srcbuf, c[0].filesize, NULL);
454 KUNIT_EXPECT_EQ(test, len, c[0].filesize);
455 KUNIT_EXPECT_MEMEQ(test, tbufs->cpio_srcbuf, c[0].data, len);
456
457 fput(file);
458 KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0);
459 out:
460 kfree(tbufs);
461 }
462
initramfs_test_fname_path_max(struct kunit * test)463 static void __init initramfs_test_fname_path_max(struct kunit *test)
464 {
465 char *err;
466 size_t len;
467 struct kstat st0 = {}, st1 = {};
468 char fdata[] = "this file data will not be unpacked";
469 struct test_fname_path_max {
470 char fname_oversize[PATH_MAX + 1];
471 char fname_ok[PATH_MAX];
472 char cpio_src[(CPIO_HDRLEN + PATH_MAX + 3 + sizeof(fdata)) * 2];
473 } *tbufs = kzalloc_obj(struct test_fname_path_max);
474 struct initramfs_test_cpio c[] = { {
475 .magic = "070701",
476 .ino = 1,
477 .mode = S_IFDIR | 0777,
478 .nlink = 1,
479 .namesize = sizeof(tbufs->fname_oversize),
480 .fname = tbufs->fname_oversize,
481 .filesize = sizeof(fdata),
482 .data = fdata,
483 }, {
484 .magic = "070701",
485 .ino = 2,
486 .mode = S_IFDIR | 0777,
487 .nlink = 1,
488 .namesize = sizeof(tbufs->fname_ok),
489 .fname = tbufs->fname_ok,
490 } };
491
492 memset(tbufs->fname_oversize, '/', sizeof(tbufs->fname_oversize) - 1);
493 memset(tbufs->fname_ok, '/', sizeof(tbufs->fname_ok) - 1);
494 memcpy(tbufs->fname_oversize, "fname_oversize",
495 sizeof("fname_oversize") - 1);
496 memcpy(tbufs->fname_ok, "fname_ok", sizeof("fname_ok") - 1);
497 len = fill_cpio(c, ARRAY_SIZE(c), false, tbufs->cpio_src);
498
499 /* unpack skips over fname_oversize instead of returning an error */
500 err = unpack_to_rootfs(tbufs->cpio_src, len);
501 KUNIT_EXPECT_NULL(test, err);
502
503 KUNIT_EXPECT_EQ(test, init_stat("fname_oversize", &st0, 0), -ENOENT);
504 KUNIT_EXPECT_EQ(test, init_stat("fname_ok", &st1, 0), 0);
505 KUNIT_EXPECT_EQ(test, init_rmdir("fname_ok"), 0);
506
507 kfree(tbufs);
508 }
509
initramfs_test_hdr_hex(struct kunit * test)510 static void __init initramfs_test_hdr_hex(struct kunit *test)
511 {
512 char *err;
513 size_t len;
514 char fdata[] = "this file data will not be unpacked";
515 struct initramfs_test_bufs {
516 char cpio_src[(CPIO_HDRLEN + PATH_MAX + 3 + sizeof(fdata)) * 2];
517 } *tbufs = kzalloc_obj(struct initramfs_test_bufs);
518 struct initramfs_test_cpio c[] = { {
519 .magic = "070701",
520 .ino = 1,
521 .mode = S_IFREG | 0777,
522 .uid = 0x123456,
523 .gid = 0x123457,
524 .nlink = 1,
525 .namesize = sizeof("initramfs_test_hdr_hex_0"),
526 .fname = "initramfs_test_hdr_hex_0",
527 .filesize = sizeof(fdata),
528 .data = fdata,
529 }, {
530 .magic = "070701",
531 .ino = 2,
532 .mode = S_IFDIR | 0777,
533 .uid = 0x000056,
534 .gid = 0x000057,
535 .nlink = 1,
536 .namesize = sizeof("initramfs_test_hdr_hex_1"),
537 .fname = "initramfs_test_hdr_hex_1",
538 } };
539
540 /* inject_ox=true to add "0x" cpio field prefixes */
541 len = fill_cpio(c, ARRAY_SIZE(c), true, tbufs->cpio_src);
542
543 err = unpack_to_rootfs(tbufs->cpio_src, len);
544 KUNIT_EXPECT_NOT_NULL(test, err);
545
546 kfree(tbufs);
547 }
548
549 /*
550 * The kunit_case/_suite struct cannot be marked as __initdata as this will be
551 * used in debugfs to retrieve results after test has run.
552 */
553 static struct kunit_case __refdata initramfs_test_cases[] = {
554 KUNIT_CASE(initramfs_test_extract),
555 KUNIT_CASE(initramfs_test_fname_overrun),
556 KUNIT_CASE(initramfs_test_data),
557 KUNIT_CASE(initramfs_test_csum),
558 KUNIT_CASE(initramfs_test_hardlink),
559 KUNIT_CASE(initramfs_test_many),
560 KUNIT_CASE(initramfs_test_fname_pad),
561 KUNIT_CASE(initramfs_test_fname_path_max),
562 KUNIT_CASE(initramfs_test_hdr_hex),
563 {},
564 };
565
initramfs_suite_init(struct kunit_suite * suite)566 static int __init initramfs_suite_init(struct kunit_suite *suite)
567 {
568 /*
569 * unpack_to_rootfs() uses module-static state (victim, byte_count,
570 * state, ...). The boot-time async do_populate_rootfs() may still be
571 * running, so wait for it to finish before we call unpack_to_rootfs()
572 * from the test thread, otherwise the two writers race and crash.
573 */
574 wait_for_initramfs();
575 return 0;
576 }
577
578 /* Tests run in a nullfs kthread; always use the init fs for path resolution. */
initramfs_test_init(struct kunit * test)579 static int __init initramfs_test_init(struct kunit *test)
580 {
581 test->priv = __override_init_fs();
582 return 0;
583 }
584
initramfs_test_exit(struct kunit * test)585 static void __init initramfs_test_exit(struct kunit *test)
586 {
587 __revert_init_fs(test->priv);
588 }
589
590 static struct kunit_suite __refdata initramfs_test_suite = {
591 .name = "initramfs",
592 .suite_init = initramfs_suite_init,
593 .init = initramfs_test_init,
594 .exit = initramfs_test_exit,
595 .test_cases = initramfs_test_cases,
596 };
597 kunit_test_init_section_suites(&initramfs_test_suite);
598
599 MODULE_DESCRIPTION("Initramfs KUnit test suite");
600 MODULE_LICENSE("GPL v2");
601