2.4. AVB enforcement code path (LoadImageAndAuth / libavb)¶
This page documents the runtime Android Verified Boot enforcement inside ABL:
the LoadImageAndAuth → avb_slot_verify call path, how the device
lock-state gates it, rollback-index handling, the per-result failure behavior
(halt vs warn-and-continue), the boot-state colour it sets, and the
DeviceInfo lock-state code it reads. It is deliberately scoped to the code:
the AVB metadata (
vbmetacontents, signing keys, descriptor digests) and why the whole chain is bypassable live in Secure boot and image signing;the
devinfostruct layout and byte offsets are below, in DeviceInfo lock-state enforcement (DeviceInfo.c);the fastboot command surface (no
oem unlock) lives in ABL overview, key handling, fastboot.
This page cross-references those and does not restate them. RVAs are
LinuxLoader-relative (= DXE file offset − 0xb8).
2.4.1. LoadImageAndAuth (VB2 core, RVA 0x5398)¶
LinuxLoaderEntry calls LoadImageAndAuth before BootLinux
(ABL entry point and top-level orchestration). The device runs AVB 2.0, so control enters
LoadImageAndAuthVB2 (source
QcomModulePkg/Library/avb/VerifiedBoot.c). radare2 merges this function with
its file-local helpers (ResultShouldContinue, ComputeVbMetaDigest, the
boot-state switch) into one large function at RVA 0x5398 — identified
unambiguously by its string set (Total loaded partition %d,
androidboot.verifiedbootstate=, the corrupt-device message, the
AvbSlotVerify returned logs). Pipeline:
Step |
Behavior / binary basis |
|---|---|
Lock-state gate |
|
Rollback pre-check |
|
|
The libavb entry that hashes/verifies each requested partition. See The avb_slot_verify call path. |
Result handling |
Branch on |
Boot-state colour |
Set GREEN / YELLOW / ORANGE / RED and push ROT to Keymaster. See Boot state, ROT and command line. |
Boot-state menu |
RED halts; YELLOW/ORANGE/EIO warn then continue. See Boot-state menu. |
2.4.2. Lock-state gate¶
Everything hinges on IsUnlocked () (DeviceInfo.c), which returns
DevInfo.is_unlocked. This unit reads is_unlocked = 0 → locked
(Secure boot and image signing, decoded below). In
LoadImageAndAuthVB2:
AllowVerificationError = IsUnlocked ();
VerifyFlags = AllowVerificationError
? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
: AVB_SLOT_VERIFY_FLAGS_NONE;
So on this locked device avb_slot_verify runs in strict mode: any
verification failure is fatal (see Failure behavior). But this ABL is
test-key-signed (Secure boot and image signing), and as far as the stock code
goes, nothing in it would prevent a patched ABL from reporting
is_unlocked = 0 while skipping the check entirely — a bypass that has
not been empirically verified by actually flashing such a patched image.
2.4.3. The avb_slot_verify call path¶
avb_slot_verify (libavb, RVA 0x8478) is the verification engine. The
libavb sources compile to a self-contained cluster in .text, each file
identifiable by its ASSERT path string:
RVA |
libavb file |
Role |
|---|---|---|
|
|
Top-level slot verify: walk requested partitions, load vbmeta, chain, and
assemble |
|
|
Per-partition helper (recursive chain/hash-descriptor load). |
|
|
|
|
|
RSA signature verification of the vbmeta hash. |
|
|
Whole-image hash descriptor (boot/dtbo/recovery) validation. |
|
|
Chain-partition descriptor (delegates |
|
|
Kernel-cmdline descriptor → the |
|
property / descriptor / footer / util |
Descriptor iteration, footer parse, byte-swap/util helpers. |
The descriptor set here matches the vbmeta_a structure documented in
Secure boot and image signing (chain → vbmeta_system; hash descriptors for
boot/dtbo/recovery; two hashtree descriptors). This is the code that
consumes that metadata; the metadata’s validity is analysed there.
2.4.4. Rollback-index handling¶
ABL does not store rollback indices itself. avb_should_update_rollback
gates a call into TrustZone that owns the rollback versions:
“Check if slot is bootable and call into TZ to update rollback version … the secure environment make the decision on updating rollback version”
(source comment, VerifiedBoot.c ~line 1162). The avb_slot_verify result
AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is one of the failure codes
handled below; the stored rollback counters live in TZ/QFPROM, not in any
partition (Open questions and limits of analysis), so their live values are not statically
recoverable from this dump.
2.4.5. Failure behavior¶
After avb_slot_verify returns, the result is classified by the inlined
ResultShouldContinue and combined with the lock state:
|
|
Effect |
|---|---|---|
|
False |
Fatal even when unlocked → |
|
True |
Continue only if unlocked ( |
|
True |
Verified. |
So the branch is: locked + any non-OK result → RED (the
ERROR: Device State Locked, AvbSlotVerify returned %a path); unlocked +
continuable result → warn and proceed (State: Unlocked, AvbSlotVerify
returned %a, continue boot); a small class of structural errors (OOM/IO/…)
halts regardless of lock state.
2.4.6. Boot state, ROT and command line¶
On success the colour is chosen purely from lock state and key origin:
if (AllowVerificationError) Info->BootState = ORANGE; // unlocked
else if (UserData->IsUserKey) Info->BootState = YELLOW; // locked, custom key
else Info->BootState = GREEN; // locked, OEM key
The colour, the unlocked flag and the public key are pushed to Keymaster as the
Root-of-Trust (Data.Color / Data.IsUnlocked / Data.PublicKey), and
AppendVBCommonCmdLine / AppendVBCmdLine build the
androidboot.verifiedbootstate=… command line that
Kernel/DTB/ramdisk load and the kernel hand-off splices in as VBCmdLine. On a stock locked boot
this device is GREEN (OEM key, locked) — consistent with the release-keys
AVB metadata in Secure boot and image signing.
2.4.8. DeviceInfo lock-state enforcement (DeviceInfo.c)¶
The lock state the AVB gate reads is managed by DeviceInfo.c:
IsUnlocked ()/IsUnlockCritical ()return the cachedDevInfobooleans, populated byDeviceInfoInitviaReadWriteDeviceInfo (READ_CONFIG, …)from thedevinfopartition.On first init the
DEVICE_MAGIC("ANDROID-BOOT!") is checked; if absent the struct is (re)written withis_unlocked = FALSE/is_unlock_critical = FALSEby default (theTARGET_DEFINITIONunlocked default is not taken here).SetDeviceUnlockValue/ the unlock-critical setter are the only writers of the lock booleans, each guarded (if (IsUnlocked () != State)) and persisted withReadWriteDeviceInfo (WRITE_CONFIG, …).
These setters are the enforcement point, but on this build no fastboot command reaches them (next section).
2.4.8.1. devinfo.bin struct — byte offsets and values on this unit¶
The ABL device_info RAM struct (RVA 0x60618) is a 1:1 image of
devinfo.bin (LUN4, 4 KB), magic ANDROID-BOOT! at +0. Getters exist
only for three fields:
Offset |
Field |
Value on this unit |
|---|---|---|
|
|
byte 13 = 0 (LOCKED) |
|
|
byte 14 = 0 |
|
|
byte 15 = 1 (ENABLED) |
There is no is_tampered/is_verified byte in this struct — byte 15 is
charger_screen_enabled, not a tamper flag; do not confuse the two. The
rollback-index fields elsewhere in the struct
are all-zero on this unit (factory state) — see Rollback-index handling
above for where the live rollback counters actually live (TZ/QFPROM, not this
struct’s cache). ABL also sets HLOS tamper fuses via KeyMaster
(TZ_HLOS_IMG_TAMPER_FUSE, KeyMasterSetRotAndBootState) — a separate
anti-rollback path from the AVB rollback-index mechanism above. The lock state
here is independent of the QFPROM SEC_BOOT fuse — the device reports
“locked” while the chain is still test-key-signed (Secure boot and image signing).
2.4.10. Provenance¶
- Source:
../artifacts/abl_a/abl_dxe_fv.bin(RVA0x5398LoadImageAndAuthVB2+ boot-state dispatch; libavb cluster0x8478/0xad74/0xcf88/0xfdc8/0xf4dc/0xe48c/0xf4f4…; unlock plumbing0x1fa00/0x2fe3c). Structural correlation againstQcomModulePkg/Library/avb/VerifiedBoot.c,libavb/*,QcomModulePkg/Library/BootLib/DeviceInfo.c,VerifiedBootMenu.c,UnlockMenu.cat CodeLinaro tagLA.UM.9.12.1.r2-05100-SMxx50.QSSI12.0(QSSI12; version gap is an open question — ABL function map and upstream-source correlation, Open questions and limits of analysis).- Method:
functions located by embedded ASSERT source paths and DEBUG strings (AArch64
adrp/addliterals resolved with Capstone); the lock-state gate,ResultShouldContinueclassification, colour selection and boot-state switch read fromVerifiedBoot.cand matched to the0x5398body.IsUnlocked/SetDeviceUnlockValuesemantics fromDeviceInfo.c. The0x5398boundary merge is a radare2 auto-analysis artifact.- Cross-refs:
Secure boot and image signing (AVB metadata, keys, why unenforced), ABL overview, key handling, fastboot (fastboot surface, no unlock command), ABL entry point and top-level orchestration (caller), Kernel/DTB/ramdisk load and the kernel hand-off (
VBCmdLineconsumer), ABL function map and upstream-source correlation (function inventory).