Commit Graph

477 Commits

Author SHA1 Message Date
Andrew Gunnerson 6ef8e548a3 Add support for Magisk v27.0
Upstream Magisk now xz-compresses files in modifies in the ramdisk. This
commit also implements the same in avbroot's MagiskRootPatcher.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2024-02-03 14:35:57 -05:00
Andrew Gunnerson 80549346ea README.md: Temporarily suggest manual procedure for initially flashing system.img
We'll switch to using `fastboot flashall` in the future once that has
been implemented and tested.

Fixes: #252

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2024-01-31 17:39:13 -05:00
Andrew Gunnerson 275b18b2a5 CHANGELOG.md: Add entry for PR #247
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-31 16:29:40 -05:00
Andrew Gunnerson 0a68966594 Switch from xz2 to liblzma
liblzma is a maintained fork of xz2. We can now get rid of our own fork
of xz2.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-31 16:20:30 -05:00
Andrew Gunnerson 9ef5629556 CHANGELOG.md: Add entry for PR #246
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-30 19:25:49 -05:00
Andrew Gunnerson 1db09eb896 Merge pull request #246 from chenxiaolong/remove_modules
Remove oemunlockonboot module
2023-12-30 19:24:06 -05:00
Andrew Gunnerson a134d7f889 Remove oemunlockonboot module
The module has been split out into another repo [1] so that it can be
versioned separately. It now also supports Magisk's automatic update
mechanism.

Closes: #235

[1] https://github.com/chenxiaolong/OEMUnlockOnBoot

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-30 19:16:05 -05:00
Andrew Gunnerson 833ca931e8 Version 3.0.0
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
v3.0.0
2023-12-29 20:57:22 -05:00
Andrew Gunnerson 9b6677d28a CHANGELOG.md: Remove entry for PR #220
It was obsoleted by #226.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 20:55:06 -05:00
Andrew Gunnerson 12e59fcf53 CHANGELOG.md: Add entry for PR #245
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 20:52:30 -05:00
Andrew Gunnerson 4bc7363f70 Merge pull request #245 from chenxiaolong/deps
Update all dependencies
2023-12-29 20:51:53 -05:00
Andrew Gunnerson b5ad9dddf6 Update all dependencies
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 20:44:12 -05:00
Andrew Gunnerson f0aba89549 CHANGELOG.md: Add entry for PR #243
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 20:41:22 -05:00
Andrew Gunnerson c9633682ef Merge pull request #243 from chenxiaolong/repair_mode
README.md: Document Repair Mode
2023-12-29 20:39:22 -05:00
Andrew Gunnerson da17935972 CHANGELOG.md: Add entry for PR #241
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 16:18:39 -05:00
Andrew Gunnerson c2140a85e9 Merge pull request #241 from chenxiaolong/e2e
e2e: Switch to using mock OTAs for testing
2023-12-29 16:17:31 -05:00
Andrew Gunnerson 3a3582ce4c e2e: Switch to using mock OTAs for testing
This commit replaces the previous approach of patching real OTAs with
patching mock OTAs. The motivation for this change is to make it
possible to test the system partition otacerts.zip patching without
needing to download huge files. Adding the system image to the stripped
OTAs would increase the file size by an order of magnitude.

The mock OTAs are generated from a set of profiles defined in e2e.toml.
The four included profiles are meant to mimic the OTAs used for testing
before:

* pixel_v4_gki     ~= cheetah
* pixel_v4_non_gki ~= bluejay
* pixel_v3         ~= bramble
* pixel_v2         ~= sunfish

There is no equivalent profile for ossi because newer OnePlus devices no
longer support custom signing keys properly.

The mock OTAs are perfectly valid, structure and signature-wise. They
just don't include any real partition data where possible. They are
initially signed with a different set of keys to ensure that the changes
made by the patching process are actually visible.

With how small the mock OTAs are, testing every profile only takes about
two seconds. Thus, the Github Actions workflow was adjusted to just run
e2e in the same job as the build.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 16:07:57 -05:00
Andrew Gunnerson b029116a5a CHANGELOG.md: Add entry for PR #244
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 15:48:12 -05:00
Andrew Gunnerson af1b01646d Merge pull request #244 from chenxiaolong/system_patch_performance
Optimize repacking of modified system image into payload
2023-12-29 15:47:09 -05:00
Andrew Gunnerson e85102709f Optimize repacking of modified system image into payload
When the original payload extents are all in order and have no gaps, we
can efficiently copy unmodified chunks of the system image from the
original payload into the new payload. Only the chunks containing the
modified regions (`otacerts.zip`, hash tree, FEC data, and AVB metadata)
need to be recompressed. This massively reduces the CPU usage since
usually only <20 MiB need to be recompressed.

