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 ([email protected]) #1 SMP Debian 4.9.110-3+deb9u4 (2018-08-21)
4.9.0-8-amd64 ([email protected]) (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
extract-vmlinux
searches for typical start markers of compression and only tries to decompress from there on. It also decides which decompression method to try based on which markers were found.