Strip out 0xd935 extra field record in zip entries

The extra field record was previously stripped out due to a bug in
Python's zipfile implementation. That was fixed by [1], which was
backported to 3.10 and 3.11, but not 3.9.

This commit explicitly strips out the 0xd935 record to ensure that the
checksums of the patched files are the same across all Python versions.
This is probably the correct thing to do anyway, since the record is
related to zip entry alignment [2], which we don't do.

Note that the Python bug can affect other extra field records too, but
we don't see that in practice.

[1] https://github.com/python/cpython/commit/62c0327487ce39ec6504919b7712e0f197075ef9
[2] https://android.googlesource.com/platform/build/+/android-13.0.0_r1/tools/signapk/src/com/android/signapk/SignApk.java#133

Fixes: #93

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
This commit is contained in:
Andrew Gunnerson
2023-05-22 23:39:54 -04:00
parent 7d5977b410
commit dc81e8571f
2 changed files with 25 additions and 4 deletions
+23 -2
View File
@@ -4,6 +4,7 @@ import copy
import io
import os
import shutil
import struct
import tempfile
import time
import zipfile
@@ -150,6 +151,25 @@ def patch_ota_payload(f_in, open_more_f_in, f_out, file_size, boot_partition,
)
def strip_alignment_extra_field(extra):
offset = 0
new_extra = bytearray()
while offset < len(extra):
record_sig, record_len = \
struct.unpack('<HH', extra[offset:offset + 4])
next_offset = offset + 4 + record_len
# ALIGNMENT_ZIP_EXTRA_DATA_FIELD_HEADER_ID
if record_sig != 0xd935:
new_extra.extend(extra[offset:next_offset])
offset = next_offset
return new_extra
def patch_ota_zip(f_zip_in, f_zip_out, boot_partition, root_patch,
clear_vbmeta_flags, privkey_avb, passphrase_avb, privkey_ota,
passphrase_ota, cert_ota):
@@ -195,16 +215,17 @@ def patch_ota_zip(f_zip_in, f_zip_out, boot_partition, root_patch,
for info in infolist:
out_info = copy.copy(info)
out_info.extra = strip_alignment_extra_field(out_info.extra)
# Ignore because the plain-text legacy metadata file is regenerated
# from the new metadata
if info.filename == PATH_METADATA:
metadata_info = info
metadata_info = out_info
continue
# The existing metadata is needed to generate a new signed zip
elif info.filename == PATH_METADATA_PB:
metadata_pb_info = info
metadata_pb_info = out_info
with z_in.open(info, 'r') as f_in:
metadata_pb_raw = f_in.read()
+2 -2
View File
@@ -135,8 +135,8 @@ device:
full: 929f892fbd70699cf7f118a119aac1ae1b86351e1ada17715666fa4401e63472
stripped: 6d9013c29aff5dc07ec549d844c5888089fe65f4a5c624bbd0afa04d1503ec8a
patched:
full: 25f14582186e0f544480c6126b6b6ff0b6616023b796372d39af909300fb2e3a
stripped: 8c82dcc4427320fd8df4e1026c6d50ff92d5caf96e66a5c8f8b698f9fbe8806d
full: 1c4294f2faa711eacf4647025041e73d10488d7b9ff3a1a3142fe84b195cd9e0
stripped: c6abc228354ee6f4e338fce6860884c0aa6d4d2a72920e411c491ff52278702d
avb_images:
boot.img: ec703e143c24e7eb5b2eb96beb1d4342c1dd2179b12612d41430b1b55e7dec0f
recovery.img: 2ff62bc52a5900eb170cc44df0f0ee8062ee6dcb48ecf1899ac556145161f53c