[PATCH v4 1/6] initramfs_test: add fill_cpio() inject_ox parameter

David Disseldorp
2026-03-29T10:53:34Z

fill_cpio() uses sprintf() to write out the in-memory cpio archive from
an array of struct initramfs_test_cpio. This change allows callers to
modify the cpio sprintf() format string so that future tests can
intentionally corrupt the header with "0x" and "0X" prefixed fields.

Signed-off-by: David Disseldorp <ddiss@suse.de>
---
init/initramfs_test.c | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/init/initramfs_test.c b/init/initramfs_test.c
index 2ce38d9a8fd0f..3ec7591660e03 100644
--- a/init/initramfs_test.c
+++ b/init/initramfs_test.c
@@ -27,7 +27,17 @@ struct initramfs_test_cpio {
char *data;
};

-static size_t fill_cpio(struct initramfs_test_cpio *cs, size_t csz, char *out)
+/* regular newc header format */
+#define CPIO_HDR_FMT "%s%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%s"
+/*
+ * bogus newc header with "0x" prefixes on the uid, gid and namesize values.
+ * parse_header()/simple_str[n]toul() accept this.
+ */
+#define CPIO_HDR_OX_INJECT \
+ "%s%08x%08x0x%06x0X%06x%08x%08x%08x%08x%08x%08x%08x0x%06x%08x%s"
+
+static size_t fill_cpio(struct initramfs_test_cpio *cs, size_t csz,
+ bool inject_ox, char *out)
{
int i;
size_t off = 0;
@@ -38,9 +48,8 @@ static size_t fill_cpio(struct initramfs_test_cpio *cs, size_t csz, char *out)
size_t thislen;

/* +1 to account for nulterm */
- thislen = sprintf(pos, "%s"
- "%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x"
- "%s",
+ thislen = sprintf(pos,
+ inject_ox ? CPIO_HDR_OX_INJECT : CPIO_HDR_FMT,
c->magic, c->ino, c->mode, c->uid, c->gid, c->nlink,
c->mtime, c->filesize, c->devmajor, c->devminor,
c->rdevmajor, c->rdevminor, c->namesize, c->csum,
@@ -102,7 +111,7 @@ static void __init initramfs_test_extract(struct kunit *test)
/* +3 to cater for any 4-byte end-alignment */
cpio_srcbuf = kzalloc(ARRAY_SIZE(c) * (CPIO_HDRLEN + PATH_MAX + 3),
GFP_KERNEL);
- len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);

ktime_get_real_ts64(&ts_before);
err = unpack_to_rootfs(cpio_srcbuf, len);
@@ -177,7 +186,7 @@ static void __init initramfs_test_fname_overrun(struct kunit *test)
/* limit overrun to avoid crashes / filp_open() ENAMETOOLONG */
cpio_srcbuf[CPIO_HDRLEN + strlen(c[0].fname) + 20] = '\0';

- len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);
/* overwrite trailing fname terminator and padding */
suffix_off = len - 1;
while (cpio_srcbuf[suffix_off] == '\0') {
@@ -219,7 +228,7 @@ static void __init initramfs_test_data(struct kunit *test)
cpio_srcbuf = kmalloc(CPIO_HDRLEN + c[0].namesize + c[0].filesize + 6,
GFP_KERNEL);

- len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);

err = unpack_to_rootfs(cpio_srcbuf, len);
KUNIT_EXPECT_NULL(test, err);
@@ -274,7 +283,7 @@ static void __init initramfs_test_csum(struct kunit *test)

cpio_srcbuf = kmalloc(8192, GFP_KERNEL);

- len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);

err = unpack_to_rootfs(cpio_srcbuf, len);
KUNIT_EXPECT_NULL(test, err);
@@ -284,7 +293,7 @@ static void __init initramfs_test_csum(struct kunit *test)

/* mess up the csum and confirm that unpack fails */
c[0].csum--;
- len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);

err = unpack_to_rootfs(cpio_srcbuf, len);
KUNIT_EXPECT_NOT_NULL(test, err);
@@ -330,7 +339,7 @@ static void __init initramfs_test_hardlink(struct kunit *test)

cpio_srcbuf = kmalloc(8192, GFP_KERNEL);

- len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, cpio_srcbuf);

err = unpack_to_rootfs(cpio_srcbuf, len);
KUNIT_EXPECT_NULL(test, err);
@@ -371,7 +380,7 @@ static void __init initramfs_test_many(struct kunit *test)
};

c.namesize = 1 + sprintf(thispath, "initramfs_test_many-%d", i);
- p += fill_cpio(&c, 1, p);
+ p += fill_cpio(&c, 1, false, p);
}

len = p - cpio_srcbuf;
@@ -425,7 +434,7 @@ static void __init initramfs_test_fname_pad(struct kunit *test)
} };

memcpy(tbufs->padded_fname, "padded_fname", sizeof("padded_fname"));
- len = fill_cpio(c, ARRAY_SIZE(c), tbufs->cpio_srcbuf);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, tbufs->cpio_srcbuf);

err = unpack_to_rootfs(tbufs->cpio_srcbuf, len);
KUNIT_EXPECT_NULL(test, err);
@@ -481,7 +490,7 @@ static void __init initramfs_test_fname_path_max(struct kunit *test)
memcpy(tbufs->fname_oversize, "fname_oversize",
sizeof("fname_oversize") - 1);
memcpy(tbufs->fname_ok, "fname_ok", sizeof("fname_ok") - 1);
- len = fill_cpio(c, ARRAY_SIZE(c), tbufs->cpio_src);
+ len = fill_cpio(c, ARRAY_SIZE(c), false, tbufs->cpio_src);

/* unpack skips over fname_oversize instead of returning an error */
err = unpack_to_rootfs(tbufs->cpio_src, len);
--
2.51.0