Skip to content

Commit 81a674f

Browse files
kousuclaude
andcommitted
Update AVB hash header image_size to match unpacked original_image_size.
Fixes #8389 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9d0b529 commit 81a674f

2 files changed

Lines changed: 95 additions & 1 deletion

File tree

native/src/boot/bootimg.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,10 +1019,36 @@ void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp) {
10191019
memcpy(footer, boot.avb_footer, sizeof(AvbFooter));
10201020
footer->original_image_size = __builtin_bswap64(aosp_img_size);
10211021
footer->vbmeta_offset = __builtin_bswap64(off.vbmeta);
1022+
1023+
auto vbmeta = reinterpret_cast<AvbVBMetaImageHeader*>(out.data() + off.vbmeta);
1024+
10221025
if (check_env("PATCHVBMETAFLAG")) {
1023-
auto vbmeta = reinterpret_cast<AvbVBMetaImageHeader*>(out.data() + off.vbmeta);
10241026
vbmeta->flags = __builtin_bswap32(3);
10251027
}
1028+
1029+
// Sync hash descriptor image_size with the new AOSP portion size.
1030+
// Without this, some bootloaders (e.g. Motorola) reject images.
1031+
for (auto &desc : vbmeta->descriptors()) {
1032+
if (__builtin_bswap64(desc.tag) != AVB_DESCRIPTOR_TAG_HASH)
1033+
continue;
1034+
1035+
// enforce size limits; protect against adversarial input.
1036+
size_t buf_remaining = out.data() + out.size() - reinterpret_cast<uint8_t *>(&desc);
1037+
if (buf_remaining < __builtin_bswap64(desc.num_bytes_following) || buf_remaining - __builtin_bswap64(desc.num_bytes_following) < sizeof(AvbDescriptor)) {
1038+
// beware: both conditions are necessary because underflow in the subtraction could wrap
1039+
fprintf(stderr, "AVB hash descriptor num_bytes_following overflows buffer\n");
1040+
break;
1041+
}
1042+
1043+
if (__builtin_bswap64(desc.num_bytes_following) < sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor)) {
1044+
fprintf(stderr, "AvbDescriptor too small to hold AvbHashDescriptor\n");
1045+
break;
1046+
}
1047+
1048+
auto &hd = reinterpret_cast<AvbHashDescriptor &>(desc);
1049+
hd.image_size = __builtin_bswap64(aosp_img_size);
1050+
break;
1051+
}
10261052
}
10271053

10281054
if (boot.flags[DHTB_FLAG]) {

native/src/boot/bootimg.hpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,34 @@ struct AvbFooter {
6969
uint8_t reserved[28];
7070
} __attribute__((packed));
7171

72+
// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_descriptor.h
73+
enum AvbDescriptorTag : uint64_t {
74+
AVB_DESCRIPTOR_TAG_PROPERTY = 0,
75+
AVB_DESCRIPTOR_TAG_HASHTREE = 1,
76+
AVB_DESCRIPTOR_TAG_HASH = 2,
77+
AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE = 3,
78+
AVB_DESCRIPTOR_TAG_CHAIN_PARTITION = 4,
79+
};
80+
81+
struct AvbDescriptor {
82+
uint64_t tag;
83+
uint64_t num_bytes_following; // size of descriptor body (excludes this header); should always be a multiple of 8.
84+
} __attribute__((packed));
85+
86+
// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_hash_descriptor.h
87+
// for AvbDescriptor.tag == AVB_DESCRIPTOR_TAG_HASH
88+
struct AvbHashDescriptor {
89+
AvbDescriptor header;
90+
uint64_t image_size;
91+
uint8_t hash_algorithm[32];
92+
uint32_t partition_name_len;
93+
uint32_t salt_len;
94+
uint32_t digest_len;
95+
uint32_t flags;
96+
uint8_t reserved[60];
97+
// followed by: partition_name, salt, digest (variable length)
98+
} __attribute__((packed));
99+
72100
// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_vbmeta_image.h
73101
struct AvbVBMetaImageHeader {
74102
uint8_t magic[AVB_MAGIC_LEN];
@@ -92,8 +120,48 @@ struct AvbVBMetaImageHeader {
92120
uint32_t rollback_index_location;
93121
uint8_t release_string[AVB_RELEASE_STRING_SIZE];
94122
uint8_t reserved[80];
123+
124+
struct AvbDescriptorRange descriptors();
95125
} __attribute__((packed));
96126

127+
struct AvbDescriptorIterator {
128+
AvbDescriptor *ptr;
129+
AvbDescriptor &operator*() const { return *ptr; }
130+
AvbDescriptor *operator->() const { return ptr; }
131+
bool operator!=(const AvbDescriptorIterator &o) const {
132+
if(ptr == nullptr) return false;
133+
return ptr != o.ptr;
134+
}
135+
AvbDescriptorIterator &operator++() {
136+
if (ptr->num_bytes_following % 8 != 0) {
137+
// This is an error, a malformed image.
138+
// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_descriptor.h#60
139+
// > For padding, |num_bytes_following| is always a multiple of 8.
140+
// we can't signal an error easily, but we can stop the iteration.
141+
ptr = nullptr;
142+
return *this;
143+
}
144+
ptr = reinterpret_cast<AvbDescriptor *>(
145+
reinterpret_cast<uint8_t *>(ptr) + sizeof(AvbDescriptor) + __builtin_bswap64(ptr->num_bytes_following));
146+
return *this;
147+
}
148+
};
149+
150+
struct AvbDescriptorRange {
151+
AvbDescriptor *first, *last;
152+
AvbDescriptorIterator begin() const { return {first}; }
153+
AvbDescriptorIterator end() const { return {last}; }
154+
};
155+
156+
inline AvbDescriptorRange AvbVBMetaImageHeader::descriptors() {
157+
auto *base = reinterpret_cast<const uint8_t *>(this) + sizeof(AvbVBMetaImageHeader);
158+
base += __builtin_bswap64(authentication_data_block_size);
159+
base += __builtin_bswap64(descriptors_offset);
160+
auto *first = reinterpret_cast<AvbDescriptor *>(const_cast<uint8_t *>(base));
161+
auto *last = reinterpret_cast<AvbDescriptor *>(const_cast<uint8_t *>(base) + __builtin_bswap64(descriptors_size));
162+
return {first, last};
163+
}
164+
97165
/*********************
98166
* Boot Image Headers
99167
*********************/

0 commit comments

Comments
 (0)