Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit 94bb036

Browse files
author
F8LEFT
committed
fix file loading out bounds
1 parent d6914e6 commit 94bb036

File tree

4 files changed

+56
-33
lines changed

4 files changed

+56
-33
lines changed

ElfReader.cpp

+43-29
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,15 @@ bool ElfReader::Load() {
119119
return ReadElfHeader() &&
120120
VerifyElfHeader() &&
121121
ReadProgramHeader() &&
122+
// TODO READ dynamic from SECTION header (>= __ANDROID_API_O__)
122123
ReserveAddressSpace() &&
123124
LoadSegments() &&
124125
FindPhdr() &&
125126
PatchPhdr();
126127
}
127128

128129
bool ElfReader::ReadElfHeader() {
129-
ssize_t rc = read(fd_, &header_, sizeof(header_));
130+
ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, &header_, sizeof(header_)));
130131
if (rc < 0) {
131132
FLOGE("can't read file \"%s\": %s", name_, strerror(errno));
132133
return false;
@@ -201,30 +202,35 @@ bool ElfReader::ReadProgramHeader() {
201202
if(dump_so_file_) {
202203
auto phdr = phdr_table_;
203204
for(auto i = 0; i < phdr_num_; i++) {
204-
phdr->p_filesz = phdr->p_memsz; // expend filesize to memsiz
205205
phdr->p_paddr = phdr->p_vaddr;
206-
phdr->p_offset = phdr->p_vaddr; // elf has been loaded.
206+
phdr->p_filesz = phdr->p_memsz; // expend filesize to memsiz
207+
phdr->p_offset = phdr->p_vaddr; // since elf has been loaded. just expand file data to dump memory data
208+
// phdr->p_flags = 0 // TODO fix flags by PT_TYPE
207209
phdr++;
208210
}
209-
// fix phdr, just load all data
211+
// some shell will release data between loadable phdr(s), just load all memory data
210212
std::vector<Elf_Phdr*> loaded_phdrs;
211213
for (auto i = 0; i < phdr_num_; i++) {
212214
auto phdr = &phdr_table_[i];
213215
if(phdr->p_type != PT_LOAD) continue;
214216
loaded_phdrs.push_back(phdr);
215217
}
218+
std::sort(loaded_phdrs.begin(), loaded_phdrs.end(),
219+
[](Elf_Phdr * first, Elf_Phdr * second) {
220+
return first->p_vaddr < second->p_vaddr;
221+
});
216222
if (!loaded_phdrs.empty()) {
217223
for (unsigned long i = 0, total = loaded_phdrs.size(); i < total; i++) {
218224
auto phdr = loaded_phdrs[i];
219-
if (i != total - 1) {
220-
// to next loaded segament
221-
auto nphdr = loaded_phdrs[i+1];
222-
phdr->p_memsz = nphdr->p_vaddr - phdr->p_vaddr;
223-
} else {
224-
// to the file end
225-
phdr->p_memsz = file_size - phdr->p_vaddr;
226-
}
227-
phdr->p_filesz = phdr->p_memsz;
225+
if (i != total - 1) {
226+
// to next loaded segament
227+
auto nphdr = loaded_phdrs[i+1];
228+
phdr->p_memsz = nphdr->p_vaddr - phdr->p_vaddr;
229+
} else {
230+
// to the file end
231+
phdr->p_memsz = file_size - phdr->p_vaddr;
232+
}
233+
phdr->p_filesz = phdr->p_memsz;
228234
}
229235
}
230236
}
@@ -246,7 +252,11 @@ size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table,
246252
Elf_Addr* out_min_vaddr,
247253
Elf_Addr* out_max_vaddr)
248254
{
249-
Elf_Addr min_vaddr = 0xFFFFFFFFU;
255+
#ifdef __SO64__
256+
Elf_Addr min_vaddr = UINT64_MAX;
257+
#else
258+
Elf_Addr min_vaddr = UINT_MAX;
259+
#endif
250260
Elf_Addr max_vaddr = 0x00000000U;
251261

252262
bool found_pt_load = false;
@@ -296,8 +306,11 @@ bool ElfReader::ReserveAddressSpace() {
296306
uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
297307
// alloc map data, and load in addr
298308
uint8_t * start = new uint8_t[load_size_];
309+
memset(start, 0, load_size_);
299310

300311
load_start_ = start;
312+
// the first loaded phdr data should be loaded in the start of load_start
313+
// (load_bias_ + phdr.vaddr), so load_bias_ = load_start - phdr.vaddr(min_addr)
301314
load_bias_ = reinterpret_cast<uint8_t *>(reinterpret_cast<uintptr_t >(start)
302315
- reinterpret_cast<uintptr_t >(addr));
303316
return true;
@@ -320,23 +333,23 @@ bool ElfReader::LoadSegments() {
320333
Elf_Addr seg_start = phdr->p_vaddr;
321334
Elf_Addr seg_end = seg_start + phdr->p_memsz;
322335

323-
Elf_Addr seg_page_start = PAGE_START(seg_start);
324-
Elf_Addr seg_page_end = PAGE_END(seg_end);
336+
// Elf_Addr seg_page_start = PAGE_START(seg_start);
337+
// Elf_Addr seg_page_end = PAGE_END(seg_end);
325338

326339
Elf_Addr seg_file_end = seg_start + phdr->p_filesz;
327340

328341
// File offsets.
329342
Elf_Addr file_start = phdr->p_offset;
330343
Elf_Addr file_end = file_start + phdr->p_filesz;
331344

332-
Elf_Addr file_page_start = PAGE_START(file_start);
333-
Elf_Addr file_length = file_end - file_page_start;
345+
// Elf_Addr file_page_start = PAGE_START(file_start);
346+
Elf_Addr file_length = file_end - file_start;
334347

335348

336349
if (file_length != 0) {
337350
// memory data loading
338-
void* load_point = seg_page_start + reinterpret_cast<uint8_t *>(load_bias_);
339-
if(!LoadFileData(load_point, file_length, file_page_start)) {
351+
void* load_point = seg_start + reinterpret_cast<uint8_t *>(load_bias_);
352+
if(!LoadFileData(load_point, file_length, file_start)) {
340353
FLOGE("couldn't map \"%s\" segment %zu: %s", name_, i, strerror(errno));
341354
return false;
342355
}
@@ -345,20 +358,21 @@ bool ElfReader::LoadSegments() {
345358

346359
// if the segment is writable, and does not end on a page boundary,
347360
// zero-fill it until the page limit.
348-
if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
349-
memset(seg_file_end + reinterpret_cast<uint8_t *>(load_bias_), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
350-
}
361+
// if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
362+
// memset(seg_file_end + reinterpret_cast<uint8_t *>(load_bias_), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
363+
// }
351364

352-
seg_file_end = PAGE_END(seg_file_end);
365+
// seg_file_end = PAGE_END(seg_file_end);
353366

354367
// seg_file_end is now the first page address after the file
355368
// content. If seg_end is larger, we need to zero anything
356369
// between them. This is done by using a private anonymous
357370
// map for all extra pages.
358-
if (seg_page_end > seg_file_end) {
359-
void* load_point = (uint8_t*)load_bias_ + seg_file_end;
360-
memset(load_point, 0, seg_page_end - seg_file_end);
361-
}
371+
// since data has been clear, just skip this step
372+
// if (seg_page_end > seg_file_end) {
373+
// void* load_point = (uint8_t*)load_bias_ + seg_file_end;
374+
// memset(load_point, 0, seg_page_end - seg_file_end);
375+
// }
362376
}
363377
return true;
364378
}
@@ -661,7 +675,7 @@ bool ElfReader::CheckPhdr(uint8_t * loaded) {
661675

662676
bool ElfReader::LoadFileData(void *addr, size_t len, int offset) {
663677
lseek(fd_, offset, SEEK_SET);
664-
auto rc = read(fd_, addr, len);
678+
auto rc = TEMP_FAILURE_RETRY(read(fd_, addr, len));
665679

666680
if (rc < 0) {
667681
FLOGE("can't read file \"%s\": %s", name_, strerror(errno));

ElfReader.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef SOFIXER_ELFREADER_H
1010
#define SOFIXER_ELFREADER_H
1111

12-
#include "exelf.h"
12+
#include "macros.h"
1313

1414
#include <cstdint>
1515
#include <cstddef>

exelf.h renamed to macros.h

+10
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,14 @@ typedef Elf64_Word Elf_Word;
5050
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
5151
#endif
5252

53+
#ifndef TEMP_FAILURE_RETRY
54+
#define TEMP_FAILURE_RETRY(expression) \
55+
(__extension__\
56+
({ long int __result;\
57+
do __result = (long int)(expression);\
58+
while(__result == -1L&& errno == EINTR);\
59+
__result;}))
60+
#endif
61+
62+
5363
#endif //FAOATDUMP_EXELF_H

main.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ int main(int argc, char* argv[]) {
7575
return -1;
7676
}
7777
#ifdef __LARGE64_FILES
78-
auto fd = file->_file;
78+
auto fd = file->_file;
7979
#else
8080
auto fd = fileno(file);
8181
#endif
@@ -101,7 +101,7 @@ int main(int argc, char* argv[]) {
101101
printf("output so file cannot write !!!\n");
102102
return -1;
103103
}
104-
fwrite(elf_rebuilder.getRebuildData(), elf_rebuilder.getRebuildSize(), 1, file);
104+
fwrite(elf_rebuilder.getRebuildData(), 1, elf_rebuilder.getRebuildSize(), file);
105105
fclose(file);
106106
}
107107

@@ -120,5 +120,4 @@ void useage() {
120120
printf(" -s --source sourceFilePath Source file path\n");
121121
printf(" -o --output generateFilePath Generate file path\n");
122122
printf(" -h --help Display this information\n");
123-
124123
}

0 commit comments

Comments
 (0)