summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2018-03-23 18:46:07 -0700
committerElliott Hughes <enh@google.com>2018-03-23 18:46:07 -0700
commit9724e93c196d0dbaa0e60bf45c29971a22da50c9 (patch)
tree0d3e0847bff250b168a0fcb2af431ba7fed097ee
parent4d339287080022ed67bb98949d7eb6737f8c917b (diff)
Reject .so files using ELF TLS.
Bug: http://b/74361956 Test: ran tests Change-Id: I53e71252eb08c607c2c436dcba433374c8c53887
-rw-r--r--libc/include/elf.h2
-rw-r--r--linker/linker.cpp10
-rw-r--r--tests/dlfcn_test.cpp7
-rw-r--r--tests/libs/Android.bp10
-rw-r--r--tests/libs/elf_tls_test_library.cpp19
5 files changed, 48 insertions, 0 deletions
diff --git a/libc/include/elf.h b/libc/include/elf.h
index a8d62db66..f5b209193 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -260,6 +260,8 @@ typedef Elf64_Xword Elf64_Relr;
#define DT_ANDROID_RELASZ (DT_LOOS + 5)
#define DT_GNU_HASH 0x6ffffef5
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
/* http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
#define EI_ABIVERSION 8
diff --git a/linker/linker.cpp b/linker/linker.cpp
index dd700fe88..32df9113d 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2784,6 +2784,11 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
}
}
#endif
+ if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
+ DL_ERR("unsupported ELF TLS symbol \"%s\" referenced by \"%s\"",
+ sym_name, get_realpath());
+ return false;
+ }
sym_addr = lsi->resolve_symbol_address(s);
#if !defined(__LP64__)
if (protect_segments) {
@@ -3437,6 +3442,11 @@ bool soinfo::prelink_image() {
default:
if (!relocating_linker) {
+ if (d->d_tag == DT_TLSDESC_GOT || d->d_tag == DT_TLSDESC_PLT) {
+ DL_ERR("unsupported ELF TLS DT entry in \"%s\"", get_realpath());
+ return false;
+ }
+
const char* tag_name;
if (d->d_tag == DT_RPATH) {
tag_name = "DT_RPATH";
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 46f5097a7..84f525dee 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1080,6 +1080,13 @@ TEST(dlfcn, dlopen_library_with_only_sysv_hash) {
ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname);
}
+TEST(dlfcn, dlopen_library_with_ELF_TLS) {
+ dlerror(); // Clear any pending errors.
+ void* handle = dlopen("libelf-tls-library.so", RTLD_NOW);
+ ASSERT_TRUE(handle == nullptr);
+ ASSERT_SUBSTR("unsupported ELF TLS", dlerror());
+}
+
TEST(dlfcn, dlopen_bad_flags) {
dlerror(); // Clear any pending errors.
void* handle;
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 3afda6709..ae5f78a00 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -40,6 +40,16 @@ cc_defaults {
}
// -----------------------------------------------------------------------------
+// Library to test ELF TLS
+// -----------------------------------------------------------------------------
+cc_test_library {
+ name: "libelf-tls-library",
+ defaults: ["bionic_testlib_defaults"],
+ srcs: ["elf_tls_test_library.cpp"],
+ cflags: ["-fno-emulated-tls"],
+}
+
+// -----------------------------------------------------------------------------
// Library to test gnu-styled hash
// -----------------------------------------------------------------------------
cc_test_library {
diff --git a/tests/libs/elf_tls_test_library.cpp b/tests/libs/elf_tls_test_library.cpp
new file mode 100644
index 000000000..56d0171ae
--- /dev/null
+++ b/tests/libs/elf_tls_test_library.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+thread_local int elf_tls_variable;
+
+extern "C" int* get() { return &elf_tls_variable; }