Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion native/src/boot/bootimg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1019,10 +1019,36 @@ void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp) {
memcpy(footer, boot.avb_footer, sizeof(AvbFooter));
footer->original_image_size = __builtin_bswap64(aosp_img_size);
footer->vbmeta_offset = __builtin_bswap64(off.vbmeta);

auto vbmeta = reinterpret_cast<AvbVBMetaImageHeader*>(out.data() + off.vbmeta);

if (check_env("PATCHVBMETAFLAG")) {
auto vbmeta = reinterpret_cast<AvbVBMetaImageHeader*>(out.data() + off.vbmeta);
vbmeta->flags = __builtin_bswap32(3);
}

// Sync hash descriptor image_size with the new AOSP portion size.
// Without this, some bootloaders (e.g. Motorola) reject images.
for (auto &desc : vbmeta->descriptors()) {
if (__builtin_bswap64(desc.tag) != AVB_DESCRIPTOR_TAG_HASH)
continue;
Comment thread
kousu marked this conversation as resolved.

// enforce size limits; protect against adversarial input.
size_t buf_remaining = out.data() + out.size() - reinterpret_cast<uint8_t *>(&desc);
if (buf_remaining < __builtin_bswap64(desc.num_bytes_following) || buf_remaining - __builtin_bswap64(desc.num_bytes_following) < sizeof(AvbDescriptor)) {
// beware: both conditions are necessary because underflow in the subtraction could wrap
fprintf(stderr, "AVB hash descriptor num_bytes_following overflows buffer\n");
break;
}

if (__builtin_bswap64(desc.num_bytes_following) < sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor)) {
fprintf(stderr, "AvbDescriptor too small to hold AvbHashDescriptor\n");
break;
}

auto &hd = reinterpret_cast<AvbHashDescriptor &>(desc);
hd.image_size = __builtin_bswap64(aosp_img_size);
break;
}
}

if (boot.flags[DHTB_FLAG]) {
Expand Down
68 changes: 68 additions & 0 deletions native/src/boot/bootimg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,34 @@ struct AvbFooter {
uint8_t reserved[28];
} __attribute__((packed));

// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_descriptor.h
enum AvbDescriptorTag : uint64_t {
AVB_DESCRIPTOR_TAG_PROPERTY = 0,
AVB_DESCRIPTOR_TAG_HASHTREE = 1,
AVB_DESCRIPTOR_TAG_HASH = 2,
AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE = 3,
AVB_DESCRIPTOR_TAG_CHAIN_PARTITION = 4,
};

struct AvbDescriptor {
uint64_t tag;
uint64_t num_bytes_following; // size of descriptor body (excludes this header); should always be a multiple of 8.
} __attribute__((packed));

// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_hash_descriptor.h
// for AvbDescriptor.tag == AVB_DESCRIPTOR_TAG_HASH
struct AvbHashDescriptor {
AvbDescriptor header;
uint64_t image_size;
Comment thread
kousu marked this conversation as resolved.
uint8_t hash_algorithm[32];
uint32_t partition_name_len;
uint32_t salt_len;
uint32_t digest_len;
uint32_t flags;
uint8_t reserved[60];
// followed by: partition_name, salt, digest (variable length)
} __attribute__((packed));

// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_vbmeta_image.h
struct AvbVBMetaImageHeader {
uint8_t magic[AVB_MAGIC_LEN];
Expand All @@ -92,8 +120,48 @@ struct AvbVBMetaImageHeader {
uint32_t rollback_index_location;
uint8_t release_string[AVB_RELEASE_STRING_SIZE];
uint8_t reserved[80];

struct AvbDescriptorRange descriptors();
} __attribute__((packed));

struct AvbDescriptorIterator {
AvbDescriptor *ptr;
AvbDescriptor &operator*() const { return *ptr; }
AvbDescriptor *operator->() const { return ptr; }
bool operator!=(const AvbDescriptorIterator &o) const {
if(ptr == nullptr) return false;
return ptr != o.ptr;
}
AvbDescriptorIterator &operator++() {
if (ptr->num_bytes_following % 8 != 0) {
// This is an error, a malformed image.
// https://android.googlesource.com/platform/external/avb/+/refs/heads/android11-release/libavb/avb_descriptor.h#60
// > For padding, |num_bytes_following| is always a multiple of 8.
// we can't signal an error easily, but we can stop the iteration.
ptr = nullptr;
return *this;
}
ptr = reinterpret_cast<AvbDescriptor *>(
reinterpret_cast<uint8_t *>(ptr) + sizeof(AvbDescriptor) + __builtin_bswap64(ptr->num_bytes_following));
return *this;
}
};

struct AvbDescriptorRange {
AvbDescriptor *first, *last;
AvbDescriptorIterator begin() const { return {first}; }
AvbDescriptorIterator end() const { return {last}; }
Comment thread
kousu marked this conversation as resolved.
};

inline AvbDescriptorRange AvbVBMetaImageHeader::descriptors() {
auto *base = reinterpret_cast<const uint8_t *>(this) + sizeof(AvbVBMetaImageHeader);
base += __builtin_bswap64(authentication_data_block_size);
base += __builtin_bswap64(descriptors_offset);
auto *first = reinterpret_cast<AvbDescriptor *>(const_cast<uint8_t *>(base));
auto *last = reinterpret_cast<AvbDescriptor *>(const_cast<uint8_t *>(base) + __builtin_bswap64(descriptors_size));
return {first, last};
Comment thread
kousu marked this conversation as resolved.
}

/*********************
* Boot Image Headers
*********************/
Expand Down