If the conditions for the optimized path aren't satisfied (eg. extents
aren't in order or `--replace` is used), then it falls back to splitting
and compressing the entire system image.

This fixes the performance issues introduced in #240. This is probably
the best that we can do given that we now always patch the system image.

Issue: #225

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-29 00:02:35 -05:00
Andrew Gunnerson 124629dc45 README.md: Document Repair Mode
Closes: #216

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-28 18:10:26 -05:00
Andrew Gunnerson e89c4bdc9e CHANGELOG.md: Add entry for PR #240
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-28 18:00:23 -05:00
Andrew Gunnerson c1095b8321 Merge pull request #240 from chenxiaolong/system_otacerts
Add support for replacing otacerts.zip in the system image
2023-12-28 17:49:02 -05:00
Andrew Gunnerson 17504a7f81 Add support for replacing otacerts.zip in the system image
Previously, overriding otacerts.zip in the system partition required the
user to flash a Magisk/KernelSU module that would bind mount over the
file during boot. While this worked well enough, it's insufficient for
unrooted setups, which has become more important since unrooting is the
only safe way to use the new OEM repair mode feature. With the stock
otacerts.zip, the OEM's default OTA updater app could run and install an
OS upgrade that's not signed by the user's key.

With this commit, the raw otacerts.zip bytes in the system partition are
directly replaced with a new zip that contains the user's certificate.
This method was inspired by @pascallj's comment in #216 suggesting
intentionally corrupting the otacerts.zip data in the filesystem.

Because avbroot does not have filesystem parsers for ext4/f2fs/erofs, we
rely on a heuristic-based search on the raw filesystem image. The file
is always smaller than one block (which is at least 4096 bytes on all
known devices), so the file data is stored contiguously on disk and in
the case of erofs, won't be compressed. None of the three filesystems
are copy-on-write and thus, have no filesystem-level data checksums. For
the dm-verity layer one level up, avbroot already knows how to recompute
the hash tree and FEC data.

To ensure that there are no false positives, any match that the search
finds must correctly parse as a valid zip and every entry within the zip
must have a filename that ends in .x509.pem. This matches what
update_engine expects from a proper otacerts.zip file.

Since the new approach is doing a raw search and replace, the old and
new files must have the same size. When the new zip is smaller, null
bytes are added to the zip archive comment field to pad to the correct
size. When the new zip is larger, avbroot will attempt the following to
try and make the file size smaller:

1. Enable zip deflate compression
2. Strip the X.509 signature from the certificate
3. Clear out the issuer RDN sequence from the certificate
4. Clear out the subject RDN sequence from the certificate

The latter three changes work because Android never performs any PKI
operations with the certificate. There is no CA certificate chain. The
X.509 certificate file is nothing more than a way to transport an RSA
public key.

avbroot requires the user's key to be RSA 4096. If the original zip had
the same key size, then none of these shrinking methods are needed. If
it contained an RSA 2048 key, then the first two modifications are
usually sufficient. The latter two modifications should only be needed
if the user picked a really long subject value when generating the
certificate.

With these new changes, the OTA patching time will approximately double
on a system with an SSD and modern CPU. This is dominated by the time it
takes to XZ-compress the system partition image. The compression is
already parallelized and scales linearly with the number of cores.
There's likely not much more that can be done to further speed this up.

Finally, these new changes are currently excluded from the e2e tests
because including the system partition in the stripped OTAs would
increase the file size by an order of magnitude. This could potentially
be solved in the future by generating our own small OTAs to use for
testing instead of running against real device OTAs.

Fixes: #225

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-24 18:23:03 -05:00
Andrew Gunnerson d8190143bf CHANGELOG.md: Add entry for PR #237
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-22 16:17:06 -05:00
Andrew Gunnerson 0944abcea2 Merge pull request #237 from chenxiaolong/autodetect
Allow boot image autodetection to inspect boot images
2023-12-22 16:14:52 -05:00
Andrew Gunnerson 249c36d8c3 Allow boot image autodetection to inspect boot images
During patching, all boot images are now extracted and the individual
patchers can inspect them to determine which ones need modifications.
This replaces the previous mechanism of detecting which boot images to
patch based on the name alone.

