Per "man 5 cpio", the namesize in the cpio header includes the trailing NULL byte of the pathname and the pathname is followed by NULL bytes, but the current implementation excludes the trailing NULL byte when making the newc header plus the pathname. Although make_header() would pad the pathname string, the padding won't happen when strlen(name) + sizeof(struct newc_head) is a multiple of 4, and the non-NULL-terminated pathname may lead to unexpected results.
For example, when loading linux with the following command: linux /boot/vmlinuz initrd newc:test12:/boot/test12 /boot/initrd Since strlen("test12") + sizeof(struct newc_head) is 116 = 29 * 4, there is no padding for the pathname, and the following error may show during linux boot: Initramfs unpacking failed: ZSTD-compressed data is trunc To avoid the potential problems, this commit includes the NULL byte when calling make_header() and adjusts the initrd size accordingly. Signed-off-by: Gary Lin <g...@suse.com> --- grub-core/loader/linux.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index 830360172..2b26d293f 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -127,12 +127,14 @@ insert_dir (const char *name, struct dir **root, n->name = grub_strndup (cb, ce - cb); if (ptr) { + char *tmp_name = grub_strndup (name, ce - name); grub_dprintf ("linux", "Creating directory %s, %s\n", name, ce); - ptr = make_header (ptr, name, ce - name, + ptr = make_header (ptr, tmp_name, ce - name + 1, 040777, 0); + grub_free (tmp_name); } if (grub_add (*size, - ALIGN_UP ((ce - (char *) name) + ALIGN_UP ((ce - (char *) name + 1) + sizeof (struct newc_head), 4), size)) { @@ -191,7 +193,7 @@ grub_initrd_init (int argc, char *argv[], grub_initrd_close (initrd_ctx); return grub_errno; } - name_len = grub_strlen (initrd_ctx->components[i].newc_name); + name_len = grub_strlen (initrd_ctx->components[i].newc_name) + 1; if (grub_add (initrd_ctx->size, ALIGN_UP (sizeof (struct newc_head) + name_len, 4), &initrd_ctx->size) || @@ -205,7 +207,7 @@ grub_initrd_init (int argc, char *argv[], { if (grub_add (initrd_ctx->size, ALIGN_UP (sizeof (struct newc_head) - + sizeof ("TRAILER!!!") - 1, 4), + + sizeof ("TRAILER!!!"), 4), &initrd_ctx->size)) goto overflow; free_dir (root); @@ -233,7 +235,7 @@ grub_initrd_init (int argc, char *argv[], initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); if (grub_add (initrd_ctx->size, ALIGN_UP (sizeof (struct newc_head) - + sizeof ("TRAILER!!!") - 1, 4), + + sizeof ("TRAILER!!!"), 4), &initrd_ctx->size)) goto overflow; free_dir (root); @@ -304,7 +306,7 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, } else if (newc) { - ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, + ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!"), 0, 0); free_dir (root); root = 0; @@ -327,7 +329,7 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, { grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ptr += ALIGN_UP_OVERHEAD (cursize, 4); - ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); + ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!"), 0, 0); } free_dir (root); root = 0; -- 2.35.3 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel