From 96be7205dce97977909e93b73f48779fcce3bc65 Mon Sep 17 00:00:00 2001 From: Hristo Bojinov Date: Mon, 2 Aug 2010 10:26:17 -0700 Subject: Working ASLR implementation. ASLR for shared libraries is controlled by "-a" in ota_from_target_files. Binary files are self-contained (supported by apriori/soslim). Signed-off-by: Hristo Bojinov Change-Id: I500e325bf4a70a8d69a2ab9b2938e83dadb4e65d --- tools/soslim/main.c | 18 +++++++- tools/soslim/prelink_info.c | 101 ++++++++++++++++++++++++++++++++++++++++++-- tools/soslim/prelink_info.h | 4 ++ tools/soslim/soslim.c | 10 ++++- tools/soslim/soslim.h | 5 ++- 5 files changed, 131 insertions(+), 7 deletions(-) (limited to 'tools/soslim') diff --git a/tools/soslim/main.c b/tools/soslim/main.c index dd8a60bb7..e23fbcec7 100644 --- a/tools/soslim/main.c +++ b/tools/soslim/main.c @@ -188,9 +188,13 @@ int main(int argc, char **argv) else INFO("Not building symbol filter, filter file is empty.\n"); } #ifdef SUPPORT_ANDROID_PRELINK_TAGS - int prelinked = 0; + int prelinked = 0, retouched = 0; int elf_little; /* valid if prelinked != 0 */ long prelink_addr; /* valid if prelinked != 0 */ +#define RETOUCH_MAX_SIZE 500000 + /* _cnt valid if retouched != 0 */ + unsigned int retouch_byte_cnt = RETOUCH_MAX_SIZE; + char retouch_buf[RETOUCH_MAX_SIZE]; /* valid if retouched != 0 */ #endif clone_elf(elf, newelf, infile, outfile, @@ -200,7 +204,10 @@ int main(int argc, char **argv) #ifdef SUPPORT_ANDROID_PRELINK_TAGS , &prelinked, &elf_little, - &prelink_addr + &prelink_addr, + &retouched, + &retouch_byte_cnt, + retouch_buf #endif , true, /* rebuild the section-header-strings table */ @@ -223,6 +230,13 @@ int main(int argc, char **argv) infile, strerror(errno), errno); #ifdef SUPPORT_ANDROID_PRELINK_TAGS + if (retouched) { + INFO("File has retouch data, putting it back in place.\n"); + retouch_dump(outfile != NULL ? outfile : infile, + elf_little, + retouch_byte_cnt, + retouch_buf); + } if (prelinked) { INFO("File is prelinked, putting prelink TAG back in place.\n"); setup_prelink_info(outfile != NULL ? outfile : infile, diff --git a/tools/soslim/prelink_info.c b/tools/soslim/prelink_info.c index 81d5de304..2600ac73b 100644 --- a/tools/soslim/prelink_info.c +++ b/tools/soslim/prelink_info.c @@ -11,6 +11,7 @@ #include #include +#define RETOUCH_SUFFIX_SIZE 12 typedef struct { uint32_t mmap_addr; char tag[4]; /* 'P', 'R', 'E', ' ' */ @@ -28,7 +29,7 @@ static inline void set_prelink(long *prelink_addr, } else { /* Different endianness */ - *prelink_addr = switch_endianness(info->mmap_addr); + *prelink_addr = switch_endianness(info->mmap_addr); } } } @@ -67,10 +68,104 @@ int check_prelinked(const char *fname, int elf_little, long *prelink_addr) set_prelink(prelink_addr, elf_little, &info); prelinked = 1; } - FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); + FAILIF(close(fd) < 0, + "close(%d): %s (%d)!\n", fd, strerror(errno), errno); return prelinked; } +int check_retouched(const char *fname, int elf_little, + unsigned int *retouch_byte_cnt, char *retouch_buf) { + FAILIF(sizeof(prelink_info_t) != 8, + "Unexpected sizeof(prelink_info_t) == %d!\n", + sizeof(prelink_info_t)); + int fd = open(fname, O_RDONLY); + FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n", + fname, strerror(errno), errno); + off_t end = lseek(fd, 0, SEEK_END); + int nr = sizeof(prelink_info_t); + off_t sz = lseek(fd, -nr-RETOUCH_SUFFIX_SIZE, SEEK_CUR); + ASSERT((long)(end - sz) == (long)(nr+RETOUCH_SUFFIX_SIZE)); + FAILIF(sz == (off_t)-1, + "lseek(%d, 0, SEEK_END): %s (%d)!\n", + fd, strerror(errno), errno); + + char retouch_meta[RETOUCH_SUFFIX_SIZE]; + int num_read = read(fd, &retouch_meta, RETOUCH_SUFFIX_SIZE); + FAILIF(num_read < 0, + "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n", + fd, strerror(errno), errno); + FAILIF(num_read != RETOUCH_SUFFIX_SIZE, + "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as " + "expected (read %d)!\n", + fd, RETOUCH_SUFFIX_SIZE, num_read); + + int retouched = 0; + if (!strncmp(retouch_meta, "RETOUCH ", 8)) { + unsigned int retouch_byte_cnt_meta; + if (!(elf_little ^ is_host_little())) + retouch_byte_cnt_meta = *(unsigned int *)(retouch_meta+8); + else + retouch_byte_cnt_meta = + switch_endianness(*(unsigned int *)(retouch_meta+8)); + FAILIF(*retouch_byte_cnt < retouch_byte_cnt_meta, + "Retouch buffer too small at %d bytes (%d needed).", + *retouch_byte_cnt, retouch_byte_cnt_meta); + *retouch_byte_cnt = retouch_byte_cnt_meta; + off_t sz = lseek(fd, + -((long)*retouch_byte_cnt)-RETOUCH_SUFFIX_SIZE-nr, + SEEK_END); + ASSERT((long)(end - sz) == + (long)(*retouch_byte_cnt+RETOUCH_SUFFIX_SIZE+nr)); + FAILIF(sz == (off_t)-1, + "lseek(%d, 0, SEEK_END): %s (%d)!\n", + fd, strerror(errno), errno); + num_read = read(fd, retouch_buf, *retouch_byte_cnt); + FAILIF(num_read < 0, + "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n", + fd, strerror(errno), errno); + FAILIF(num_read != *retouch_byte_cnt, + "read(%d, retouch_buf, %u): did not read %d bytes as " + "expected (read %d)!\n", + fd, *retouch_byte_cnt, *retouch_byte_cnt, num_read); + + retouched = 1; + } + FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); + return retouched; +} + +void retouch_dump(const char *fname, int elf_little, + unsigned int retouch_byte_cnt, char *retouch_buf) { + int fd = open(fname, O_WRONLY); + FAILIF(fd < 0, + "open(%s, O_WRONLY): %s (%d)\n", + fname, strerror(errno), errno); + off_t sz = lseek(fd, 0, SEEK_END); + FAILIF(sz == (off_t)-1, + "lseek(%d, 0, SEEK_END): %s (%d)!\n", + fd, strerror(errno), errno); + + // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte + // size of the retouch blob, in target endianness. + strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8); + if (elf_little ^ is_host_little()) { + *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) = + switch_endianness(retouch_byte_cnt); + } else { + *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) = + retouch_byte_cnt; + } + + int num_written = write(fd, retouch_buf, retouch_byte_cnt+12); + FAILIF(num_written < 0, + "write(%d, &info, sizeof(info)): %s (%d)\n", + fd, strerror(errno), errno); + FAILIF((retouch_byte_cnt+12) != num_written, + "Could not write %d bytes as expected (wrote %d bytes instead)!\n", + retouch_byte_cnt, num_written); + FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); +} + void setup_prelink_info(const char *fname, int elf_little, long base) { FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t)); @@ -92,7 +187,7 @@ void setup_prelink_info(const char *fname, int elf_little, long base) else { /* Different endianness */ INFO("Host and ELF file [%s] have different endianness.\n", fname); - info.mmap_addr = switch_endianness(base); + info.mmap_addr = switch_endianness(base); } strncpy(info.tag, "PRE ", 4); diff --git a/tools/soslim/prelink_info.h b/tools/soslim/prelink_info.h index e2787cb04..efa84fdab 100644 --- a/tools/soslim/prelink_info.h +++ b/tools/soslim/prelink_info.h @@ -3,6 +3,10 @@ #ifdef SUPPORT_ANDROID_PRELINK_TAGS int check_prelinked(const char *fname, int elf_little, long *prelink_addr); +int check_retouched(const char *fname, int elf_little, + unsigned int *retouch_byte_cnt, char *retouch_buf); +void retouch_dump(const char *fname, int elf_little, + unsigned int retouch_byte_cnt, char *retouch_buf); void setup_prelink_info(const char *fname, int elf_little, long base); #endif diff --git a/tools/soslim/soslim.c b/tools/soslim/soslim.c index 125e29e89..33b1ee700 100644 --- a/tools/soslim/soslim.c +++ b/tools/soslim/soslim.c @@ -27,7 +27,10 @@ void clone_elf(Elf *elf, Elf *newelf, #ifdef SUPPORT_ANDROID_PRELINK_TAGS , int *prelinked, int *elf_little, - long *prelink_addr + long *prelink_addr, + int *retouched, + unsigned int *retouch_byte_cnt, + char *retouch_buf #endif , bool rebuild_shstrtab, bool strip_debug, @@ -70,6 +73,11 @@ void clone_elf(Elf *elf, Elf *newelf, ASSERT(elf_little); *elf_little = (ehdr->e_ident[EI_DATA] == ELFDATA2LSB); *prelinked = check_prelinked(elf_name, *elf_little, prelink_addr); + ASSERT(retouched); + ASSERT(retouch_byte_cnt); + ASSERT(retouch_buf); + *retouched = check_retouched(elf_name, *elf_little, + retouch_byte_cnt, retouch_buf); #endif INFO("\n\nCALCULATING MODIFICATIONS\n\n"); diff --git a/tools/soslim/soslim.h b/tools/soslim/soslim.h index dfcb0856b..952c960f3 100644 --- a/tools/soslim/soslim.h +++ b/tools/soslim/soslim.h @@ -23,7 +23,10 @@ void clone_elf(Elf *elf, Elf *newelf, #ifdef SUPPORT_ANDROID_PRELINK_TAGS , int *prelinked, int *elf_little, - long *prelink_addr + long *prelink_addr, + int *retouched, + unsigned int *retouch_byte_cnt, + char *retouch_buf #endif , bool rebuild_shstrtab, bool strip_debug, -- cgit v1.2.3