1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <dlfcn.h>
30 #include <gtest/gtest.h>
31 #include <link.h>
32 
33 #include <thread>
34 
35 #include "gtest_globals.h"
36 #include "platform/bionic/tls.h"
37 #include "utils.h"
38 
39 #if defined(__BIONIC__)
40 #include "bionic/pthread_internal.h"
41 #endif
42 
43 // Access libtest_elftls_shared_var.so's TLS variable using an IE access.
44 __attribute__((tls_model("initial-exec"))) extern "C" __thread int elftls_shared_var;
45 
TEST(elftls_dl,dlopen_shared_var_ie)46 TEST(elftls_dl, dlopen_shared_var_ie) {
47   // libtest_elftls_shared_var_ie.so can be dlopen'ed, even though it contains a
48   // TLS IE access, because its IE access references a TLS variable from
49   // libtest_elftls_shared_var.so, which is DT_NEEDED by the executable. This
50   // pattern appears in sanitizers, which use TLS IE instrumentation in shared
51   // objects to access special variables exported from the executable or from a
52   // preloaded solib.
53   void* lib = dlopen("libtest_elftls_shared_var_ie.so", RTLD_LOCAL | RTLD_NOW);
54   ASSERT_NE(nullptr, lib);
55 
56   auto bump_shared_var = reinterpret_cast<int(*)()>(dlsym(lib, "bump_shared_var"));
57   ASSERT_NE(nullptr, bump_shared_var);
58 
59   ASSERT_EQ(21, ++elftls_shared_var);
60   ASSERT_EQ(22, bump_shared_var());
61 
62   std::thread([bump_shared_var] {
63     ASSERT_EQ(21, ++elftls_shared_var);
64     ASSERT_EQ(22, bump_shared_var());
65   }).join();
66 }
67 
TEST(elftls_dl,dlopen_ie_error)68 TEST(elftls_dl, dlopen_ie_error) {
69   std::string helper = GetTestlibRoot() +
70       "/elftls_dlopen_ie_error_helper/elftls_dlopen_ie_error_helper";
71   std::string src_path = GetTestlibRoot() + "/libtest_elftls_shared_var_ie.so";
72   std::string dst_path = GetTestlibRoot() + "/libtest_elftls_shared_var.so";
73 #if defined(__BIONIC__)
74   std::string error =
75       "dlerror: dlopen failed: TLS symbol \"elftls_shared_var\" in dlopened \"" + dst_path + "\" " +
76       "referenced from \"" + src_path + "\" using IE access model\n";
77 #else
78   // glibc will reserve some surplus static TLS memory, allowing this test to pass.
79   std::string error = "success\n";
80 #endif
81 
82   chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
83   ExecTestHelper eth;
84   eth.SetArgs({ helper.c_str(), nullptr });
85   eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, error.c_str());
86 }
87 
88 // Use a GD access (__tls_get_addr or TLSDESC) to modify a variable in static
89 // TLS memory.
TEST(elftls_dl,access_static_tls)90 TEST(elftls_dl, access_static_tls) {
91   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
92   ASSERT_NE(nullptr, lib);
93 
94   auto bump_shared_var = reinterpret_cast<int(*)()>(dlsym(lib, "bump_shared_var"));
95   ASSERT_NE(nullptr, bump_shared_var);
96 
97   ASSERT_EQ(21, ++elftls_shared_var);
98   ASSERT_EQ(22, bump_shared_var());
99 
100   std::thread([bump_shared_var] {
101     ASSERT_EQ(21, ++elftls_shared_var);
102     ASSERT_EQ(22, bump_shared_var());
103   }).join();
104 }
105 
TEST(elftls_dl,bump_local_vars)106 TEST(elftls_dl, bump_local_vars) {
107   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
108   ASSERT_NE(nullptr, lib);
109 
110   auto bump_local_vars = reinterpret_cast<int(*)()>(dlsym(lib, "bump_local_vars"));
111   ASSERT_NE(nullptr, bump_local_vars);
112 
113   ASSERT_EQ(42, bump_local_vars());
114   std::thread([bump_local_vars] {
115     ASSERT_EQ(42, bump_local_vars());
116   }).join();
117 }
118 
119 extern "C" int* missing_weak_tls_addr();
120 
121 // The Bionic linker resolves a TPREL relocation to an unresolved weak TLS
122 // symbol to 0, which is added to the thread pointer. N.B.: A TPREL relocation
123 // in a static executable is resolved by the static linker instead, and static
124 // linker behavior varies (especially with bfd and gold). See
125 // https://bugs.llvm.org/show_bug.cgi?id=40570.
TEST(elftls_dl,tprel_missing_weak)126 TEST(elftls_dl, tprel_missing_weak) {
127   ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
128   std::thread([] {
129     ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
130   }).join();
131 }
132 
133 // The behavior of accessing an unresolved weak TLS symbol using a dynamic TLS
134 // relocation depends on which kind of implementation the target uses. With
135 // TLSDESC, the result is NULL. With __tls_get_addr, the result is the
136 // generation count (or maybe undefined behavior)? This test only tests TLSDESC.
TEST(elftls_dl,tlsdesc_missing_weak)137 TEST(elftls_dl, tlsdesc_missing_weak) {
138 #if defined(__aarch64__)
139   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
140   ASSERT_NE(nullptr, lib);
141 
142   auto missing_weak_dyn_tls_addr = reinterpret_cast<int*(*)()>(dlsym(lib, "missing_weak_dyn_tls_addr"));
143   ASSERT_NE(nullptr, missing_weak_dyn_tls_addr);
144 
145   ASSERT_EQ(nullptr, missing_weak_dyn_tls_addr());
146   std::thread([missing_weak_dyn_tls_addr] {
147     ASSERT_EQ(nullptr, missing_weak_dyn_tls_addr());
148   }).join();
149 #else
150   GTEST_SKIP() << "This test is only run on TLSDESC-based targets";
151 #endif
152 }
153 
TEST(elftls_dl,dtv_resize)154 TEST(elftls_dl, dtv_resize) {
155 #if defined(__BIONIC__)
156 #define LOAD_LIB(soname) ({                           \
157     auto lib = dlopen(soname, RTLD_LOCAL | RTLD_NOW); \
158     ASSERT_NE(nullptr, lib);                          \
159     reinterpret_cast<int(*)()>(dlsym(lib, "bump"));   \
160   })
161 
162   auto dtv = []() -> TlsDtv* { return __get_tcb_dtv(__get_bionic_tcb()); };
163 
164   static_assert(sizeof(TlsDtv) == 3 * sizeof(void*),
165                 "This test assumes that the Dtv has a 3-word header");
166 
167   // Initially there are 4 modules:
168   //  - the main test executable
169   //  - libc
170   //  - libtest_elftls_shared_var
171   //  - libtest_elftls_tprel
172 
173   // The initial DTV is an empty DTV with no generation and a size of 0.
174   TlsDtv* zero_dtv = dtv();
175   ASSERT_EQ(0u, zero_dtv->count);
176   ASSERT_EQ(nullptr, zero_dtv->next);
177   ASSERT_EQ(kTlsGenerationNone, zero_dtv->generation);
178 
179   // Load the fifth module.
180   auto func1 = LOAD_LIB("libtest_elftls_dynamic_filler_1.so");
181   ASSERT_EQ(101, func1());
182 
183   // After loading one module, the DTV should be initialized to the next
184   // power-of-2 size (including the header).
185   TlsDtv* initial_dtv = dtv();
186   ASSERT_EQ(5u, initial_dtv->count);
187   ASSERT_EQ(zero_dtv, initial_dtv->next);
188   ASSERT_LT(0u, initial_dtv->generation);
189 
190   // Load module 6.
191   auto func2 = LOAD_LIB("libtest_elftls_dynamic_filler_2.so");
192   ASSERT_EQ(102, func1());
193 
194 #if defined(__aarch64__)
195   // The arm64 TLSDESC resolver doesn't update the DTV if it is new enough for
196   // the given access.
197   ASSERT_EQ(5u, dtv()->count);
198 #else
199   // __tls_get_addr updates the DTV anytime the generation counter changes.
200   ASSERT_EQ(13u, dtv()->count);
201 #endif
202 
203   ASSERT_EQ(201, func2());
204   TlsDtv* new_dtv = dtv();
205   ASSERT_NE(initial_dtv, new_dtv);
206   ASSERT_EQ(initial_dtv, new_dtv->next);
207   ASSERT_EQ(13u, new_dtv->count);
208 
209   // Load module 7.
210   auto func3 = LOAD_LIB("libtest_elftls_dynamic_filler_3.so");
211   ASSERT_EQ(103, func1());
212   ASSERT_EQ(202, func2());
213   ASSERT_EQ(301, func3());
214 
215   ASSERT_EQ(new_dtv, dtv());
216 
217 #undef LOAD_LIB
218 #else
219   GTEST_SKIP() << "test doesn't apply to glibc";
220 #endif
221 }
222 
223 // Verify that variables are reset to their initial values after the library
224 // containing them is closed.
TEST(elftls_dl,dlclose_resets_values)225 TEST(elftls_dl, dlclose_resets_values) {
226   for (int round = 0; round < 2; ++round) {
227     void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
228     ASSERT_NE(nullptr, lib);
229 
230     auto bump_local_vars = reinterpret_cast<int(*)()>(dlsym(lib, "bump_local_vars"));
231     ASSERT_NE(nullptr, bump_local_vars);
232 
233     ASSERT_EQ(42, bump_local_vars());
234     ASSERT_EQ(44, bump_local_vars());
235 
236     ASSERT_EQ(0, dlclose(lib));
237   }
238 }
239 
240 // Calling dlclose should remove the entry for the solib from the global list of
241 // ELF TLS modules. Test that repeatedly loading and unloading a library doesn't
242 // increase the DTV size.
TEST(elftls_dl,dlclose_removes_entry)243 TEST(elftls_dl, dlclose_removes_entry) {
244 #if defined(__BIONIC__)
245   auto dtv = []() -> TlsDtv* { return __get_tcb_dtv(__get_bionic_tcb()); };
246 
247   bool first = true;
248   size_t count = 0;
249 
250   // Use a large number of rounds in case the DTV is initially larger than
251   // expected.
252   for (int round = 0; round < 32; ++round) {
253     void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
254     ASSERT_NE(nullptr, lib);
255 
256     auto bump_local_vars = reinterpret_cast<int(*)()>(dlsym(lib, "bump_local_vars"));
257     ASSERT_NE(nullptr, bump_local_vars);
258 
259     ASSERT_EQ(42, bump_local_vars());
260     if (first) {
261       first = false;
262       count = dtv()->count;
263     } else {
264       ASSERT_EQ(count, dtv()->count);
265     }
266 
267     dlclose(lib);
268   }
269 #else
270   GTEST_SKIP() << "test doesn't apply to glibc";
271 #endif
272 }
273 
274 // Use dlsym to get the address of a TLS variable in static TLS and compare it
275 // against the ordinary address of the variable.
TEST(elftls_dl,dlsym_static_tls)276 TEST(elftls_dl, dlsym_static_tls) {
277   void* lib = dlopen("libtest_elftls_shared_var.so", RTLD_LOCAL | RTLD_NOW);
278   ASSERT_NE(nullptr, lib);
279 
280   int* var_addr = static_cast<int*>(dlsym(lib, "elftls_shared_var"));
281   ASSERT_EQ(&elftls_shared_var, var_addr);
282 
283   std::thread([lib] {
284     int* var_addr = static_cast<int*>(dlsym(lib, "elftls_shared_var"));
285     ASSERT_EQ(&elftls_shared_var, var_addr);
286   }).join();
287 }
288 
289 // Use dlsym to get the address of a TLS variable in dynamic TLS and compare it
290 // against the ordinary address of the variable.
TEST(elftls_dl,dlsym_dynamic_tls)291 TEST(elftls_dl, dlsym_dynamic_tls) {
292   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
293   ASSERT_NE(nullptr, lib);
294   auto get_var_addr = reinterpret_cast<int*(*)()>(dlsym(lib, "get_large_tls_var_addr"));
295   ASSERT_NE(nullptr, get_var_addr);
296 
297   int* var_addr = static_cast<int*>(dlsym(lib, "large_tls_var"));
298   ASSERT_EQ(get_var_addr(), var_addr);
299 
300   std::thread([lib, get_var_addr] {
301     int* var_addr = static_cast<int*>(dlsym(lib, "large_tls_var"));
302     ASSERT_EQ(get_var_addr(), var_addr);
303   }).join();
304 }
305 
306 // Calling dladdr on a TLS variable's address doesn't find anything.
TEST(elftls_dl,dladdr_on_tls_var)307 TEST(elftls_dl, dladdr_on_tls_var) {
308   Dl_info info;
309 
310   // Static TLS variable
311   ASSERT_EQ(0, dladdr(&elftls_shared_var, &info));
312 
313   // Dynamic TLS variable
314   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
315   ASSERT_NE(nullptr, lib);
316   int* var_addr = static_cast<int*>(dlsym(lib, "large_tls_var"));
317   ASSERT_EQ(0, dladdr(var_addr, &info));
318 }
319 
320 // Verify that dladdr does not misinterpret a TLS symbol's value as a virtual
321 // address.
TEST(elftls_dl,dladdr_skip_tls_symbol)322 TEST(elftls_dl, dladdr_skip_tls_symbol) {
323   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
324 
325   auto get_local_addr = reinterpret_cast<void*(*)()>(dlsym(lib, "get_local_addr"));
326   ASSERT_NE(nullptr, get_local_addr);
327   void* local_addr = get_local_addr();
328 
329   Dl_info info;
330   ASSERT_NE(0, dladdr(local_addr, &info));
331 
332   std::string libpath = GetTestlibRoot() + "/libtest_elftls_dynamic.so";
333   char dli_realpath[PATH_MAX];
334   ASSERT_TRUE(realpath(info.dli_fname, dli_realpath));
335   ASSERT_STREQ(libpath.c_str(), dli_realpath);
336   ASSERT_STREQ(nullptr, info.dli_sname);
337   ASSERT_EQ(nullptr, info.dli_saddr);
338 }
339 
TEST(elftls_dl,dl_iterate_phdr)340 TEST(elftls_dl, dl_iterate_phdr) {
341   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
342 
343   auto get_var_addr = reinterpret_cast<void*(*)()>(dlsym(lib, "get_large_tls_var_addr"));
344   ASSERT_NE(nullptr, get_var_addr);
345 
346   struct TlsInfo {
347     bool found;
348     size_t modid;
349     void* data;
350     size_t memsz;
351   };
352 
353   auto get_tls_info = []() {
354     auto callback = [](dl_phdr_info* info, size_t, void* data) {
355       TlsInfo& tls_info = *static_cast<TlsInfo*>(data);
356 
357       // This test is also run with glibc, where dlpi_name may have relative path components, so
358       // examine just the basename when searching for the library.
359       if (strcmp(basename(info->dlpi_name), "libtest_elftls_dynamic.so") != 0) return 0;
360 
361       tls_info.found = true;
362       tls_info.modid = info->dlpi_tls_modid;
363       tls_info.data = info->dlpi_tls_data;
364       for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
365         if (info->dlpi_phdr[i].p_type == PT_TLS) {
366           tls_info.memsz = info->dlpi_phdr[i].p_memsz;
367         }
368       }
369       EXPECT_NE(static_cast<size_t>(0), tls_info.memsz);
370       return 1;
371     };
372 
373     TlsInfo result {};
374     dl_iterate_phdr(callback, &result);
375     return result;
376   };
377 
378   // The executable has a TLS segment, so it will use module ID #1, and the DSO's ID will be larger
379   // than 1. Initially, the data field is nullptr, because this thread's instance hasn't been
380   // allocated yet.
381   TlsInfo tls_info = get_tls_info();
382   ASSERT_TRUE(tls_info.found);
383   ASSERT_GT(tls_info.modid, static_cast<size_t>(1));
384   ASSERT_EQ(nullptr, tls_info.data);
385 
386   void* var_addr = get_var_addr();
387 
388   // Verify that dl_iterate_phdr returns a range of memory covering the allocated TLS variable.
389   tls_info = get_tls_info();
390   ASSERT_TRUE(tls_info.found);
391   ASSERT_GE(var_addr, tls_info.data);
392   ASSERT_LT(var_addr, static_cast<char*>(tls_info.data) + tls_info.memsz);
393 }
394