Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

initramfs_test: add filename padding test case

Confirm that cpio filenames with multiple trailing zeros (accounted for
in namesize) extract successfully.

Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Nicolas Schier <nsc@kernel.org>
Link: https://lore.kernel.org/r/20250819032607.28727-9-ddiss@suse.de
[nathan: Fix duplicate filesize initialization, reported at
https://lore.kernel.org/202508200304.wF1u78il-lkp@intel.com/]
Signed-off-by: Nathan Chancellor <nathan@kernel.org>

authored by

David Disseldorp and committed by
Nathan Chancellor
6da752f5 5467e855

+66 -1
+66 -1
init/initramfs_test.c
··· 45 45 c->mtime, c->filesize, c->devmajor, c->devminor, 46 46 c->rdevmajor, c->rdevminor, c->namesize, c->csum, 47 47 c->fname) + 1; 48 + 48 49 pr_debug("packing (%zu): %.*s\n", thislen, (int)thislen, pos); 49 - off += thislen; 50 + if (thislen != CPIO_HDRLEN + c->namesize) 51 + pr_debug("padded to: %u\n", CPIO_HDRLEN + c->namesize); 52 + off += CPIO_HDRLEN + c->namesize; 50 53 while (off & 3) 51 54 out[off++] = '\0'; 52 55 ··· 387 384 } 388 385 389 386 /* 387 + * An initramfs filename is namesize in length, including the zero-terminator. 388 + * A filename can be zero-terminated prior to namesize, with the remainder used 389 + * as padding. This can be useful for e.g. alignment of file data segments with 390 + * a 4KB filesystem block, allowing for extent sharing (reflinks) between cpio 391 + * source and destination. This hack works with both GNU cpio and initramfs, as 392 + * long as PATH_MAX isn't exceeded. 393 + */ 394 + static void __init initramfs_test_fname_pad(struct kunit *test) 395 + { 396 + char *err; 397 + size_t len; 398 + struct file *file; 399 + char fdata[] = "this file data is aligned at 4K in the archive"; 400 + struct test_fname_pad { 401 + char padded_fname[4096 - CPIO_HDRLEN]; 402 + char cpio_srcbuf[CPIO_HDRLEN + PATH_MAX + 3 + sizeof(fdata)]; 403 + } *tbufs = kzalloc(sizeof(struct test_fname_pad), GFP_KERNEL); 404 + struct initramfs_test_cpio c[] = { { 405 + .magic = "070701", 406 + .ino = 1, 407 + .mode = S_IFREG | 0777, 408 + .uid = 0, 409 + .gid = 0, 410 + .nlink = 1, 411 + .mtime = 1, 412 + .filesize = sizeof(fdata), 413 + .devmajor = 0, 414 + .devminor = 1, 415 + .rdevmajor = 0, 416 + .rdevminor = 0, 417 + /* align file data at 4K archive offset via padded fname */ 418 + .namesize = 4096 - CPIO_HDRLEN, 419 + .csum = 0, 420 + .fname = tbufs->padded_fname, 421 + .data = fdata, 422 + } }; 423 + 424 + memcpy(tbufs->padded_fname, "padded_fname", sizeof("padded_fname")); 425 + len = fill_cpio(c, ARRAY_SIZE(c), tbufs->cpio_srcbuf); 426 + 427 + err = unpack_to_rootfs(tbufs->cpio_srcbuf, len); 428 + KUNIT_EXPECT_NULL(test, err); 429 + 430 + file = filp_open(c[0].fname, O_RDONLY, 0); 431 + if (IS_ERR(file)) { 432 + KUNIT_FAIL(test, "open failed"); 433 + goto out; 434 + } 435 + 436 + /* read back file contents into @cpio_srcbuf and confirm match */ 437 + len = kernel_read(file, tbufs->cpio_srcbuf, c[0].filesize, NULL); 438 + KUNIT_EXPECT_EQ(test, len, c[0].filesize); 439 + KUNIT_EXPECT_MEMEQ(test, tbufs->cpio_srcbuf, c[0].data, len); 440 + 441 + fput(file); 442 + KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0); 443 + out: 444 + kfree(tbufs); 445 + } 446 + 447 + /* 390 448 * The kunit_case/_suite struct cannot be marked as __initdata as this will be 391 449 * used in debugfs to retrieve results after test has run. 392 450 */ ··· 458 394 KUNIT_CASE(initramfs_test_csum), 459 395 KUNIT_CASE(initramfs_test_hardlink), 460 396 KUNIT_CASE(initramfs_test_many), 397 + KUNIT_CASE(initramfs_test_fname_pad), 461 398 {}, 462 399 }; 463 400