Merge "Fix DLEXT_WRITE_RELRO when loading multiple libs." am: 865866ee2b am: c950489599
am: ce62c05753
Change-Id: I234ee6e837fe2609918cee82121aa3994afbd4d8
diff --git a/linker/linker.cpp b/linker/linker.cpp
index c60ab6a..306b800 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3987,7 +3987,7 @@
/* 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 1aaa17f..3534287 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -831,16 +831,17 @@
* 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 @@
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 9761bc8..5d1cfc2 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -119,7 +119,7 @@
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);
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 1bc5030..3af52d4 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -450,7 +450,21 @@
fprintf(stderr, "in child: %s\n", dlerror());
exit(1);
}
- exit(0);
+ fn f = reinterpret_cast<fn>(dlsym(handle, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_EQ(4, f());
+
+ if (recursive) {
+ fn f = reinterpret_cast<fn>(dlsym(handle, "getBiggerRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_EQ(8, f());
+ }
+
+ uint32_t* taxicab_number =
+ reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
+ ASSERT_DL_NOTNULL(taxicab_number);
+ EXPECT_EQ(1729U, *taxicab_number);
+ exit(testing::Test::HasFailure());
}
// continuing in parent