(note: I am not subscribed to this bug report. If you want a reply from
me, please keep me Cc'd).

The padding between the component initramfs images that make up a
"hybrid initramfs" is a sequence of zeros, and it is aligned to the cpio
block/record size boundary.  There are several valid block sizes for
cpio, e.g. 512 (used by iucode v1.0 and earlier, and cpio default) or
1024, which iucode-tool v1.1 and later uses (as a defensive measure).

I can revert the 1024-byte block size in iucode-tool to 512 bytes, but
that's neither here nor there: it would just work around the bug in
lsinitramfs.  It would be better to fix lsinitramfs (assuming this isn't
fixed already in unstable).


Now, to the root cause of the breakage:

The heuristics initramfs-tools "lsinitramfs" uses (used?) to locate the
next initramfs are incomplete (it does not skip over the padding at the
end of each initramfs) and causes zcat to crash (which is likely a bug
in zcat itself).  It will work fine for 512-byte cpio block size, but
not for 1024-byte block size (and also likely not for other block
sizes).

lsinitramfs needs to skip all zero bytes (or dwords) to locate the next
initramfs segment, instead of assuming a cpio block size of 512 bytes.

And zcat should not crash if it gets a file that begins with a lot of
zeroes before the compressed data... it should either abort with an
error (invalid file), or skip the zeroes without crashing.  But that's a
separate bug.


For the record, a full account of how the kernel parses and loads an
initramfs (which is how lsinitramfs should behave in an ideal world):


EARLY cpio loader (lib/earlycpio.c, loads the microcode data and ACPI
table override data): always skips zero DWORDs (4 bytes) before any cpio
header, including the first.  So, it will just concatenate every
non-compressed cpio archive and skip any dword-aligned zero padding
before, after, or between cpio archive headers (and, therefore, also
between cpio archives).

Note: the early cpio loader does not care for subdirectories, it can
find data by the whole path, and that's how microcode is loaded. This
means the cpio archive with microcode does not need to have any of the
subdirectories inside, it doesn't matter to the kernel. I didn't check
how the ACPI table override loader behaves.

LATE cpio loader (init/initramfs.c, loads the real initramfs):
  1. Skips any zero bytes before the compressed or uncompressed data
  (thus, skips any padding between cpio archives).

  2. Unpacks any compressed or uncompressed cpio archive it finds,
  concatenating the contents (thus, it *will* also unpack
      the microcode in the first cpio archive, and this file will be
      available inside the initramfs).

  3. It *depends* on subdirectories being created *first* before any
  files inside them. If this is not done, it will ignore the file
      (so you could have data in the early initramfs that is "invisible"
      for the late cpio loader).

  4. It does NOT skip inital zero-padding on the *decompressed* data
  (i.e. if you compress a cpio archive, it must not have
      any initial zero padding).

  5. It skips any zero padding at the end (compressed or not), but the
  zeros must *end* at a DWORD boundary.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique de Moraes Holschuh <h...@debian.org>

Reply via email to