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
_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;
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) {
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);