Reject .so files using ELF TLS.

Bug: http://b/74361956
Test: ran tests
Change-Id: I53e71252eb08c607c2c436dcba433374c8c53887
diff --git a/libc/include/elf.h b/libc/include/elf.h
index a8d62db..f5b2091 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -260,6 +260,8 @@
 #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 dd700fe..32df911 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2784,6 +2784,11 @@
           }
         }
 #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 @@
 
       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 46f5097..84f525d 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1080,6 +1080,13 @@
   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 3afda67..ae5f78a 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -40,6 +40,16 @@
 }
 
 // -----------------------------------------------------------------------------
+// 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 0000000..56d0171
--- /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; }