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 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 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 */ 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 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 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 */ 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))) 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 */ 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 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 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(sizeof(struct initramfs_test_bufs), GFP_KERNEL); 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 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. */ 579 static int __init initramfs_test_init(struct kunit *test) 580 { 581 test->priv = __override_init_fs(); 582 return 0; 583 } 584 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