1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18
19 #include <dlfcn.h>
20 #include <elf.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <inttypes.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include <android/dlext.h>
29 #include <android-base/file.h>
30 #include <android-base/strings.h>
31 #include <android-base/test_utils.h>
32
33 #include <sys/mman.h>
34 #include <sys/types.h>
35 #include <sys/vfs.h>
36 #include <sys/wait.h>
37
38 #include <meminfo/procmeminfo.h>
39 #include <procinfo/process_map.h>
40 #include <ziparchive/zip_archive.h>
41
42 #include "core_shared_libs.h"
43 #include "gtest_globals.h"
44 #include "utils.h"
45 #include "dlext_private.h"
46 #include "dlfcn_symlink_support.h"
47
48 #define ASSERT_DL_NOTNULL(ptr) \
49 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
50
51 #define ASSERT_DL_ZERO(i) \
52 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
53
54 #define ASSERT_NOERROR(i) \
55 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
56
57 #define ASSERT_SUBSTR(needle, haystack) \
58 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
59
60
61 typedef int (*fn)(void);
62 constexpr const char* kLibName = "libdlext_test.so";
63 constexpr const char* kLibNameRecursive = "libdlext_test_recursive.so";
64 constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
65 constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
66 constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
67
68 class DlExtTest : public ::testing::Test {
69 protected:
SetUp()70 void SetUp() override {
71 handle_ = nullptr;
72 // verify that we don't have the library loaded already
73 void* h = dlopen(kLibName, RTLD_NOW | RTLD_NOLOAD);
74 ASSERT_TRUE(h == nullptr);
75 h = dlopen(kLibNameNoRelro, RTLD_NOW | RTLD_NOLOAD);
76 ASSERT_TRUE(h == nullptr);
77 // call dlerror() to swallow the error, and check it was the one we wanted
78 ASSERT_EQ(std::string("dlopen failed: library \"") + kLibNameNoRelro + "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
79 }
80
TearDown()81 void TearDown() override {
82 if (handle_ != nullptr) {
83 ASSERT_DL_ZERO(dlclose(handle_));
84 }
85 }
86
87 void* handle_;
88 };
89
TEST_F(DlExtTest,ExtInfoNull)90 TEST_F(DlExtTest, ExtInfoNull) {
91 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, nullptr);
92 ASSERT_DL_NOTNULL(handle_);
93 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
94 ASSERT_DL_NOTNULL(f);
95 EXPECT_EQ(4, f());
96 }
97
TEST_F(DlExtTest,ExtInfoNoFlags)98 TEST_F(DlExtTest, ExtInfoNoFlags) {
99 android_dlextinfo extinfo;
100 extinfo.flags = 0;
101 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
102 ASSERT_DL_NOTNULL(handle_);
103 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
104 ASSERT_DL_NOTNULL(f);
105 EXPECT_EQ(4, f());
106 }
107
TEST_F(DlExtTest,ExtInfoUseFd)108 TEST_F(DlExtTest, ExtInfoUseFd) {
109 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_fd/libdlext_test_fd.so";
110
111 android_dlextinfo extinfo;
112 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
113 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
114 ASSERT_TRUE(extinfo.library_fd != -1);
115 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
116 ASSERT_DL_NOTNULL(handle_);
117 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
118 ASSERT_DL_NOTNULL(f);
119 EXPECT_EQ(4, f());
120
121 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
122 ASSERT_DL_NOTNULL(taxicab_number);
123 EXPECT_EQ(1729U, *taxicab_number);
124 }
125
TEST_F(DlExtTest,ExtInfoUseFdWithOffset)126 TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
127 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
128
129 android_dlextinfo extinfo;
130 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
131 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
132
133 // Find the offset of the shared library in the zip.
134 ZipArchiveHandle handle;
135 ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
136 ZipEntry zip_entry;
137 ASSERT_EQ(0, FindEntry(handle, kLibZipSimpleZip, &zip_entry));
138 extinfo.library_fd_offset = zip_entry.offset;
139 CloseArchive(handle);
140
141 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
142 ASSERT_DL_NOTNULL(handle_);
143
144 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
145 ASSERT_DL_NOTNULL(taxicab_number);
146 EXPECT_EQ(1729U, *taxicab_number);
147 }
148
TEST_F(DlExtTest,ExtInfoUseFdWithInvalidOffset)149 TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
150 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
151
152 android_dlextinfo extinfo;
153 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
154 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
155 extinfo.library_fd_offset = 17;
156
157 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
158 ASSERT_TRUE(handle_ == nullptr);
159 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
160
161 // Test an address above 2^44, for http://b/18178121 .
162 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
163 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
164 ASSERT_TRUE(handle_ == nullptr);
165 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
166
167 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
168 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
169 ASSERT_TRUE(handle_ == nullptr);
170 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
171
172 extinfo.library_fd_offset = 0;
173 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
174 ASSERT_TRUE(handle_ == nullptr);
175 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
176
177 // Check if dlsym works after unsuccessful dlopen().
178 // Supply non-exiting one to make linker visit every soinfo.
179 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
180 ASSERT_TRUE(sym == nullptr);
181
182 close(extinfo.library_fd);
183 }
184
TEST_F(DlExtTest,ExtInfoUseOffsetWithoutFd)185 TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
186 android_dlextinfo extinfo;
187 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
188 // This offset will not be used, so it doesn't matter.
189 extinfo.library_fd_offset = 0;
190
191 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
192 ASSERT_TRUE(handle_ == nullptr);
193 ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
194 }
195
TEST(dlext,android_dlopen_ext_force_load_smoke)196 TEST(dlext, android_dlopen_ext_force_load_smoke) {
197 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
198 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
199 // 1. Open actual file
200 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
201 ASSERT_DL_NOTNULL(handle);
202 // 2. Open link with force_load flag set
203 android_dlextinfo extinfo;
204 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
205 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
206 ASSERT_DL_NOTNULL(handle2);
207 ASSERT_TRUE(handle != handle2);
208
209 dlclose(handle2);
210 dlclose(handle);
211 }
212
TEST(dlext,android_dlopen_ext_force_load_soname_exception)213 TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
214 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
215 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
216 // Check if soname lookup still returns already loaded library
217 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
218 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
219 ASSERT_DL_NOTNULL(handle);
220
221 android_dlextinfo extinfo;
222 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
223
224 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
225 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
226
227 ASSERT_DL_NOTNULL(handle2);
228 ASSERT_TRUE(handle == handle2);
229
230 dlclose(handle2);
231 dlclose(handle);
232 }
233
TEST(dlfcn,dlopen_from_nullptr_android_api_level_28)234 TEST(dlfcn, dlopen_from_nullptr_android_api_level_28) {
235 // Regression test for http://b/123972211. Testing dlopen(nullptr) when target sdk is P
236 android_set_application_target_sdk_version(28);
237 ASSERT_TRUE(dlopen(nullptr, RTLD_NOW) != nullptr);
238 }
239
TEST(dlfcn,dlopen_from_zip_absolute_path)240 TEST(dlfcn, dlopen_from_zip_absolute_path) {
241 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
242 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
243
244 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
245 ASSERT_TRUE(handle != nullptr) << dlerror();
246
247 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
248 ASSERT_DL_NOTNULL(taxicab_number);
249 EXPECT_EQ(1729U, *taxicab_number);
250
251 dlclose(handle);
252 }
253
TEST(dlfcn,dlopen_from_zip_with_dt_runpath)254 TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
255 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
256 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
257
258 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
259
260 ASSERT_TRUE(handle != nullptr) << dlerror();
261
262 typedef void *(* dlopen_b_fn)();
263 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
264 ASSERT_TRUE(fn != nullptr) << dlerror();
265
266 void *p = fn();
267 ASSERT_TRUE(p != nullptr) << dlerror();
268
269 dlclose(p);
270 dlclose(handle);
271 }
272
TEST(dlfcn,dlopen_from_zip_ld_library_path)273 TEST(dlfcn, dlopen_from_zip_ld_library_path) {
274 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
275 const std::string lib_path = GetTestlibRoot() + lib_zip_path + "!/libdir";
276
277 typedef void (*fn_t)(const char*);
278 fn_t android_update_LD_LIBRARY_PATH =
279 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
280
281 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
282
283 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
284 ASSERT_TRUE(handle == nullptr);
285
286 android_update_LD_LIBRARY_PATH(lib_path.c_str());
287
288 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
289 ASSERT_TRUE(handle != nullptr) << dlerror();
290
291 int (*fn)(void);
292 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
293 ASSERT_TRUE(fn != nullptr);
294 EXPECT_EQ(4, fn());
295
296 uint32_t* taxicab_number =
297 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
298 ASSERT_DL_NOTNULL(taxicab_number);
299 EXPECT_EQ(1729U, *taxicab_number);
300
301 dlclose(handle);
302 }
303
304
TEST_F(DlExtTest,Reserved)305 TEST_F(DlExtTest, Reserved) {
306 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
307 ASSERT_TRUE(start != MAP_FAILED);
308 android_dlextinfo extinfo;
309 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
310 extinfo.reserved_addr = start;
311 extinfo.reserved_size = kLibSize;
312 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
313 ASSERT_DL_NOTNULL(handle_);
314 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
315 ASSERT_DL_NOTNULL(f);
316 EXPECT_GE(reinterpret_cast<void*>(f), start);
317 EXPECT_LT(reinterpret_cast<void*>(f),
318 reinterpret_cast<char*>(start) + kLibSize);
319 EXPECT_EQ(4, f());
320
321 // Check that after dlclose reserved address space is unmapped (and can be reused)
322 dlclose(handle_);
323 handle_ = nullptr;
324
325 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
326 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
327 }
328
TEST_F(DlExtTest,ReservedTooSmall)329 TEST_F(DlExtTest, ReservedTooSmall) {
330 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
331 ASSERT_TRUE(start != MAP_FAILED);
332 android_dlextinfo extinfo;
333 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
334 extinfo.reserved_addr = start;
335 extinfo.reserved_size = PAGE_SIZE;
336 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
337 EXPECT_EQ(nullptr, handle_);
338 }
339
TEST_F(DlExtTest,ReservedRecursive)340 TEST_F(DlExtTest, ReservedRecursive) {
341 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
342 ASSERT_TRUE(start != MAP_FAILED);
343 android_dlextinfo extinfo;
344 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
345 extinfo.reserved_addr = start;
346 extinfo.reserved_size = kLibSize;
347 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
348 ASSERT_DL_NOTNULL(handle_);
349
350 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
351 ASSERT_DL_NOTNULL(f);
352 EXPECT_GE(reinterpret_cast<void*>(f), start);
353 EXPECT_LT(reinterpret_cast<void*>(f),
354 reinterpret_cast<char*>(start) + kLibSize);
355 EXPECT_EQ(4, f());
356
357 f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
358 ASSERT_DL_NOTNULL(f);
359 EXPECT_GE(reinterpret_cast<void*>(f), start);
360 EXPECT_LT(reinterpret_cast<void*>(f),
361 reinterpret_cast<char*>(start) + kLibSize);
362 EXPECT_EQ(8, f());
363
364 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
365 ASSERT_DL_NOTNULL(taxicab_number);
366 // Untag the pointer so that it can be compared with start, which will be untagged.
367 void* addr = reinterpret_cast<void*>(untag_address(taxicab_number));
368 EXPECT_GE(addr, start);
369 EXPECT_LT(addr, reinterpret_cast<char*>(start) + kLibSize);
370 EXPECT_EQ(1729U, *taxicab_number);
371 }
372
TEST_F(DlExtTest,ReservedRecursiveTooSmall)373 TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
374 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
375 ASSERT_TRUE(start != MAP_FAILED);
376 android_dlextinfo extinfo;
377 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
378 extinfo.reserved_addr = start;
379 extinfo.reserved_size = PAGE_SIZE;
380 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
381 EXPECT_EQ(nullptr, handle_);
382 }
383
TEST_F(DlExtTest,ReservedHint)384 TEST_F(DlExtTest, ReservedHint) {
385 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
386 ASSERT_TRUE(start != MAP_FAILED);
387 android_dlextinfo extinfo;
388 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
389 extinfo.reserved_addr = start;
390 extinfo.reserved_size = kLibSize;
391 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
392 ASSERT_DL_NOTNULL(handle_);
393 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
394 ASSERT_DL_NOTNULL(f);
395 EXPECT_GE(reinterpret_cast<void*>(f), start);
396 EXPECT_LT(reinterpret_cast<void*>(f),
397 reinterpret_cast<char*>(start) + kLibSize);
398 EXPECT_EQ(4, f());
399 }
400
TEST_F(DlExtTest,ReservedHintTooSmall)401 TEST_F(DlExtTest, ReservedHintTooSmall) {
402 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
403 ASSERT_TRUE(start != MAP_FAILED);
404 android_dlextinfo extinfo;
405 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
406 extinfo.reserved_addr = start;
407 extinfo.reserved_size = PAGE_SIZE;
408 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
409 ASSERT_DL_NOTNULL(handle_);
410 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
411 ASSERT_DL_NOTNULL(f);
412 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
413 (reinterpret_cast<void*>(f) >=
414 reinterpret_cast<char*>(start) + PAGE_SIZE));
415 EXPECT_EQ(4, f());
416 }
417
418 class DlExtRelroSharingTest : public DlExtTest {
419 protected:
SetUp()420 void SetUp() override {
421 DlExtTest::SetUp();
422 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
423 ASSERT_TRUE(start != MAP_FAILED);
424 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
425 extinfo_.reserved_addr = start;
426 extinfo_.reserved_size = kLibSize;
427 extinfo_.relro_fd = -1;
428 }
429
TearDown()430 void TearDown() override {
431 DlExtTest::TearDown();
432 }
433
CreateRelroFile(const char * lib,const char * relro_file,bool recursive)434 void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
435 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
436 ASSERT_NOERROR(relro_fd);
437
438 if (recursive) {
439 extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
440 }
441
442 pid_t pid = fork();
443 if (pid == 0) {
444 // child process
445 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
446 extinfo_.relro_fd = relro_fd;
447 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
448 if (handle == nullptr) {
449 fprintf(stderr, "in child: %s\n", dlerror());
450 exit(1);
451 }
452 fn f = reinterpret_cast<fn>(dlsym(handle, "getRandomNumber"));
453 ASSERT_DL_NOTNULL(f);
454 EXPECT_EQ(4, f());
455
456 if (recursive) {
457 fn f = reinterpret_cast<fn>(dlsym(handle, "getBiggerRandomNumber"));
458 ASSERT_DL_NOTNULL(f);
459 EXPECT_EQ(8, f());
460 }
461
462 uint32_t* taxicab_number =
463 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
464 ASSERT_DL_NOTNULL(taxicab_number);
465 EXPECT_EQ(1729U, *taxicab_number);
466 exit(testing::Test::HasFailure());
467 }
468
469 // continuing in parent
470 ASSERT_NOERROR(close(relro_fd));
471 ASSERT_NOERROR(pid);
472 AssertChildExited(pid, 0);
473
474 // reopen file for reading so it can be used
475 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
476 ASSERT_NOERROR(relro_fd);
477 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
478 extinfo_.relro_fd = relro_fd;
479 }
480
TryUsingRelro(const char * lib,bool recursive)481 void TryUsingRelro(const char* lib, bool recursive) {
482 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
483 ASSERT_DL_NOTNULL(handle_);
484 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
485 ASSERT_DL_NOTNULL(f);
486 EXPECT_EQ(4, f());
487
488 if (recursive) {
489 fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
490 ASSERT_DL_NOTNULL(f);
491 EXPECT_EQ(8, f());
492 }
493
494 uint32_t* taxicab_number =
495 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
496 ASSERT_DL_NOTNULL(taxicab_number);
497 EXPECT_EQ(1729U, *taxicab_number);
498 }
499
500 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
501 size_t* pss_out);
502
503 std::string FindMappingName(void* ptr);
504
505 android_dlextinfo extinfo_;
506 };
507
TEST_F(DlExtRelroSharingTest,ChildWritesGoodData)508 TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
509 TemporaryFile tf; // Use tf to get an unique filename.
510 ASSERT_NOERROR(close(tf.fd));
511
512 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
513 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
514 void* relro_data = dlsym(handle_, "lots_of_relro");
515 ASSERT_DL_NOTNULL(relro_data);
516 EXPECT_EQ(tf.path, FindMappingName(relro_data));
517
518 // Use destructor of tf to close and unlink the file.
519 tf.fd = extinfo_.relro_fd;
520 }
521
TEST_F(DlExtRelroSharingTest,ChildWritesGoodDataRecursive)522 TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
523 TemporaryFile tf; // Use tf to get an unique filename.
524 ASSERT_NOERROR(close(tf.fd));
525
526 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
527 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
528 void* relro_data = dlsym(handle_, "lots_of_relro");
529 ASSERT_DL_NOTNULL(relro_data);
530 EXPECT_EQ(tf.path, FindMappingName(relro_data));
531 void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
532 ASSERT_DL_NOTNULL(recursive_relro_data);
533 EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
534
535
536 // Use destructor of tf to close and unlink the file.
537 tf.fd = extinfo_.relro_fd;
538 }
539
TEST_F(DlExtRelroSharingTest,CheckRelroSizes)540 TEST_F(DlExtRelroSharingTest, CheckRelroSizes) {
541 TemporaryFile tf1, tf2;
542 ASSERT_NOERROR(close(tf1.fd));
543 ASSERT_NOERROR(close(tf2.fd));
544
545 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf1.path, false));
546 struct stat no_recursive;
547 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &no_recursive));
548 tf1.fd = extinfo_.relro_fd;
549
550 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf2.path, true));
551 struct stat with_recursive;
552 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &with_recursive));
553 tf2.fd = extinfo_.relro_fd;
554
555 // RELRO file should end up bigger when we use the recursive flag, since it
556 // includes data for more than one library.
557 ASSERT_GT(with_recursive.st_size, no_recursive.st_size);
558 }
559
TEST_F(DlExtRelroSharingTest,ChildWritesNoRelro)560 TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
561 TemporaryFile tf; // // Use tf to get an unique filename.
562 ASSERT_NOERROR(close(tf.fd));
563
564 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
565 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
566
567 // Use destructor of tf to close and unlink the file.
568 tf.fd = extinfo_.relro_fd;
569 }
570
TEST_F(DlExtRelroSharingTest,RelroFileEmpty)571 TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
572 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
573 }
574
TEST_F(DlExtRelroSharingTest,VerifyMemorySaving)575 TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
576 if (geteuid() != 0) GTEST_SKIP() << "This test must be run as root";
577
578 TemporaryFile tf; // Use tf to get an unique filename.
579 ASSERT_NOERROR(close(tf.fd));
580
581 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
582
583 int pipefd[2];
584 ASSERT_NOERROR(pipe(pipefd));
585
586 size_t without_sharing, with_sharing;
587 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
588 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
589 ASSERT_LT(with_sharing, without_sharing);
590
591 // We expect the sharing to save at least 50% of the library's total PSS.
592 // In practice it saves 80%+ for this library in the test.
593 size_t pss_saved = without_sharing - with_sharing;
594 size_t expected_min_saved = without_sharing / 2;
595
596 EXPECT_LT(expected_min_saved, pss_saved);
597
598 // Use destructor of tf to close and unlink the file.
599 tf.fd = extinfo_.relro_fd;
600 }
601
GetPss(bool shared_relro,const char * lib,const char * relro_file,pid_t pid,size_t * total_pss)602 void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
603 size_t* total_pss) {
604 android::meminfo::ProcMemInfo proc_mem(pid);
605 const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats();
606 ASSERT_GT(maps.size(), 0UL);
607
608 // Calculate total PSS of the library.
609 *total_pss = 0;
610 bool saw_relro_file = false;
611 for (auto& vma : maps) {
612 if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
613 if (vma.name == relro_file) {
614 saw_relro_file = true;
615 }
616
617 android::meminfo::Vma update_vma(vma);
618 ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma));
619 *total_pss += update_vma.usage.pss;
620 }
621 }
622
623 if (shared_relro) ASSERT_TRUE(saw_relro_file);
624 }
625
SpawnChildrenAndMeasurePss(const char * lib,const char * relro_file,bool share_relro,size_t * pss_out)626 void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
627 bool share_relro, size_t* pss_out) {
628 const int CHILDREN = 20;
629
630 // Create children
631 pid_t child_pids[CHILDREN];
632 int childpipe[CHILDREN];
633 for (int i=0; i<CHILDREN; ++i) {
634 char read_buf;
635 int child_done_pipe[2], parent_done_pipe[2];
636 ASSERT_NOERROR(pipe(child_done_pipe));
637 ASSERT_NOERROR(pipe(parent_done_pipe));
638
639 pid_t child = fork();
640 if (child == 0) {
641 // close the 'wrong' ends of the pipes in the child
642 close(child_done_pipe[0]);
643 close(parent_done_pipe[1]);
644
645 // open the library
646 void* handle;
647 if (share_relro) {
648 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
649 } else {
650 handle = dlopen(lib, RTLD_NOW);
651 }
652 if (handle == nullptr) {
653 fprintf(stderr, "in child: %s\n", dlerror());
654 exit(1);
655 }
656
657 // close write end of child_done_pipe to signal the parent that we're done.
658 close(child_done_pipe[1]);
659
660 // wait for the parent to close parent_done_pipe, then exit
661 read(parent_done_pipe[0], &read_buf, 1);
662 exit(0);
663 }
664
665 ASSERT_NOERROR(child);
666
667 // close the 'wrong' ends of the pipes in the parent
668 close(child_done_pipe[1]);
669 close(parent_done_pipe[0]);
670
671 // wait for the child to be done
672 read(child_done_pipe[0], &read_buf, 1);
673 close(child_done_pipe[0]);
674
675 // save the child's pid and the parent_done_pipe
676 child_pids[i] = child;
677 childpipe[i] = parent_done_pipe[1];
678 }
679
680 // Sum the PSS of tested library of all the children
681 size_t total_pss = 0;
682 for (int i=0; i<CHILDREN; ++i) {
683 size_t child_pss;
684 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
685 total_pss += child_pss;
686 }
687 *pss_out = total_pss;
688
689 // Close pipes and wait for children to exit
690 for (int i=0; i<CHILDREN; ++i) {
691 ASSERT_NOERROR(close(childpipe[i]));
692 }
693 for (int i = 0; i < CHILDREN; ++i) {
694 AssertChildExited(child_pids[i], 0);
695 }
696 }
697
FindMappingName(void * ptr)698 std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
699 uint64_t addr = reinterpret_cast<uint64_t>(ptr);
700 std::string found_name = "<not found>";
701
702 EXPECT_TRUE(android::procinfo::ReadMapFile(
703 "/proc/self/maps",
704 [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
705 if (addr >= start && addr < end) {
706 found_name = name;
707 }
708 }));
709
710 return found_name;
711 }
712
713 // Testing namespaces
714 static const char* g_public_lib = "libnstest_public.so";
715
716 // These are libs shared with default namespace
717 static const std::string g_core_shared_libs = kCoreSharedLibs;
718
TEST(dlext,ns_smoke)719 TEST(dlext, ns_smoke) {
720 static const char* root_lib = "libnstest_root.so";
721 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
722
723 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
724 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
725 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
726 dlerror());
727
728 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
729 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
730 ASSERT_TRUE(handle_public != nullptr) << dlerror();
731
732 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
733
734 // Check that libraries added to public namespace are not NODELETE
735 dlclose(handle_public);
736 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
737 ASSERT_TRUE(handle_public == nullptr);
738 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
739 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
740
741 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
742
743 // create "public namespace", share limited set of public libraries with
744
745 android_namespace_t* ns1 =
746 android_create_namespace("private",
747 nullptr,
748 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
749 ANDROID_NAMESPACE_TYPE_REGULAR,
750 nullptr,
751 nullptr);
752 ASSERT_TRUE(ns1 != nullptr) << dlerror();
753 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
754
755 android_namespace_t* ns2 =
756 android_create_namespace("private_isolated",
757 nullptr,
758 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
759 ANDROID_NAMESPACE_TYPE_ISOLATED,
760 nullptr,
761 nullptr);
762 ASSERT_TRUE(ns2 != nullptr) << dlerror();
763 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
764
765 // This should not have affect search path for default namespace:
766 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
767 void* handle = dlopen(g_public_lib, RTLD_NOW);
768 ASSERT_TRUE(handle != nullptr) << dlerror();
769 dlclose(handle);
770
771 // dlopen for a public library using an absolute path should work
772 // 1. For isolated namespaces
773 android_dlextinfo extinfo;
774 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
775 extinfo.library_namespace = ns2;
776 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
777 ASSERT_TRUE(handle != nullptr) << dlerror();
778 ASSERT_TRUE(handle == handle_public);
779
780 dlclose(handle);
781
782 // 1.1 even if it wasn't loaded before
783 dlclose(handle_public);
784
785 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
786 ASSERT_TRUE(handle_public == nullptr);
787 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
788 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
789
790 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
791 ASSERT_TRUE(handle != nullptr) << dlerror();
792
793 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
794 ASSERT_TRUE(handle == handle_public);
795
796 dlclose(handle);
797
798 // 2. And for regular namespaces (make sure it does not load second copy of the library)
799 extinfo.library_namespace = ns1;
800 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
801 ASSERT_TRUE(handle != nullptr) << dlerror();
802 ASSERT_TRUE(handle == handle_public);
803
804 dlclose(handle);
805
806 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
807 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
808 dlclose(handle_public);
809
810 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
811 ASSERT_TRUE(handle_public == nullptr);
812 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
813 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
814
815 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
816 ASSERT_TRUE(handle != nullptr) << dlerror();
817
818 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
819
820 ASSERT_TRUE(handle != handle_public);
821
822 dlclose(handle);
823
824 extinfo.library_namespace = ns1;
825
826 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
827 ASSERT_TRUE(handle1 != nullptr) << dlerror();
828
829 extinfo.library_namespace = ns2;
830 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
831 ASSERT_TRUE(handle2 != nullptr) << dlerror();
832
833 ASSERT_TRUE(handle1 != handle2);
834
835 typedef const char* (*fn_t)();
836
837 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
838 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
839 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
840 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
841
842 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
843 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
844
845 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
846
847 fn_t ns_get_private_extern_string1 =
848 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
849 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
850 fn_t ns_get_private_extern_string2 =
851 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
852 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
853
854 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
855 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
856
857 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
858
859 fn_t ns_get_public_extern_string1 =
860 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
861 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
862 fn_t ns_get_public_extern_string2 =
863 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
864 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
865
866 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
867 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
868
869 // and now check that dlopen() does the right thing in terms of preserving namespace
870 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
871 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
872 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
873 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
874
875 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
876 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
877
878 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
879
880 // Check that symbols from non-shared libraries a shared library depends on are not visible
881 // from original namespace.
882
883 fn_t ns_get_internal_extern_string =
884 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
885 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
886 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
887 "ns_get_internal_extern_string() expected to return null but returns \"" <<
888 ns_get_internal_extern_string() << "\"";
889
890 dlclose(handle1);
891
892 // Check if handle2 is still alive (and well)
893 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
894 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
895 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
896 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
897
898 dlclose(handle2);
899 }
900
TEST(dlext,dlopen_ext_use_o_tmpfile_fd)901 TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
902 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
903
904 int tmpfd = TEMP_FAILURE_RETRY(
905 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
906
907 // Ignore kernels without O_TMPFILE flag support
908 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
909 return;
910 }
911
912 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
913
914 android_namespace_t* ns =
915 android_create_namespace("testing-o_tmpfile",
916 nullptr,
917 GetTestlibRoot().c_str(),
918 ANDROID_NAMESPACE_TYPE_ISOLATED,
919 nullptr,
920 nullptr);
921
922 ASSERT_DL_NOTNULL(ns);
923
924 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
925
926 std::string content;
927 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
928 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
929
930 android_dlextinfo extinfo;
931 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
932 extinfo.library_fd = tmpfd;
933 extinfo.library_namespace = ns;
934
935 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
936
937 ASSERT_DL_NOTNULL(handle);
938
939 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
940 ASSERT_DL_NOTNULL(taxicab_number);
941 EXPECT_EQ(1729U, *taxicab_number);
942 dlclose(handle);
943 }
944
TEST(dlext,dlopen_ext_use_memfd)945 TEST(dlext, dlopen_ext_use_memfd) {
946 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
947
948 // create memfd
949 int memfd = memfd_create("foobar", MFD_CLOEXEC);
950 if (memfd == -1 && errno == ENOSYS) {
951 return;
952 }
953
954 ASSERT_TRUE(memfd != -1) << strerror(errno);
955
956 // Check st.f_type is TMPFS_MAGIC for memfd
957 struct statfs st;
958 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
959 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
960
961 android_namespace_t* ns =
962 android_create_namespace("testing-memfd",
963 nullptr,
964 GetTestlibRoot().c_str(),
965 ANDROID_NAMESPACE_TYPE_ISOLATED,
966 nullptr,
967 nullptr);
968
969 ASSERT_DL_NOTNULL(ns);
970
971 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
972
973 // read file into memfd backed one.
974 std::string content;
975 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
976 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
977
978 android_dlextinfo extinfo;
979 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
980 extinfo.library_fd = memfd;
981 extinfo.library_namespace = ns;
982
983 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
984
985 ASSERT_DL_NOTNULL(handle);
986
987 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
988 ASSERT_DL_NOTNULL(taxicab_number);
989 EXPECT_EQ(1729U, *taxicab_number);
990 dlclose(handle);
991 }
992
TEST(dlext,ns_symbol_visibilty_one_namespace)993 TEST(dlext, ns_symbol_visibilty_one_namespace) {
994 static const char* root_lib = "libnstest_root.so";
995 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
996
997 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
998 GetTestlibRoot() + "/private_namespace_libs";
999
1000 android_namespace_t* ns =
1001 android_create_namespace("one",
1002 nullptr,
1003 ns_search_path.c_str(),
1004 ANDROID_NAMESPACE_TYPE_ISOLATED,
1005 nullptr,
1006 nullptr);
1007
1008 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1009
1010 android_dlextinfo extinfo;
1011 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1012 extinfo.library_namespace = ns;
1013
1014 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1015 ASSERT_TRUE(handle != nullptr) << dlerror();
1016
1017 typedef const char* (*fn_t)();
1018
1019 // Check that relocation worked correctly
1020 fn_t ns_get_internal_extern_string =
1021 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1022 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1023 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
1024
1025 fn_t internal_extern_string_fn =
1026 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1027 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
1028 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
1029 }
1030
TEST(dlext,ns_symbol_visibilty_between_namespaces)1031 TEST(dlext, ns_symbol_visibilty_between_namespaces) {
1032 static const char* root_lib = "libnstest_root.so";
1033 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1034
1035 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1036 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
1037
1038 android_namespace_t* ns_public =
1039 android_create_namespace("public",
1040 nullptr,
1041 public_ns_search_path.c_str(),
1042 ANDROID_NAMESPACE_TYPE_ISOLATED,
1043 nullptr,
1044 nullptr);
1045
1046 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1047
1048 android_namespace_t* ns_private =
1049 android_create_namespace("private",
1050 nullptr,
1051 private_ns_search_path.c_str(),
1052 ANDROID_NAMESPACE_TYPE_ISOLATED,
1053 nullptr,
1054 nullptr);
1055
1056 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1057 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1058
1059 android_dlextinfo extinfo;
1060 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1061 extinfo.library_namespace = ns_private;
1062
1063 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1064 ASSERT_TRUE(handle != nullptr) << dlerror();
1065
1066 typedef const char* (*fn_t)();
1067
1068 // Check that relocation worked correctly
1069 fn_t ns_get_internal_extern_string =
1070 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1071 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1072 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
1073 "ns_get_internal_extern_string() expected to return null but returns \"" <<
1074 ns_get_internal_extern_string() << "\"";
1075
1076 fn_t internal_extern_string_fn =
1077 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1078 ASSERT_TRUE(internal_extern_string_fn == nullptr);
1079 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
1080 }
1081
TEST(dlext,ns_unload_between_namespaces)1082 TEST(dlext, ns_unload_between_namespaces) {
1083 static const char* root_lib = "libnstest_root.so";
1084 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1085
1086 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1087 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
1088
1089 android_namespace_t* ns_public =
1090 android_create_namespace("public",
1091 nullptr,
1092 public_ns_search_path.c_str(),
1093 ANDROID_NAMESPACE_TYPE_ISOLATED,
1094 nullptr,
1095 nullptr);
1096
1097 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1098
1099 android_namespace_t* ns_private =
1100 android_create_namespace("private",
1101 nullptr,
1102 private_ns_search_path.c_str(),
1103 ANDROID_NAMESPACE_TYPE_ISOLATED,
1104 nullptr,
1105 nullptr);
1106
1107 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1108 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1109
1110 android_dlextinfo extinfo;
1111 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1112 extinfo.library_namespace = ns_private;
1113
1114 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1115 ASSERT_TRUE(handle != nullptr) << dlerror();
1116
1117 dlclose(handle);
1118 // Check that root_lib was unloaded
1119 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1120 ASSERT_TRUE(handle == nullptr);
1121 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1122 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1123
1124 // Check that shared library was unloaded in public ns
1125 extinfo.library_namespace = ns_public;
1126 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1127 ASSERT_TRUE(handle == nullptr);
1128 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1129 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1130 }
1131
TEST(dlext,ns_unload_between_namespaces_missing_symbol_direct)1132 TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1133 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1134
1135 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1136 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
1137
1138 android_namespace_t* ns_public =
1139 android_create_namespace("public",
1140 nullptr,
1141 public_ns_search_path.c_str(),
1142 ANDROID_NAMESPACE_TYPE_ISOLATED,
1143 nullptr,
1144 nullptr);
1145
1146 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1147
1148 android_namespace_t* ns_private =
1149 android_create_namespace("private",
1150 nullptr,
1151 private_ns_search_path.c_str(),
1152 ANDROID_NAMESPACE_TYPE_ISOLATED,
1153 nullptr,
1154 nullptr);
1155
1156 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1157 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1158
1159 android_dlextinfo extinfo;
1160 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1161 extinfo.library_namespace = ns_private;
1162
1163 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1164 RTLD_NOW,
1165 &extinfo);
1166 ASSERT_TRUE(handle == nullptr);
1167 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1168 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1169 dlerror());
1170 }
1171
TEST(dlext,ns_unload_between_namespaces_missing_symbol_indirect)1172 TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1173 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1174
1175 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1176 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
1177
1178 android_namespace_t* ns_public =
1179 android_create_namespace("public",
1180 nullptr,
1181 public_ns_search_path.c_str(),
1182 ANDROID_NAMESPACE_TYPE_ISOLATED,
1183 nullptr,
1184 nullptr);
1185
1186 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1187
1188 android_namespace_t* ns_private =
1189 android_create_namespace("private",
1190 nullptr,
1191 private_ns_search_path.c_str(),
1192 ANDROID_NAMESPACE_TYPE_ISOLATED,
1193 nullptr,
1194 nullptr);
1195
1196 ASSERT_TRUE(android_link_namespaces(ns_private,
1197 ns_public,
1198 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1199 ) << dlerror();
1200 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1201
1202 android_dlextinfo extinfo;
1203 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1204 extinfo.library_namespace = ns_private;
1205
1206 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1207 ASSERT_TRUE(handle == nullptr);
1208 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1209 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1210 dlerror());
1211 }
1212
TEST(dlext,ns_greylist_enabled)1213 TEST(dlext, ns_greylist_enabled) {
1214 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1215
1216 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
1217
1218 android_namespace_t* ns =
1219 android_create_namespace("namespace",
1220 nullptr,
1221 ns_search_path.c_str(),
1222 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
1223 nullptr,
1224 nullptr);
1225
1226 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1227
1228 android_dlextinfo extinfo;
1229 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1230 extinfo.library_namespace = ns;
1231
1232 // An app targeting M can open libnativehelper.so because it's on the greylist.
1233 android_set_application_target_sdk_version(23);
1234 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1235 ASSERT_TRUE(handle != nullptr) << dlerror();
1236
1237 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1238 void* dlsym_ptr = dlsym(handle, "dlsym");
1239 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1240 ASSERT_EQ(&dlsym, dlsym_ptr);
1241
1242 dlclose(handle);
1243
1244 // An app targeting N no longer has the greylist.
1245 android_set_application_target_sdk_version(24);
1246 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1247 ASSERT_TRUE(handle == nullptr);
1248 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1249 }
1250
TEST(dlext,ns_greylist_disabled_by_default)1251 TEST(dlext, ns_greylist_disabled_by_default) {
1252 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1253
1254 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
1255
1256 android_namespace_t* ns =
1257 android_create_namespace("namespace",
1258 nullptr,
1259 ns_search_path.c_str(),
1260 ANDROID_NAMESPACE_TYPE_ISOLATED,
1261 nullptr,
1262 nullptr);
1263
1264 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1265
1266 android_dlextinfo extinfo;
1267 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1268 extinfo.library_namespace = ns;
1269
1270 android_set_application_target_sdk_version(23);
1271 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1272 ASSERT_TRUE(handle == nullptr);
1273 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1274 }
1275
TEST(dlext,ns_cyclic_namespaces)1276 TEST(dlext, ns_cyclic_namespaces) {
1277 // Test that ns1->ns2->ns1 link does not break the loader
1278 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1279 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1280
1281 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1282
1283 android_namespace_t* ns1 =
1284 android_create_namespace("ns1",
1285 nullptr,
1286 ns_search_path.c_str(),
1287 ANDROID_NAMESPACE_TYPE_ISOLATED,
1288 nullptr,
1289 nullptr);
1290
1291 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1292
1293 android_namespace_t* ns2 =
1294 android_create_namespace("ns1",
1295 nullptr,
1296 ns_search_path.c_str(),
1297 ANDROID_NAMESPACE_TYPE_ISOLATED,
1298 nullptr,
1299 nullptr);
1300
1301 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1302
1303 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1304 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1305
1306 android_dlextinfo extinfo;
1307 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1308 extinfo.library_namespace = ns1;
1309
1310 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1311 ASSERT_TRUE(handle == nullptr);
1312 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1313 }
1314
TEST(dlext,ns_isolated)1315 TEST(dlext, ns_isolated) {
1316 static const char* root_lib = "libnstest_root_not_isolated.so";
1317 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
1318
1319 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
1320 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1321 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1322
1323 android_set_application_target_sdk_version(42U); // something > 23
1324
1325 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
1326
1327 android_namespace_t* ns_not_isolated =
1328 android_create_namespace("private",
1329 nullptr,
1330 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1331 ANDROID_NAMESPACE_TYPE_REGULAR,
1332 nullptr,
1333 nullptr);
1334 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
1335 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
1336
1337 android_namespace_t* ns_isolated =
1338 android_create_namespace("private_isolated1",
1339 nullptr,
1340 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1341 ANDROID_NAMESPACE_TYPE_ISOLATED,
1342 nullptr,
1343 nullptr);
1344 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1345 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
1346
1347 android_namespace_t* ns_isolated2 =
1348 android_create_namespace("private_isolated2",
1349 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1350 nullptr,
1351 ANDROID_NAMESPACE_TYPE_ISOLATED,
1352 GetTestlibRoot().c_str(),
1353 nullptr);
1354 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
1355 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
1356
1357 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1358 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1359
1360 std::string lib_private_external_path =
1361 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
1362
1363 // Load lib_private_external_path to default namespace
1364 // (it should remain invisible for the isolated namespaces after this)
1365 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1366 ASSERT_TRUE(handle != nullptr) << dlerror();
1367
1368 android_dlextinfo extinfo;
1369 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1370 extinfo.library_namespace = ns_not_isolated;
1371
1372 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1373 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1374
1375 extinfo.library_namespace = ns_isolated;
1376
1377 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1378 ASSERT_TRUE(handle2 == nullptr);
1379 const char* error = dlerror();
1380 ASSERT_MATCH(error,
1381 R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )"
1382 R"(\S+libnstest_root_not_isolated.so in namespace private_isolated1)");
1383
1384 // Check dlopen by absolute path
1385 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1386 ASSERT_TRUE(handle2 == nullptr);
1387 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
1388 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
1389 " for the namespace \"private_isolated1\"", dlerror());
1390
1391 extinfo.library_namespace = ns_isolated2;
1392
1393 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
1394 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1395 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1396 dlclose(handle2);
1397
1398 // Check dlopen by absolute path
1399 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1400 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1401 dlclose(handle2);
1402
1403 typedef const char* (*fn_t)();
1404 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1405 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1406
1407 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1408
1409 fn_t ns_get_private_extern_string =
1410 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1411 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1412
1413 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1414
1415 fn_t ns_get_public_extern_string =
1416 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1417 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1418
1419 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1420
1421 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1422 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1423
1424 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1425
1426 dlclose(handle1);
1427 }
1428
TEST(dlext,ns_shared)1429 TEST(dlext, ns_shared) {
1430 static const char* root_lib = "libnstest_root_not_isolated.so";
1431 static const char* root_lib_isolated = "libnstest_root.so";
1432
1433 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
1434
1435 // create a parent namespace to use instead of the default namespace. This is
1436 // to make this test be independent from the configuration of the default
1437 // namespace.
1438 android_namespace_t* ns_parent =
1439 android_create_namespace("parent",
1440 nullptr,
1441 nullptr,
1442 ANDROID_NAMESPACE_TYPE_REGULAR,
1443 nullptr,
1444 nullptr);
1445 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1446 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1447
1448 android_dlextinfo extinfo;
1449 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1450 extinfo.library_namespace = ns_parent;
1451
1452 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
1453 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
1454 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1455
1456 android_set_application_target_sdk_version(42U); // something > 23
1457
1458 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
1459
1460 // preload this library to the parent namespace to check if it
1461 // is shared later on.
1462 void* handle_dlopened =
1463 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
1464 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1465
1466 // create two child namespaces of 'ns_parent'. One with regular, the other
1467 // with isolated & shared.
1468 android_namespace_t* ns_not_isolated =
1469 android_create_namespace("private",
1470 nullptr,
1471 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1472 ANDROID_NAMESPACE_TYPE_REGULAR,
1473 nullptr,
1474 ns_parent);
1475 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
1476 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1477 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1478
1479 android_namespace_t* ns_isolated_shared =
1480 android_create_namespace("private_isolated_shared",
1481 nullptr,
1482 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1483 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
1484 nullptr,
1485 ns_parent);
1486 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
1487 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1488 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
1489
1490 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
1491 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1492
1493 std::string lib_private_external_path =
1494 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
1495
1496 // Load lib_private_external_path to the parent namespace
1497 // (it should remain invisible for the isolated namespaces after this)
1498 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1499 ASSERT_TRUE(handle != nullptr) << dlerror();
1500
1501 extinfo.library_namespace = ns_not_isolated;
1502
1503 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1504 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1505
1506 extinfo.library_namespace = ns_isolated_shared;
1507
1508 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1509 ASSERT_TRUE(handle2 == nullptr);
1510 ASSERT_MATCH(dlerror(),
1511 R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )"
1512 R"(\S+libnstest_root_not_isolated.so in namespace private_isolated_shared)");
1513
1514 // Check dlopen by absolute path
1515 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1516 ASSERT_TRUE(handle2 == nullptr);
1517 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
1518 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
1519 " for the namespace \"private_isolated_shared\"", dlerror());
1520
1521 // load libnstest_root.so to shared namespace in order to check that everything is different
1522 // except shared libnstest_dlopened.so
1523
1524 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1525
1526 typedef const char* (*fn_t)();
1527 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1528 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1529 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1530 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1531
1532 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1533 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1534 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1535
1536 fn_t ns_get_private_extern_string =
1537 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1538 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1539 fn_t ns_get_private_extern_string_shared =
1540 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1541 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1542
1543 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1544 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1545 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1546
1547 fn_t ns_get_public_extern_string =
1548 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1549 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1550 fn_t ns_get_public_extern_string_shared =
1551 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1552 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1553
1554 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1555 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1556 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1557
1558 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1559 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1560 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1561 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1562 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1563 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1564
1565 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1566 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1567 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1568 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1569 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1570
1571 dlclose(handle1);
1572 dlclose(handle2);
1573 }
1574
TEST(dlext,ns_shared_links_and_paths)1575 TEST(dlext, ns_shared_links_and_paths) {
1576 // Create parent namespace (isolated, not shared)
1577 android_namespace_t* ns_isolated =
1578 android_create_namespace("private_isolated",
1579 nullptr,
1580 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1581 ANDROID_NAMESPACE_TYPE_ISOLATED,
1582 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
1583 nullptr);
1584 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1585 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1586
1587 // Create shared namespace with ns_isolated parent
1588 android_namespace_t* ns_shared =
1589 android_create_namespace("private_shared",
1590 nullptr,
1591 nullptr,
1592 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1593 nullptr,
1594 ns_isolated);
1595 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1596
1597 // 1. Load a library in ns_shared to check that it has inherited
1598 // search path and the link to the default namespace.
1599 android_dlextinfo extinfo;
1600 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1601 extinfo.library_namespace = ns_shared;
1602
1603 {
1604 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1605 ASSERT_TRUE(handle != nullptr) << dlerror();
1606 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1607 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1608 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1609
1610 dlclose(handle);
1611 }
1612 // 2. Load another test library by absolute path to check that
1613 // it has inherited permitted_when_isolated_path
1614 {
1615 void* handle = android_dlopen_ext(
1616 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
1617 RTLD_NOW,
1618 &extinfo);
1619
1620 ASSERT_TRUE(handle != nullptr) << dlerror();
1621 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1622 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1623 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1624
1625 dlclose(handle);
1626 }
1627
1628 // 3. Check that it is still isolated.
1629 {
1630 void* handle = android_dlopen_ext(
1631 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
1632 RTLD_NOW,
1633 &extinfo);
1634
1635 ASSERT_TRUE(handle == nullptr);
1636 }
1637 }
1638
TEST(dlext,ns_shared_dlclose)1639 TEST(dlext, ns_shared_dlclose) {
1640 android_set_application_target_sdk_version(42U); // something > 23
1641
1642 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
1643
1644 // preload this library to the default namespace to check if it
1645 // is shared later on.
1646 void* handle_dlopened =
1647 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
1648 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1649
1650 android_namespace_t* ns_isolated_shared =
1651 android_create_namespace("private_isolated_shared",
1652 nullptr,
1653 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1654 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
1655 nullptr,
1656 nullptr);
1657 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
1658 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
1659
1660 // Check if "libnstest_dlopened.so" is loaded (and the same)
1661 android_dlextinfo extinfo;
1662 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1663 extinfo.library_namespace = ns_isolated_shared;
1664
1665 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1666 ASSERT_TRUE(handle != nullptr) << dlerror();
1667 ASSERT_TRUE(handle == handle_dlopened);
1668 dlclose(handle);
1669 dlclose(handle_dlopened);
1670
1671 // And now check that the library cannot be found by soname (and is no longer loaded)
1672 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1673 ASSERT_TRUE(handle == nullptr)
1674 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1675
1676 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
1677 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1678 ASSERT_TRUE(handle == nullptr)
1679 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1680
1681 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1682 ASSERT_TRUE(handle == nullptr)
1683 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1684
1685 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
1686 RTLD_NOW | RTLD_NOLOAD);
1687 ASSERT_TRUE(handle == nullptr)
1688 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1689
1690 // Now lets see if the soinfo area gets reused in the wrong way:
1691 // load a library to default namespace.
1692 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
1693 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1694 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1695
1696 // try to find it in shared namespace
1697 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1698 ASSERT_TRUE(handle == nullptr)
1699 << "Error: " << g_public_lib << " is accessible in shared namespace";
1700 }
1701
TEST(dlext,ns_isolated_rtld_global)1702 TEST(dlext, ns_isolated_rtld_global) {
1703 static const char* root_lib = "libnstest_root.so";
1704 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1705
1706 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
1707
1708 android_namespace_t* ns1 =
1709 android_create_namespace("isolated1",
1710 nullptr,
1711 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1712 ANDROID_NAMESPACE_TYPE_ISOLATED,
1713 lib_public_path.c_str(),
1714 nullptr);
1715 ASSERT_TRUE(ns1 != nullptr) << dlerror();
1716 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1717
1718 android_namespace_t* ns2 =
1719 android_create_namespace("isolated2",
1720 nullptr,
1721 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1722 ANDROID_NAMESPACE_TYPE_ISOLATED,
1723 lib_public_path.c_str(),
1724 nullptr);
1725 ASSERT_TRUE(ns2 != nullptr) << dlerror();
1726 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1727
1728 android_dlextinfo extinfo;
1729 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1730 extinfo.library_namespace = ns1;
1731
1732 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1733 RTLD_GLOBAL,
1734 &extinfo);
1735
1736 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1737
1738 android_namespace_t* ns1_child =
1739 android_create_namespace("isolated1_child",
1740 nullptr,
1741 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1742 ANDROID_NAMESPACE_TYPE_ISOLATED,
1743 nullptr,
1744 ns1);
1745
1746 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1747 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
1748
1749 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1750 // attempt to use ns2 should result in dlerror()
1751
1752 // Check ns1_child first.
1753 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1754 extinfo.library_namespace = ns1_child;
1755
1756 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1757 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1758
1759 // now ns1
1760 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1761 extinfo.library_namespace = ns1;
1762
1763 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1764 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1765
1766 // and ns2 should fail
1767 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1768 extinfo.library_namespace = ns2;
1769
1770 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1771 ASSERT_TRUE(handle1 == nullptr);
1772 ASSERT_MATCH(
1773 dlerror(),
1774 R"(dlopen failed: library "libnstest_public.so" not found: needed by \S+libnstest_root.so)"
1775 R"( in namespace isolated2)");
1776 }
1777
TEST(dlext,ns_inaccessible_error_message)1778 TEST(dlext, ns_inaccessible_error_message) {
1779 // We set up 2 namespaces (a and b) and link a->b with a shared library
1780 // libtestshared.so. Then try to dlopen different library with the same
1781 // name from in namespace a. Note that library should not be accessible
1782 // in either namespace but since it's soname is in the list of shared libs
1783 // the linker will attempt to find it in linked namespace.
1784 //
1785 // Check the error message and make sure it mentions correct namespace name.
1786 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1787
1788 android_namespace_t* ns_a =
1789 android_create_namespace("ns_a",
1790 nullptr,
1791 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1792 ANDROID_NAMESPACE_TYPE_ISOLATED,
1793 nullptr,
1794 nullptr);
1795 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1796 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1797
1798 android_namespace_t* ns_b =
1799 android_create_namespace("ns_b",
1800 nullptr,
1801 GetTestlibRoot().c_str(),
1802 ANDROID_NAMESPACE_TYPE_ISOLATED,
1803 nullptr,
1804 nullptr);
1805 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1806 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1807
1808 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1809
1810 android_dlextinfo extinfo;
1811 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1812 extinfo.library_namespace = ns_a;
1813
1814 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
1815
1816 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1817 ASSERT_TRUE(handle == nullptr);
1818 std::string expected_dlerror =
1819 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1820 " is not accessible for the namespace \"ns_a\"",
1821 library_path.c_str(),
1822 android::base::GetExecutablePath().c_str());
1823 ASSERT_EQ(expected_dlerror, dlerror());
1824 }
1825
1826 extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1827 android_namespace_t* namespace_to);
1828
TEST(dlext,ns_link_namespaces_invalid_arguments)1829 TEST(dlext, ns_link_namespaces_invalid_arguments) {
1830 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1831
1832 android_namespace_t* ns =
1833 android_create_namespace("private",
1834 nullptr,
1835 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1836 ANDROID_NAMESPACE_TYPE_REGULAR,
1837 nullptr,
1838 nullptr);
1839 ASSERT_TRUE(ns != nullptr) << dlerror();
1840
1841 // Test android_link_namespaces()
1842 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1843 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1844 dlerror());
1845
1846 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1847 ASSERT_STREQ("android_link_namespaces failed: "
1848 "error linking namespaces \"private\"->\"(default)\": "
1849 "the list of shared libraries is empty.", dlerror());
1850
1851 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1852 ASSERT_STREQ("android_link_namespaces failed: "
1853 "error linking namespaces \"private\"->\"(default)\": "
1854 "the list of shared libraries is empty.", dlerror());
1855
1856 // Test __loader_android_link_namespaces_all_libs()
1857 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
1858 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1859 "error linking namespaces: namespace_from is null.", dlerror());
1860
1861 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
1862 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1863 "error linking namespaces: namespace_from is null.", dlerror());
1864
1865 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
1866 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1867 "error linking namespaces: namespace_to is null.", dlerror());
1868 }
1869
TEST(dlext,ns_allow_all_shared_libs)1870 TEST(dlext, ns_allow_all_shared_libs) {
1871 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1872
1873 android_namespace_t* ns_a =
1874 android_create_namespace("ns_a",
1875 nullptr,
1876 (GetTestlibRoot() + "/ns_a").c_str(),
1877 ANDROID_NAMESPACE_TYPE_ISOLATED,
1878 nullptr,
1879 nullptr);
1880 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1881 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1882
1883 android_namespace_t* ns_b =
1884 android_create_namespace("ns_b",
1885 nullptr,
1886 (GetTestlibRoot() + "/ns_b").c_str(),
1887 ANDROID_NAMESPACE_TYPE_ISOLATED,
1888 nullptr,
1889 nullptr);
1890 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1891 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1892
1893 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
1894 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
1895
1896 // Load libs with android_dlopen_ext() from namespace b
1897 android_dlextinfo extinfo;
1898 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1899 extinfo.library_namespace = ns_b;
1900
1901 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1902 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1903
1904 void* ns_b_handle1_internal =
1905 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1906 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1907
1908 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1909 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1910
1911 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1912 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1913
1914 // Load libs with android_dlopen_ext() from namespace a
1915 extinfo.library_namespace = ns_a;
1916
1917 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1918 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1919
1920 void* ns_a_handle1_internal =
1921 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1922 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1923
1924 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1925 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1926
1927 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1928 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1929
1930 // Compare the dlopen handle
1931 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1932 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1933 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1934
1935 // Close libs
1936 dlclose(ns_b_handle1);
1937 dlclose(ns_b_handle2);
1938 dlclose(ns_b_handle3);
1939
1940 dlclose(ns_a_handle1);
1941 dlclose(ns_a_handle1_internal);
1942 dlclose(ns_a_handle2);
1943 dlclose(ns_a_handle3);
1944 }
1945
TEST(dlext,ns_anonymous)1946 TEST(dlext, ns_anonymous) {
1947 static const char* root_lib = "libnstest_root.so";
1948 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
1949
1950 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
1951 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1952
1953 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1954
1955 ASSERT_TRUE(
1956 android_init_anonymous_namespace(shared_libs.c_str(),
1957 (GetTestlibRoot() + "/private_namespace_libs").c_str())
1958 ) << dlerror();
1959
1960 android_namespace_t* ns =
1961 android_create_namespace("private",
1962 nullptr,
1963 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
1964 ANDROID_NAMESPACE_TYPE_REGULAR,
1965 nullptr,
1966 nullptr);
1967
1968 ASSERT_TRUE(ns != nullptr) << dlerror();
1969 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
1970
1971 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
1972
1973 android_dlextinfo extinfo;
1974 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1975 extinfo.library_namespace = ns;
1976
1977 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1978 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1979 ASSERT_TRUE(handle != nullptr) << dlerror();
1980
1981 uintptr_t ns_get_dlopened_string_addr =
1982 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1983 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1984 typedef const char* (*fn_t)();
1985 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1986
1987 std::vector<map_record> maps;
1988 Maps::parse_maps(&maps);
1989
1990 uintptr_t addr_start = 0;
1991 uintptr_t addr_end = 0;
1992 bool has_executable_segment = false;
1993 std::vector<map_record> maps_to_copy;
1994
1995 for (const auto& rec : maps) {
1996 if (rec.pathname == private_library_absolute_path) {
1997 if (addr_start == 0) {
1998 addr_start = rec.addr_start;
1999 }
2000 addr_end = rec.addr_end;
2001 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
2002
2003 maps_to_copy.push_back(rec);
2004 }
2005 }
2006
2007 // some sanity checks..
2008 ASSERT_TRUE(addr_start > 0);
2009 ASSERT_TRUE(addr_end > 0);
2010 ASSERT_TRUE(maps_to_copy.size() > 0);
2011 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
2012 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
2013
2014 if (!has_executable_segment) {
2015 // For some natively bridged environments this code might be missing
2016 // the executable flag. This is because the guest code is not supposed
2017 // to be executed directly and making it non-executable is more secure.
2018 // In this case we assume the segment with the function is executable.
2019 for (auto& rec : maps_to_copy) {
2020 if (ns_get_dlopened_string_addr >= rec.addr_start &&
2021 ns_get_dlopened_string_addr < rec.addr_end) {
2022 ASSERT_TRUE((rec.perms & PROT_WRITE) == 0);
2023 rec.perms |= PROT_EXEC;
2024 break;
2025 }
2026 }
2027 }
2028
2029 // copy
2030 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
2031 PROT_NONE, MAP_ANON | MAP_PRIVATE,
2032 -1, 0));
2033 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
2034
2035 for (const auto& rec : maps_to_copy) {
2036 uintptr_t offset = rec.addr_start - addr_start;
2037 size_t size = rec.addr_end - rec.addr_start;
2038 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
2039 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
2040 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
2041 ASSERT_TRUE(map != MAP_FAILED);
2042 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
2043 mprotect(map, size, rec.perms);
2044 }
2045
2046 // call the function copy
2047 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
2048 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
2049 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2050 ns_get_dlopened_string_anon());
2051
2052 // They should belong to different namespaces (private and anonymous)
2053 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2054 ns_get_dlopened_string_private());
2055
2056 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
2057 }
2058
TEST(dlext,ns_hidden_child)2059 TEST(dlext, ns_hidden_child) {
2060 ExecTestHelper eth;
2061
2062 std::string helper = GetTestlibRoot() + "/ns_hidden_child_helper/ns_hidden_child_helper";
2063 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
2064 std::string app_ns_dir = GetTestlibRoot() + "/ns_hidden_child_app";
2065 eth.SetArgs({ helper.c_str(), app_ns_dir.c_str(), nullptr });
2066
2067 // Add the main libns_hidden_child_*.so libraries to the search path of the default namespace.
2068 std::string env = "LD_LIBRARY_PATH=" + GetTestlibRoot();
2069 eth.SetEnv({ env.c_str(), nullptr });
2070
2071 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
2072 "public_function is non-null\n"
2073 "internal_function is null\n");
2074 }
2075
TEST(dlext,dlopen_handle_value_platform)2076 TEST(dlext, dlopen_handle_value_platform) {
2077 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2078 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
2079 << "dlopen should return odd value for the handle";
2080 dlclose(handle);
2081 }
2082
TEST(dlext,dlopen_handle_value_app_compat)2083 TEST(dlext, dlopen_handle_value_app_compat) {
2084 android_set_application_target_sdk_version(23);
2085 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2086 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
2087 << "dlopen should return valid pointer";
2088 dlclose(handle);
2089 }
2090