diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-02-27 13:18:00 +0000 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-04-17 14:30:46 +0100 |
commit | 183ad9df536ab04ef35a397a1f4724e4e401d11f (patch) | |
tree | 65c76a120390c1350ff1d38b725b54cabd91c06b /linker/linker.cpp | |
parent | 12bbb9164578b6512b8b07a3fb093858244b7c7b (diff) |
Allow sharing the RELRO section via a file.
Add flags and a file descriptor to android_dlopen_ext() to allow writing
the RELRO section of the loaded library to a file after relocation
processing, and to allow mapping identical pages from the file over the
top of relocated memory in another process. Explicitly comparing the
pages is required in case a page contains a reference to a symbol
defined in another library loaded at a random base address.
Bug: 13005501
Change-Id: Ibb5b2d384edfaa5acf3e97a5f8b6115c10497a1e
Diffstat (limited to 'linker/linker.cpp')
-rwxr-xr-x | linker/linker.cpp | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index 85ef63b24..40237f3fb 100755 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -65,7 +65,7 @@ * and NOEXEC */ -static bool soinfo_link_image(soinfo* si); +static bool soinfo_link_image(soinfo* si, const android_dlextinfo* extinfo); static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf); // We can't use malloc(3) in the dynamic linker. We use a linked list of anonymous @@ -760,7 +760,7 @@ static soinfo* find_library_internal(const char* name, const android_dlextinfo* TRACE("[ find_library_internal base=%p size=%zu name='%s' ]", reinterpret_cast<void*>(si->base), si->size, si->name); - if (!soinfo_link_image(si)) { + if (!soinfo_link_image(si, extinfo)) { munmap(reinterpret_cast<void*>(si->base), si->size); soinfo_free(si); return NULL; @@ -1566,7 +1566,7 @@ static int nullify_closed_stdio() { return return_value; } -static bool soinfo_link_image(soinfo* si) { +static bool soinfo_link_image(soinfo* si, const android_dlextinfo* extinfo) { /* "base" might wrap around UINT32_MAX. */ ElfW(Addr) base = si->load_bias; const ElfW(Phdr)* phdr = si->phdr; @@ -1902,6 +1902,23 @@ static bool soinfo_link_image(soinfo* si) { return false; } + /* Handle serializing/sharing the RELRO segment */ + if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) { + if (phdr_table_serialize_gnu_relro(si->phdr, si->phnum, si->load_bias, + extinfo->relro_fd) < 0) { + DL_ERR("failed serializing GNU RELRO section for \"%s\": %s", + si->name, strerror(errno)); + return false; + } + } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) { + if (phdr_table_map_gnu_relro(si->phdr, si->phnum, si->load_bias, + extinfo->relro_fd) < 0) { + DL_ERR("failed mapping GNU RELRO section for \"%s\": %s", + si->name, strerror(errno)); + return false; + } + } + notify_gdb_of_load(si); return true; } @@ -2055,7 +2072,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW( somain = si; - if (!soinfo_link_image(si)) { + if (!soinfo_link_image(si, NULL)) { __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); exit(EXIT_FAILURE); } @@ -2172,7 +2189,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) { linker_so.phnum = elf_hdr->e_phnum; linker_so.flags |= FLAG_LINKER; - if (!soinfo_link_image(&linker_so)) { + if (!soinfo_link_image(&linker_so, NULL)) { // It would be nice to print an error message, but if the linker // can't link itself, there's no guarantee that we'll be able to // call write() (because it involves a GOT reference). We may as |