With this new method, the --boot-partition and --otacerts-partitions
options are no longer needed. The former option is kept (but ignored
with a warning message) for backwards compatibility, but the latter is
completely removed because it never made it to a stable release.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-22 00:35:32 -05:00
Andrew Gunnerson 446e87289f CHANGELOG.md: Add entry for PR #234
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 22:14:44 -05:00
Andrew Gunnerson 04b8e3c315 Merge pull request #234 from chenxiaolong/fec_param_order
fec: Change update() parameter order to be more consistent
2023-12-17 22:14:09 -05:00
Andrew Gunnerson 03809a1e88 fec: Change update() parameter order to be more consistent
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 22:07:00 -05:00
Andrew Gunnerson 1fcb29532d CHANGELOG.md: Add entry for PR #233
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 21:08:28 -05:00
Andrew Gunnerson b383c8a0ab Merge pull request #233 from chenxiaolong/hash_tree
Split dm-verify hash tree logic out of avb module
2023-12-17 21:06:07 -05:00
Andrew Gunnerson 7ea8e8fa9e Split dm-verify hash tree logic out of avb module
* Refactor hash tree computation to work on a preallocated hash tree
  buffer. This makes it possible to partially update a hash tree, which
  is now supported.

* Add new subcommands for working with hash trees. There's no standard
  header format for dm-verity information, so these commands write hash
  tree files with a custom header. The commands are not really useful
  outside of debugging avbroot's hash tree implementation.

  Using AVB was considered, but it has no support for the hash tree data
  living in a separate file from the input. If other parties agree on a
  standard header in the future, avbroot will switch to that format.

* Add tests for the hash tree implementation.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 20:48:00 -05:00
Andrew Gunnerson ce43b3c657 CHANGELOG.md: Add entry for PR #232
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 15:08:43 -05:00
Andrew Gunnerson 05e5e59d65 Merge pull request #232 from chenxiaolong/small_hash_tree
avb: hashtree: Fix incorrect I/O read size for input smaller than one block
2023-12-17 15:07:51 -05:00
Andrew Gunnerson 72b8120bf9 avb: hashtree: Fix incorrect I/O read size for input smaller than one block
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 15:00:50 -05:00
Andrew Gunnerson 8110f82b17 CHANGELOG.md: Add entry for PR #231
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 14:59:47 -05:00
Andrew Gunnerson 64dbfa241e Merge pull request #231 from chenxiaolong/overlap
util: merge_overlapping: Skip empty and invalid ranges
2023-12-17 14:59:11 -05:00
Andrew Gunnerson 7041c8ef2c util: merge_overlapping: Skip empty and invalid ranges
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 14:50:21 -05:00
Andrew Gunnerson 7296eed51f CHANGELOG.md: Add entry for PR #230
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 00:48:36 -05:00
Andrew Gunnerson 698810d256 Merge pull request #230 from chenxiaolong/fec_update
fec: Add support for partially updating FEC data
2023-12-17 00:47:45 -05:00
Andrew Gunnerson acf57272a7 fec: Add support for partially updating FEC data
FEC data can be updated efficiently with "round" granularity when the
regions where the input file was modified are known.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-17 00:39:04 -05:00
Andrew Gunnerson 2b50e4527f CHANGELOG.md: Add entry for PR #229
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-16 23:09:09 -05:00
Andrew Gunnerson cd7b5ab23c Merge pull request #229 from chenxiaolong/partition_hashes
cli/ota: Also verify whole-partition hashes
2023-12-16 23:07:45 -05:00
Andrew Gunnerson f73c451d23 cli/ota: Also verify whole-partition hashes
Previously, when running `avbroot ota verify`, only the payload chunk
hashes were verified.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-16 22:59:33 -05:00
Andrew Gunnerson a801e18595 CHANGELOG.md: Add entry for PR #228
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-16 22:51:06 -05:00
Andrew Gunnerson 3932ff9092 Merge pull request #228 from chenxiaolong/parallel_compress
Split new partition images into chunks and compress in parallel
2023-12-16 22:49:22 -05:00
Andrew Gunnerson 1a36fbd46c Split new partition images into chunks and compress in parallel
Previously, all replacement partition images (those that have been
patched or `--replace`d) were compressed as a whole, which would be very
slow for larger images. Instead, we'll split the images into 2 MiB
chunks and compress them in parallel. This more closely matches what
AOSP's payload_generator does and scales linearly with the number of CPU
cores. The compression is less efficient, but the file size generally
only increases by 10s of KiB.

This commit also reworks the implementation so that patched images are
stored in temp files instead of in memory again. In hindsight, doing
everything in memory only made things more complex and causes the memory
usage to blow up when doing things like `--replace system <path>`.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-16 22:38:18 -05:00
Andrew Gunnerson 077a80f4ce CHANGELOG.md: Add entry for PR #226
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-12-12 21:41:30 -05:00
Andrew Gunnerson 1e43930f3c Merge pull request #226 from chenxiaolong/critical
cli/ota: Limit critical partition check to bootloader-verified partitions
2023-12-12 21:39:39 -05:00