aboutsummaryrefslogtreecommitdiffstats
path: root/linker
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2019-04-02 17:04:42 -0400
committerTorne (Richard Coles) <torne@google.com>2019-04-02 18:06:12 -0400
commitfa9f7f28d4d3df6b1439553ed183efd421981616 (patch)
tree7bc371b05622827a39f375a7c43201c601e72b6d /linker
parente6fd53b751c253ce9315875bed838a6d549132f3 (diff)
downloadandroid_bionic-fa9f7f28d4d3df6b1439553ed183efd421981616.tar.gz
android_bionic-fa9f7f28d4d3df6b1439553ed183efd421981616.tar.bz2
android_bionic-fa9f7f28d4d3df6b1439553ed183efd421981616.zip
Fix DLEXT_WRITE_RELRO when loading multiple libs.
ANDROID_DLEXT_WRITE_RELRO was causing the GNU RELRO sections of libraries to become corrupted if more than one library was being loaded at once (i.e. if the root library has DT_NEEDED entries for libraries that weren't already loaded). The file offset was not being correctly propagated between calls, so after writing out the (correct) RELRO data to the file, it was mapping the data at file offset 0 for all libraries, which corrupted the data for all but one of the libraries. Fix this by passing file_offset as a pointer the same way that phdr_table_map_gnu_relro does. Bug: 128623590 Test: tbd Change-Id: I196cd336bd5a67454e89fd85487356b1c7856871
Diffstat (limited to 'linker')
-rw-r--r--linker/linker.cpp2
-rw-r--r--linker/linker_phdr.cpp9
-rw-r--r--linker/linker_phdr.h2
3 files changed, 7 insertions, 6 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index c60ab6a50..306b80014 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3987,7 +3987,7 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
/* Handle serializing/sharing the RELRO segment */
if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
- extinfo->relro_fd) < 0) {
+ extinfo->relro_fd, relro_fd_offset) < 0) {
DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 1aaa17f82..353428730 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -831,16 +831,17 @@ int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table,
* phdr_count -> number of entries in tables
* load_bias -> load bias
* fd -> writable file descriptor to use
+ * file_offset -> pointer to offset into file descriptor to use/update
* Return:
* 0 on error, -1 on failure (error code in errno).
*/
int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table,
size_t phdr_count,
ElfW(Addr) load_bias,
- int fd) {
+ int fd,
+ size_t* file_offset) {
const ElfW(Phdr)* phdr = phdr_table;
const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
- ssize_t file_offset = 0;
for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
if (phdr->p_type != PT_GNU_RELRO) {
@@ -856,11 +857,11 @@ int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table,
return -1;
}
void* map = mmap(reinterpret_cast<void*>(seg_page_start), size, PROT_READ,
- MAP_PRIVATE|MAP_FIXED, fd, file_offset);
+ MAP_PRIVATE|MAP_FIXED, fd, *file_offset);
if (map == MAP_FAILED) {
return -1;
}
- file_offset += size;
+ *file_offset += size;
}
return 0;
}
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 9761bc8ca..5d1cfc2bd 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -119,7 +119,7 @@ int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count
ElfW(Addr) load_bias);
int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
- ElfW(Addr) load_bias, int fd);
+ ElfW(Addr) load_bias, int fd, size_t* file_offset);
int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
ElfW(Addr) load_bias, int fd, size_t* file_offset);