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?
  • 1
    I believe the reason you can't extract the kernel from the image file is because of the binary blog proprietary magic compiled in by Broadcom.... but I may be wrong. – RubberStamp Aug 30 '18 at 21:04
  • AFAIK that binary blob stuff from Broadcom is just prepended. And 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. – Axel Beckert Aug 31 '18 at 14:44
  • Well... I haven't tried yet... but here are the instructions to build your own RPi kernel ... If you are looking to verify kernels, you could probably do a sha256 hash and compare rather than look for strings in binaries. – RubberStamp Aug 31 '18 at 17:59
  • No, hashsums would require to know them to be able to compare them. I'm looking to expand an existing and so far rather generic solution to work with Raspbian, too. (So far works fine on Debian and Ubuntu with their stock kernels.) – Axel Beckert Sep 4 '18 at 12:21
  • 1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.