Commit Graph

23 Commits

Author SHA1 Message Date
Andrew Gunnerson bf53859bcd Ensure output files are zip64-compliant (again)
PR #110 fixed this incorrectly. I misinterpreted "set to zero in the
local header" from §4.4.4 in the spec as referring to the two 32-bit
size fields in the local header. However, the spec considers the zip64
extra record as part of the local header. The correct behavior for
writing zip64 entries to unseekable files is 0xffffffff in the 32-bit
local header size fields (to enable zip64), 0 in the zip64 extra record
(due to streaming writes), and the actual sizes in the data descriptor.

Fixes: #109

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-07-03 16:30:09 -04:00
Andrew Gunnerson 93dcd63829 Add support for replacing any partition image
This commit adds support for replacing any partition image within
the payload with a custom image. This is useful, for example, to add a
custom kernel to an OTA, which may involve partitions that wouldn't
normally be touched (eg. `vendor_dlkm`).

Any image specified via `--replace` will have its corresponding
descriptor in the vbmeta image updated. This is handled recursively. For
example, replacing `vendor_dlkm` would update both `vbmeta_vendor` and
`vbmeta`. This requires all vbmeta images to be extracted during the
patching process so that a complete dependency graph can be computed.
The performance hit in doing so is negligible, but does require the
checksums of the stripped images to be updated for the tests.

Fixes: #102

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-06-28 21:04:49 -04:00
Andrew Gunnerson a0421d3eb4 tests: Containerfile.arch: Allow system-wide pip installation
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-06-28 18:59:21 -04:00
Andrew Gunnerson f25ac50b0a Ensure output files are zip64-compliant
This commit fixes two issues:

* Python 3.11.4 has a regression where it sets the local file header's
  compressed and uncompressed size fields to 0xffffffff when data
  descriptors are used. These should be set to 0 (along with the CRC)
  according to §4.4.4 of the spec. We work around this by monkey
  patching zipfile's local file header serialization function to correct
  the fields.
* avbroot tries to preserve as much metadata from the original zip as
  possible, including the `extra` records. This caused zip64 records
  (0x0001) to be duplicated. The first instance was from the original
  zip (containing invalid size fields) and the second instance was newly
  created by zipfile. We fix this by stripping out all 0x0001 records,
  similar to what we already do for 0xd935.

Fixes: #109

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-06-28 18:38:06 -04:00
Andrew Gunnerson 6be4665557 Update tests for non-interactive patching with encrypted keys
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-05-30 23:54:16 -04:00
Andrew Gunnerson e51c3661dd tests: Update container image distros to the latest versions
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-05-23 15:27:20 -04:00
Andrew Gunnerson dc81e8571f 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>
2023-05-22 23:52:03 -04:00
Andrew Gunnerson 50483b4ffa tests: Update Magisk to 26000 and OTAs to their latest versions
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-04-05 18:14:32 -04:00
Andrew Gunnerson 0a1888ad94 Magisk >=25207 require a rules device ID
Newer Magisk versions no longer try to autodetect a writable ext4
partition for storing SELinux rules during boot. Instead, the block
device is detected during boot image patching and is stored in the
ramdisk's `.backup/.magisk` as `makedev(rdev_maj, rdev_min)`.

This unfortunately complicates the patching process for avbroot. Even if
we replicate Magisk's algorithm for finding a suitable partition,
there's no way to find the block device's rdev for it with the
information contained in the OTA package. This is the first change that
adds a hard dependency on information only attainable from a running
device.

For these newer Magisk versions, the user will have to patch the boot
image once in the Magisk app (must be on the target device) and then run
`avbroot magisk-info` to show the computed device ID. Then, avbroot can
use this during patching via `--magisk-rules-device`. If the user's
device is unable to run the Magisk app prior to patching (eg.
unbootable), they'll have to go through the patching process twice, once
with `--ignore-magisk-warnings` and a second time with the proper device
ID specified.

When using `--ignore-magisk-warnings`, root still works, but there will
be subtle issues, like certain modules failing to load.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-09 17:01:39 -05:00
Andrew Gunnerson 1bdac19c44 Move sys.path modification to __init__.py
This way, the module path is automatically updated when avbroot is
imported. This also fixes the lint warning about `external` being
imported, but not used.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-05 14:44:54 -05:00
Andrew Gunnerson 4847ebf27a Merge tests_ci into tests
This commit merges the CI tests from `tests_ci/` into `tests/` so we
have a single way to test against both full OTAs and stripped/dummy
OTAs.

