From: Zbigniew Jędrzejewski-Szmek Date: Fri, 6 Dec 2024 12:11:02 +0000 (+0100) Subject: boot: exclude the trailing padding from initrd size in initrd_prepare() X-Git-Tag: v257~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=423de11f046cc2c9b6904e4eff71d6a48cd661c9;p=thirdparty%2Fsystemd.git boot: exclude the trailing padding from initrd size in initrd_prepare() This is a follow-up for f8fa4222c9ac3e74e91c64e25e9532c99559cf99 (boot: Make initrd_prepare() semantically equivalent to combine_initrds()). That commit changed the way that the initrd is prepared for type#1 boot loader entries, also effectively rounding up the sizes to a multiple of 4. In [1], downstream packagers report that the trailing zeroes result in the calculated hash being different. To restore compatibility with previous hash calculations and signatures, change the reported size by excluding the trailing padding. This should restore the calculation results for the case where only one initrd is used. This patch doesn't touch the stub, i.e. doesn't change behaviour for UKIs. The seems fine, since we didn't change that recently, so any changes there would break compatiblity. The measurement results for type#1 and type#2 entries are generally going to be different anyway. ukify and systemd-measure are also out of scope here, because they are for UKIs. Fixes https://github.com/systemd/systemd/issues/35439. The other changes to the way the initrd is constructed are kept, so hopefully the original issue with booting in qemu is not recreated. [1] https://bugzilla.suse.com/show_bug.cgi?id=1233752 My simple test: I'm booting a QEMU VM with systemd-boot and a type#1 entry. With old systemd-boot: $ sudo systemd-pcrlock log | grep 'kernel-initrd.*event-tag' 9 █ kernel-initrd event-tag - a337a8321bf81de5c53a842843e8f9a926f73a676e5620ff76df94d1c66bc931 F - Linux: kernel command line 9 █ kernel-initrd event-tag - aec1aee5358bde36f5498f2dc243dec2b103f81242de57b887a11f53677f1272 F - Linux: initrd With updated systemd-boot: $ sudo systemd-pcrlock log | grep 'kernel-initrd.*event-tag' 9 █ kernel-initrd event-tag - a337a8321bf81de5c53a842843e8f9a926f73a676e5620ff76df94d1c66bc931 F - Linux: kernel command line 9 █ kernel-initrd event-tag - 3ccaa710304aef8734a20265ea7fd3dd67d5461c6b3309c6d30d5c7d2a3ae7f9 F - Linux: initrd This matches the initrd hash: $ sudo sha256sum /efi//26f948d2082e4ae89f5a3af351b63149/6.12.0-rc4+/initrd-dracut 3ccaa710304aef8734a20265ea7fd3dd67d5461c6b3309c6d30d5c7d2a3ae7f9 /efi//26f948d2082e4ae89f5a3af351b63149/6.12.0-rc4+/initrd-dracut --- diff --git a/src/boot/boot.c b/src/boot/boot.c index 129d6f8f5d3..4ef519d4040 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -2446,7 +2446,7 @@ static EFI_STATUS initrd_prepare( _cleanup_free_ char16_t *options = NULL; EFI_STATUS err; - size_t size = 0; + size_t size = 0, padded_size = 0; STRV_FOREACH(i, entry->initrd) { _cleanup_free_ char16_t *o = options; @@ -2465,11 +2465,14 @@ static EFI_STATUS initrd_prepare( if (err != EFI_SUCCESS) return err; - if (!INC_SAFE(&size, ALIGN4(info->FileSize))) + size_t inc = info->FileSize; + + if (!INC_SAFE(&padded_size, ALIGN4(inc))) return EFI_OUT_OF_RESOURCES; + assert_se(INC_SAFE(&size, *(i + 1) ? ALIGN4(inc) : inc)); } - _cleanup_pages_ Pages pages = xmalloc_initrd_pages(size); + _cleanup_pages_ Pages pages = xmalloc_initrd_pages(padded_size); uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr); STRV_FOREACH(i, entry->initrd) { @@ -2501,7 +2504,11 @@ static EFI_STATUS initrd_prepare( continue; memzero(p, pad); - p += pad; + /* Exclude the trailing pad from size calculations. This would change the + * calculated hash, see https://github.com/systemd/systemd/issues/35439 + * and https://bugzilla.suse.com/show_bug.cgi?id=1233752. */ + if (*(i + 1)) + p += pad; } assert(PHYSICAL_ADDRESS_TO_POINTER(pages.addr + size) == p);