diff options
-rw-r--r-- | libc/include/elf.h | 2 | ||||
-rw-r--r-- | linker/linker.cpp | 10 | ||||
-rw-r--r-- | tests/dlfcn_test.cpp | 7 | ||||
-rw-r--r-- | tests/libs/Android.bp | 10 | ||||
-rw-r--r-- | tests/libs/elf_tls_test_library.cpp | 19 |
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; } |