Features kept from tests_ci:

* Support for dummy OTAs. They're now called stripped OTAs to hopefully
  better signify that they're a stripped down version of the original
  file instead of a test file created from scratch.
* Extracting AVB partitions and verifying their hashes.
* Writing sparse files where possible.
* Ability to change the working directory for downloads and output
  files.

Test script changes:

* There are now 4 subcommands:
    strip -i <input> -o <output>
    add -u <url> -d <device> [-H <expected hash>]
    download [--magisk | --no-magisk] [[-d <device>] ... | --no-devices]
    test [[-d <device>] ...]
* Downloads now use the parallel downloader for both full and stripped
  OTAs.

Config file changes:

* It now uses strictyaml instead of configparser/TOML since it's a bit
  more readable now that we have more nesting in the data structure. The
  config loader now also makes use of strictyaml's schema feature.
* All hashes are now SHA-256 for consistency.
* For stripped OTAs, the list of byte ranges now uses half-open
  intervals for easier calculations.
* Use device IDs as the key instead of the marketing model name.

CI changes:

* Compute all cache keys (and prefixes) in the main workflow and pass
  them to the preload scripts.
* Only run on `push` for the `master` branch to avoid double workflow
  runs on PRs from internal branches.
* Increase timeout for patching tests because `tests.py` patches twice
  (once with `--magisk` and once with `--prepatched`).

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-04 21:39:08 -05:00
Andrew Gunnerson 003fbf18ba tests/downloader.py: Add MiB/s to DefaultDisplayCallback output
No fancy algorithm. Just a simple moving average over 5 seconds, updated
at 100ms intervals.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-01 17:44:17 -05:00
Andrew Gunnerson 76eec8fb6e tests/downloader.py: Avoid unnecessary buffer allocations in DownloadWorker
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-01 17:44:16 -05:00
Andrew Gunnerson db562315e9 tests: Drop aria2 dependency
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-01 17:44:15 -05:00
Andrew Gunnerson 69cb0dd4d7 tests: Add native Python parallel download implementation
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-03-01 17:44:03 -05:00
Andrew Gunnerson d74f7c77ff tests: README.md: Document that --prepatched is now tested
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-26 22:41:54 -05:00
Andrew Gunnerson d80ce411c7 Add support for using prepatched boot images
This is useful for folks who want to apply the Magisk root patch
themselves via the Magisk app or use KernelSU. When `--prepatched` is
used, avbroot will skip the root patch, but still apply the otacerts
patch.

To help protect against accidental use of the wrong boot image, avbroot
will only accept a prepatched image if all the header fields and section
types match the original image. The only exception is the number of
ramdisks, which is allowed to increase (Magisk may create a ramdisk in
an image that didn't originally have one).

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-26 18:01:03 -05:00
Andrew Gunnerson 545a2a9587 tests/tests_containerized.py: Include elapsed time in result table
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-16 22:32:18 -05:00
Andrew Gunnerson 37ef00d7b4 tests/tests_containerized.py: Fix swapped if condition for network access
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-16 21:57:36 -05:00
Andrew Gunnerson 2238c37556 tests: Add new image for running tests for Windows in Wine
Yes, this is installing msys2 packages directory on the Arch Linux root
filesystem. Yes, it works!

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-16 21:57:15 -05:00
Andrew Gunnerson 7557d30183 tests: Add infrastructure for running tests in podman
The officially supported distros are now Alpine, Arch, Debian, Fedora,
Fedora, OpenSUSE, and Ubuntu. The new script will build images for these
distros and concurrently run tests.py inside containers.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-14 23:55:34 -05:00
Andrew Gunnerson 98bd336c91 Add new bootimagetool utility for working with boot images
This just adds a simple CLI for avbroot.formats.bootimage library. It's
not strictly related to avbroot, but is useful for troubleshooting since
the library supports all AOSP-compatible boot images.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-14 01:47:10 -05:00
Andrew Gunnerson 904a9f666a Add end-to-end patching tests
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-13 22:14:27 -05:00