Skip to content
Closed
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
23 changes: 19 additions & 4 deletions src/elf_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,18 @@ static int64_t sleb128_decode(struct sleb128_decoder *decoder) {
const size_t size = sizeof(int64_t) * CHAR_BIT;

do {
if (decoder->current >= decoder->end)
LOGF("Failed to decode SLEB128: buffer overrun");
if (decoder->current >= decoder->end) {
LOGF("Failed to decode SLEB128: buffer overrun");
return 0;
}
Comment on lines +83 to +86

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since our LOGF doesn't abort like AOSP's async_safe_fatal, the return 0 is necessary to prevent OOB reads. Do you think we should keep it for safety, or would you prefer a different way to handle this?


byte = *decoder->current++;
value |= ((int64_t)(byte & 0x7F)) << shift;
shift += 7;
if (shift > size) {
LOGF("SLEB128 shift overflow");
return 0;
}
Comment on lines +91 to +94

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^
|

} while (byte & 0x80);

if (shift < size && (byte & 0x40)) {
Expand Down Expand Up @@ -327,8 +333,9 @@ static bool elfutil_unpack_android_relocs(const struct elf_image *elf, struct an
struct sleb128_decoder decoder;
sleb128_decoder_init(&decoder, (const uint8_t *)elf->rel_android_, elf->rel_android_size_);

uint64_t num_relocs = sleb128_decode(&decoder);
if (num_relocs <= 0) return false;
int64_t num_relocs_signed = sleb128_decode(&decoder);
if (num_relocs_signed <= 0) return false;
uint64_t num_relocs = (uint64_t)num_relocs_signed;
Comment on lines +336 to +338

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see about that, but there should be no case where it will ever go below 0

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If sleb128_decode returns -1 due to corruption
uint64_t num_relocs = (int64_t)(-1); // → 0xFFFFFFFFFFFFFFFF
if (num_relocs <= 0) // unsigned compare: always false
The check silently passes and calloc(0xFFFFFFFFFFFFFFFF, ...) gets called. The type mismatch is the bug regardless of intent.


size_t out_index = 0;
void *entries = calloc(num_relocs, elf->rel_android_is_rela_ ? sizeof(ElfW(Rela)) : sizeof(ElfW(Rel)));
Expand Down Expand Up @@ -397,6 +404,14 @@ static bool elfutil_unpack_android_relocs(const struct elf_image *elf, struct an
if (elf->rel_android_is_rela_ && group_flags_reloc == RELOCATION_GROUP_HAS_ADDEND_FLAG)
r_addend += sleb128_decode(&decoder);

if (out_index >= num_relocs) {
LOGE("out_index exceeded num_relocs");

free(entries);

return false;
}
Comment on lines +407 to +413

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow the project coding style. There should be empty new lines between the LOGE, free and return, moreover the "Android reloc: " shouldn't exist

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, will fix the formatting.


if (elf->rel_android_is_rela_) {
ElfW(Rela) *rela = (ElfW(Rela) *)entries;
rela[out_index].r_offset = current_offset;
Expand Down
4 changes: 3 additions & 1 deletion src/plti.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ static bool plti_internal_set_got_entry(struct elf_info *info, uintptr_t got_add
if (!stash) {
/* INFO: Don't call LOGE -- or else it will try to access GOT while it's being modified */
void *hint = find_high_backup_hint(vma_len);
void *backup_addr = mmap(hint, vma_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
void *backup_addr = MAP_FAILED;
if (hint)
backup_addr = mmap(hint, vma_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (backup_addr == MAP_FAILED) {
backup_addr = mmap(NULL, vma_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (backup_addr == MAP_FAILED) {
Expand Down
Loading