From 8ea3d185cafa55a5ca9cd8d13d1a34c3bfa7b315 Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Mon, 27 Feb 2023 01:10:43 -0500 Subject: [PATCH] avbroot/boot.py: Check KMI version when using prepatched image This ensures that the user isn't replacing the kernel image with another one that's not binary compatible (based on the GKI kernel module interface version). Signed-off-by: Andrew Gunnerson --- avbroot/boot.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/avbroot/boot.py b/avbroot/boot.py index 4adc6e2..f57de45 100644 --- a/avbroot/boot.py +++ b/avbroot/boot.py @@ -1,6 +1,7 @@ import hashlib import io import lzma +import re import shutil import zipfile @@ -235,6 +236,9 @@ class PrepatchedImage(BootImagePatch): be higher than the original image. ''' + VERSION_REGEX = re.compile( + b'Linux version (\d+\.\d+).\d+-(android\d+)-(\d+)-') + def __init__(self, prepatched): self.prepatched = prepatched @@ -272,6 +276,14 @@ class PrepatchedImage(BootImagePatch): f'{len(boot_image.ramdisks)} -> ' f'{len(prepatched_image.ramdisks)}') + if boot_image.kernel is not None: + old_kmi = self._get_kmi_version(boot_image) + new_kmi = self._get_kmi_version(prepatched_image) + + if old_kmi != new_kmi: + errors.append('Kernel module interface version changed: ' + f'{old_kmi} -> {new_kmi}') + if errors: raise ValueError('The prepatched boot image is not compatible ' 'with the original:\n' + @@ -279,6 +291,23 @@ class PrepatchedImage(BootImagePatch): return prepatched_image + @classmethod + def _get_kmi_version(cls, boot_image): + try: + with ( + io.BytesIO(boot_image.kernel) as f_raw, + compression.CompressedFile(f_raw, 'rb') as f, + ): + decompressed = f.fp.read() + except ValueError: + decompressed = boot_image.kernel + + m = cls.VERSION_REGEX.search(decompressed) + if not m: + return None + + return b'-'.join(m.groups()).decode('ascii') + def patch_boot(avb, input_path, output_path, key, passphrase, only_if_previously_signed, patch_funcs):