5

To monitor if a reboot is necessary, I wanted to compare the version of /boot/kernel*img against the version of the running kernel.

To get the kernel version of a compressed linux kernel image (usually called zImage and named vmlinuz with a z for zipped instead of an x at the end), it suffices (at least on Debian) to look for the kernel version (major + minor + ABI + architecture) of the file name to get the exact kernel version (major + minor + micro), e.g. like this:

$ strings /boot/vmlinuz-4.9.0-8-amd64 | egrep '^4\.9\.0-8-amd64'
4.9.0-8-amd64 (debian-kernel@lists.debian.org) #1 SMP Debian 4.9.110-3+deb9u4 (2018-08-21)
4.9.0-8-amd64 (debian-kernel@lists.debian.org) (gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1) ) #1 SMP Debian 4.9.110-3+deb9u4 (2018-08-21)

But on Raspbian 9 Stretch as well as 8 Jessie (with kernels from the Raspberry Pi Foundation as common on Raspbian images provided by the Raspberry Pi Foundation) this information is not found just with strings:

$ strings /tmp/kernel7.img | head -30
@ #!
!1C "
 -- System halted
Attempting division by 0!
stack-protector: Kernel stack is corrupted
Uncompressing Linux...
 done, booting the kernel.
decompressor returned an error
[…]
Out of memory while allocating workspace
Not a gzip file
header error
read error
uncompression error

The only thing that I see is that this seems a gzip-compressed kernel (due to a gzip error message being compiled in). Also file says, that this is a zImage:

$ file /boot/kernel*.img
/boot/kernel7.img: Linux kernel ARM boot executable zImage (little-endian)
/boot/kernel.img:  Linux kernel ARM boot executable zImage (little-endian)

But I'm unable to extract the uncompressed vmlinux from these kernel images files, even with extract-vmlinux directly off Linus' Linux git repository and having installed all (de)compression tools it supports:

$ extract-vmlinux /boot/kernel7.img
extract-vmlinux: Cannot find vmlinux.

Looking at which uncompression methods it actually tries, it seems indeed to think that this is either a gzip- or zstd-compressed file:

$ sh -x `which extract-vmlinux` /boot/kernel7.img 2>&1 | fgrep -A1 tail
+ tail -c+18273 /boot/kernel7.img
+ gunzip
--
+ tail -c+566153 /boot/kernel7.img
+ gunzip
--
+ tail -c+2494526 /boot/kernel7.img
+ gunzip
--
+ tail -c+4195668 /boot/kernel7.img
+ unzstd

So independent from my initial motivation, I'd like to know:

  • Why is even extract-vmlinux unable to extract the uncompressed kernel image from Raspbian's /boot/kernel*.img images?
  • What do I need to extract the uncompressed kernel image from Raspbian's /boot/kernel*.img images?

EDIT: Addendum from late February 2023: This does not apply to RaspiOS' 64-bit kernel8.img kernel images, but still is the case with e.g. kernel7l.img.

But on the other hand, the latter looks even more weird with file nowadays. Then maybe, file is more precise these days and that's actually the reason for this issue:

# file /boot/kernel*
/boot/kernel7l.img: ARM OpenFirmware FORTH Dictionary, Text length: -509607936 bytes, Data length: -509607936 bytes, Text Relocation Table length: -369098747 bytes, Data Relocation Table length: 24061976 bytes, Entry Point: 0x00000000, BSS length: 7051064 bytes
/boot/kernel8.img:  gzip compressed data, was "Image", last modified: Thu Jan  5 12:03:14 2023, from Unix, original size modulo 2^32 22057472
Axel Beckert
  • 1,240
  • 14
  • 27

0 Answers0