blob: 35dff2a310f95dcb755310aa81f72c9ed3875b8e [file] [log] [blame]
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +00001/*
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>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080020#include <elf.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000021#include <errno.h>
22#include <fcntl.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080023#include <inttypes.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000024#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070027
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000028#include <android/dlext.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070029
30#include <linux/memfd.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000031#include <sys/mman.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010032#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070033#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000034#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000035
Torne (Richard Coles)26052612014-05-02 14:57:42 +010036#include <pagemap/pagemap.h>
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -080037#include <ziparchive/zip_archive.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010038
Dimitry Ivanov927877c2016-09-21 11:17:13 -070039#include "gtest_globals.h"
Yabin Cui294d1e22014-12-07 20:43:37 -080040#include "TemporaryFile.h"
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -080041#include "utils.h"
Dimitry Ivanov41fd2952016-05-09 17:37:39 -070042#include "dlext_private.h"
Dimitry Ivanov708589f2016-09-19 10:50:28 -070043#include "dlfcn_symlink_support.h"
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000044
45#define ASSERT_DL_NOTNULL(ptr) \
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070046 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000047
48#define ASSERT_DL_ZERO(i) \
49 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
50
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000051#define ASSERT_NOERROR(i) \
52 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
53
Yabin Cui16f7f8d2014-11-04 11:08:05 -080054#define ASSERT_SUBSTR(needle, haystack) \
55 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
56
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000057
58typedef int (*fn)(void);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070059constexpr const char* kLibName = "libdlext_test.so";
60constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
61constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
62constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070063
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000064class DlExtTest : public ::testing::Test {
65protected:
66 virtual void SetUp() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070067 handle_ = nullptr;
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000068 // verify that we don't have the library loaded already
Dimitry Ivanov927877c2016-09-21 11:17:13 -070069 void* h = dlopen(kLibName, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070070 ASSERT_TRUE(h == nullptr);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070071 h = dlopen(kLibNameNoRelro, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070072 ASSERT_TRUE(h == nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000073 // call dlerror() to swallow the error, and check it was the one we wanted
Dimitry Ivanov927877c2016-09-21 11:17:13 -070074 ASSERT_EQ(std::string("dlopen failed: library \"") + kLibNameNoRelro + "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000075 }
76
77 virtual void TearDown() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070078 if (handle_ != nullptr) {
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000079 ASSERT_DL_ZERO(dlclose(handle_));
80 }
81 }
82
83 void* handle_;
84};
85
86TEST_F(DlExtTest, ExtInfoNull) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -070087 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000088 ASSERT_DL_NOTNULL(handle_);
89 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
90 ASSERT_DL_NOTNULL(f);
91 EXPECT_EQ(4, f());
92}
93
94TEST_F(DlExtTest, ExtInfoNoFlags) {
95 android_dlextinfo extinfo;
96 extinfo.flags = 0;
Dimitry Ivanov927877c2016-09-21 11:17:13 -070097 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000098 ASSERT_DL_NOTNULL(handle_);
99 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
100 ASSERT_DL_NOTNULL(f);
101 EXPECT_EQ(4, f());
102}
103
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700104TEST_F(DlExtTest, ExtInfoUseFd) {
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800105 const std::string lib_path = get_testlib_root() + "/libdlext_test_fd/libdlext_test_fd.so";
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700106
107 android_dlextinfo extinfo;
108 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700109 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700110 ASSERT_TRUE(extinfo.library_fd != -1);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700111 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700112 ASSERT_DL_NOTNULL(handle_);
113 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
114 ASSERT_DL_NOTNULL(f);
115 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700116
117 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
118 ASSERT_DL_NOTNULL(taxicab_number);
119 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700120}
121
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700122TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800123 const std::string lib_path = get_testlib_root() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700124
125 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700126 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700127 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800128
129 // Find the offset of the shared library in the zip.
130 ZipArchiveHandle handle;
131 ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
132 ZipEntry zip_entry;
133 ZipString zip_name;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700134 zip_name.name = reinterpret_cast<const uint8_t*>(kLibZipSimpleZip);
135 zip_name.name_length = strlen(kLibZipSimpleZip);
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800136 ASSERT_EQ(0, FindEntry(handle, zip_name, &zip_entry));
137 extinfo.library_fd_offset = zip_entry.offset;
138 CloseArchive(handle);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700139
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700140 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700141 ASSERT_DL_NOTNULL(handle_);
142
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700143 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
144 ASSERT_DL_NOTNULL(taxicab_number);
145 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700146}
147
148TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800149 const std::string lib_path = get_testlib_root() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700150
151 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700152 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700153 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700154 extinfo.library_fd_offset = 17;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700155
156 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
157 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700158 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
159
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800160 // Test an address above 2^44, for http://b/18178121 .
161 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700162 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700163 ASSERT_TRUE(handle_ == nullptr);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800164 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
165
166 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
167 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
168 ASSERT_TRUE(handle_ == nullptr);
169 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
170
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700171 extinfo.library_fd_offset = 0;
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700172 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800173 ASSERT_TRUE(handle_ == nullptr);
Dimitry Ivanova36e59b2016-09-01 11:37:39 -0700174 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic", dlerror());
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700175
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -0800176 // Check if dlsym works after unsuccessful dlopen().
177 // Supply non-exiting one to make linker visit every soinfo.
178 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
179 ASSERT_TRUE(sym == nullptr);
180
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700181 close(extinfo.library_fd);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700182}
183
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800184TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700185 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700186 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800187 // This offset will not be used, so it doesn't matter.
188 extinfo.library_fd_offset = 0;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700189
190 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
191 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700192 ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700193}
194
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700195TEST(dlext, android_dlopen_ext_force_load_smoke) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700196 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
197 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700198 // 1. Open actual file
199 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
200 ASSERT_DL_NOTNULL(handle);
201 // 2. Open link with force_load flag set
202 android_dlextinfo extinfo;
203 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700204 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700205 ASSERT_DL_NOTNULL(handle2);
206 ASSERT_TRUE(handle != handle2);
207
208 dlclose(handle2);
209 dlclose(handle);
210}
211
212TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700213 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
214 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700215 // Check if soname lookup still returns already loaded library
216 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700217 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700218 ASSERT_DL_NOTNULL(handle);
219
220 android_dlextinfo extinfo;
221 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
222
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700223 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700224 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
225
226 ASSERT_DL_NOTNULL(handle2);
227 ASSERT_TRUE(handle == handle2);
228
229 dlclose(handle2);
230 dlclose(handle);
231}
232
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700233TEST(dlfcn, dlopen_from_zip_absolute_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700234 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800235 const std::string lib_path = get_testlib_root() + lib_zip_path;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700236
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700237 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700238 ASSERT_TRUE(handle != nullptr) << dlerror();
239
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700240 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
241 ASSERT_DL_NOTNULL(taxicab_number);
242 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700243
244 dlclose(handle);
245}
246
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700247TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700248 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800249 const std::string lib_path = get_testlib_root() + lib_zip_path;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700250
251 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
252
253 ASSERT_TRUE(handle != nullptr) << dlerror();
254
255 typedef void *(* dlopen_b_fn)();
256 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
257 ASSERT_TRUE(fn != nullptr) << dlerror();
258
259 void *p = fn();
260 ASSERT_TRUE(p != nullptr) << dlerror();
261
262 dlclose(p);
263 dlclose(handle);
264}
265
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700266TEST(dlfcn, dlopen_from_zip_ld_library_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700267 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800268 const std::string lib_path = get_testlib_root() + lib_zip_path + "!/libdir";
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700269
270 typedef void (*fn_t)(const char*);
271 fn_t android_update_LD_LIBRARY_PATH =
272 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
273
274 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
275
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700276 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700277 ASSERT_TRUE(handle == nullptr);
278
279 android_update_LD_LIBRARY_PATH(lib_path.c_str());
280
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700281 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700282 ASSERT_TRUE(handle != nullptr) << dlerror();
283
284 int (*fn)(void);
285 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
286 ASSERT_TRUE(fn != nullptr);
287 EXPECT_EQ(4, fn());
288
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800289 uint32_t* taxicab_number =
290 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700291 ASSERT_DL_NOTNULL(taxicab_number);
292 EXPECT_EQ(1729U, *taxicab_number);
293
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700294 dlclose(handle);
295}
296
297
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000298TEST_F(DlExtTest, Reserved) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700299 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000300 ASSERT_TRUE(start != MAP_FAILED);
301 android_dlextinfo extinfo;
302 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
303 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700304 extinfo.reserved_size = kLibSize;
305 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000306 ASSERT_DL_NOTNULL(handle_);
307 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
308 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700309 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000310 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700311 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000312 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800313
314 // Check that after dlclose reserved address space is unmapped (and can be reused)
315 dlclose(handle_);
316 handle_ = nullptr;
317
318 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
319 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000320}
321
322TEST_F(DlExtTest, ReservedTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800323 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000324 ASSERT_TRUE(start != MAP_FAILED);
325 android_dlextinfo extinfo;
326 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
327 extinfo.reserved_addr = start;
328 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700329 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700330 EXPECT_EQ(nullptr, handle_);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000331}
332
333TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700334 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000335 ASSERT_TRUE(start != MAP_FAILED);
336 android_dlextinfo extinfo;
337 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
338 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700339 extinfo.reserved_size = kLibSize;
340 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000341 ASSERT_DL_NOTNULL(handle_);
342 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
343 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700344 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000345 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700346 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000347 EXPECT_EQ(4, f());
348}
349
350TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800351 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000352 ASSERT_TRUE(start != MAP_FAILED);
353 android_dlextinfo extinfo;
354 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
355 extinfo.reserved_addr = start;
356 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700357 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000358 ASSERT_DL_NOTNULL(handle_);
359 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
360 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700361 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
362 (reinterpret_cast<void*>(f) >=
363 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000364 EXPECT_EQ(4, f());
365}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000366
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700367TEST_F(DlExtTest, LoadAtFixedAddress) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700368 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700369 ASSERT_TRUE(start != MAP_FAILED);
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700370 munmap(start, kLibSize);
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700371
372 android_dlextinfo extinfo;
373 extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
374 extinfo.reserved_addr = start;
375
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700376 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700377 ASSERT_DL_NOTNULL(handle_);
378 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
379 ASSERT_DL_NOTNULL(f);
380 EXPECT_GE(reinterpret_cast<void*>(f), start);
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700381 EXPECT_LT(reinterpret_cast<void*>(f), reinterpret_cast<char*>(start) + kLibSize);
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700382
383 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800384 dlclose(handle_);
385 handle_ = nullptr;
386
387 // Check that dlclose unmapped the file
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700388 void* addr = mmap(start, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800389 ASSERT_EQ(start, addr) << "dlclose did not unmap the memory";
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700390}
391
392TEST_F(DlExtTest, LoadAtFixedAddressTooSmall) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700393 void* start = mmap(nullptr, kLibSize + PAGE_SIZE, PROT_NONE,
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700394 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
395 ASSERT_TRUE(start != MAP_FAILED);
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700396 munmap(start, kLibSize + PAGE_SIZE);
397 void* new_addr = mmap(reinterpret_cast<uint8_t*>(start) + PAGE_SIZE, kLibSize, PROT_NONE,
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700398 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
399 ASSERT_TRUE(new_addr != MAP_FAILED);
400
401 android_dlextinfo extinfo;
402 extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
403 extinfo.reserved_addr = start;
404
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700405 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov126af752015-10-07 16:34:20 -0700406 ASSERT_TRUE(handle_ == nullptr);
407}
408
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100409class DlExtRelroSharingTest : public DlExtTest {
410protected:
411 virtual void SetUp() {
412 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700413 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100414 ASSERT_TRUE(start != MAP_FAILED);
415 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
416 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700417 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100418 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000419 }
420
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100421 virtual void TearDown() {
422 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100423 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000424
Yabin Cui294d1e22014-12-07 20:43:37 -0800425 void CreateRelroFile(const char* lib, const char* relro_file) {
426 int relro_fd = open(relro_file, O_RDWR | O_TRUNC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100427 ASSERT_NOERROR(relro_fd);
428
429 pid_t pid = fork();
430 if (pid == 0) {
431 // child process
432 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
433 extinfo_.relro_fd = relro_fd;
434 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700435 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100436 fprintf(stderr, "in child: %s\n", dlerror());
437 exit(1);
438 }
439 exit(0);
440 }
441
442 // continuing in parent
443 ASSERT_NOERROR(close(relro_fd));
444 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800445 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100446
447 // reopen file for reading so it can be used
Yabin Cui294d1e22014-12-07 20:43:37 -0800448 relro_fd = open(relro_file, O_RDONLY);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100449 ASSERT_NOERROR(relro_fd);
450 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
451 extinfo_.relro_fd = relro_fd;
452 }
453
454 void TryUsingRelro(const char* lib) {
455 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
456 ASSERT_DL_NOTNULL(handle_);
457 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
458 ASSERT_DL_NOTNULL(f);
459 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700460
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800461 uint32_t* taxicab_number =
462 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700463 ASSERT_DL_NOTNULL(taxicab_number);
464 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100465 }
466
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100467 void SpawnChildrenAndMeasurePss(const char* lib, bool share_relro, size_t* pss_out);
468
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100469 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100470};
471
472TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800473 TemporaryFile tf; // Use tf to get an unique filename.
474 ASSERT_NOERROR(close(tf.fd));
475
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700476 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
477 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
Yabin Cui294d1e22014-12-07 20:43:37 -0800478
479 // Use destructor of tf to close and unlink the file.
480 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100481}
482
483TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800484 TemporaryFile tf; // // Use tf to get an unique filename.
485 ASSERT_NOERROR(close(tf.fd));
486
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700487 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.filename));
488 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro));
Yabin Cui294d1e22014-12-07 20:43:37 -0800489
490 // Use destructor of tf to close and unlink the file.
491 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100492}
493
494TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700495 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000496}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100497
498TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Dan Albert69fb9f32014-09-03 11:30:21 -0700499 if (geteuid() != 0) {
500 GTEST_LOG_(INFO) << "This test must be run as root.\n";
501 return;
502 }
503
Yabin Cui294d1e22014-12-07 20:43:37 -0800504 TemporaryFile tf; // Use tf to get an unique filename.
505 ASSERT_NOERROR(close(tf.fd));
506
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700507 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
Yabin Cui294d1e22014-12-07 20:43:37 -0800508
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100509 int pipefd[2];
510 ASSERT_NOERROR(pipe(pipefd));
511
512 size_t without_sharing, with_sharing;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700513 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, false, &without_sharing));
514 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, true, &with_sharing));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100515
516 // We expect the sharing to save at least 10% of the total PSS. In practice
517 // it saves 40%+ for this test.
518 size_t expected_size = without_sharing - (without_sharing/10);
519 EXPECT_LT(with_sharing, expected_size);
Yabin Cui294d1e22014-12-07 20:43:37 -0800520
521 // Use destructor of tf to close and unlink the file.
522 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100523}
524
525void getPss(pid_t pid, size_t* pss_out) {
526 pm_kernel_t* kernel;
527 ASSERT_EQ(0, pm_kernel_create(&kernel));
528
529 pm_process_t* process;
530 ASSERT_EQ(0, pm_process_create(kernel, pid, &process));
531
532 pm_map_t** maps;
533 size_t num_maps;
534 ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
535
536 size_t total_pss = 0;
537 for (size_t i = 0; i < num_maps; i++) {
538 pm_memusage_t usage;
539 ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
540 total_pss += usage.pss;
541 }
542 *pss_out = total_pss;
543
544 free(maps);
545 pm_process_destroy(process);
546 pm_kernel_destroy(kernel);
547}
548
549void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool share_relro,
550 size_t* pss_out) {
551 const int CHILDREN = 20;
552
553 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800554 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100555 int childpipe[CHILDREN];
556 for (int i=0; i<CHILDREN; ++i) {
557 char read_buf;
558 int child_done_pipe[2], parent_done_pipe[2];
559 ASSERT_NOERROR(pipe(child_done_pipe));
560 ASSERT_NOERROR(pipe(parent_done_pipe));
561
562 pid_t child = fork();
563 if (child == 0) {
564 // close the 'wrong' ends of the pipes in the child
565 close(child_done_pipe[0]);
566 close(parent_done_pipe[1]);
567
568 // open the library
569 void* handle;
570 if (share_relro) {
571 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
572 } else {
573 handle = dlopen(lib, RTLD_NOW);
574 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700575 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100576 fprintf(stderr, "in child: %s\n", dlerror());
577 exit(1);
578 }
579
580 // close write end of child_done_pipe to signal the parent that we're done.
581 close(child_done_pipe[1]);
582
583 // wait for the parent to close parent_done_pipe, then exit
584 read(parent_done_pipe[0], &read_buf, 1);
585 exit(0);
586 }
587
588 ASSERT_NOERROR(child);
589
590 // close the 'wrong' ends of the pipes in the parent
591 close(child_done_pipe[1]);
592 close(parent_done_pipe[0]);
593
594 // wait for the child to be done
595 read(child_done_pipe[0], &read_buf, 1);
596 close(child_done_pipe[0]);
597
598 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800599 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100600 childpipe[i] = parent_done_pipe[1];
601 }
602
603 // Sum the PSS of all the children
604 size_t total_pss = 0;
605 for (int i=0; i<CHILDREN; ++i) {
606 size_t child_pss;
Elliott Hughes33697a02016-01-26 13:04:57 -0800607 ASSERT_NO_FATAL_FAILURE(getPss(child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100608 total_pss += child_pss;
609 }
610 *pss_out = total_pss;
611
612 // Close pipes and wait for children to exit
613 for (int i=0; i<CHILDREN; ++i) {
614 ASSERT_NOERROR(close(childpipe[i]));
615 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800616 for (int i = 0; i < CHILDREN; ++i) {
617 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100618 }
619}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700620
621// Testing namespaces
622static const char* g_public_lib = "libnstest_public.so";
623
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800624// These are libs shared with default namespace
625static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
626
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700627TEST(dlext, ns_smoke) {
628 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800629 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700630
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800631 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
632 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
633 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
634 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700635
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800636 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800637 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700638 ASSERT_TRUE(handle_public != nullptr) << dlerror();
639
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800640 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700641
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800642 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700643 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800644 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800645 ASSERT_TRUE(handle_public == nullptr);
646 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
647 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
648
649 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700650
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800651 // create "public namespace", share limited set of public libraries with
652
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800653 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800654 android_create_namespace("private",
655 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800656 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800657 ANDROID_NAMESPACE_TYPE_REGULAR,
658 nullptr,
659 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700660 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800661 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700662
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800663 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800664 android_create_namespace("private_isolated",
665 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -0800666 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800667 ANDROID_NAMESPACE_TYPE_ISOLATED,
668 nullptr,
669 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700670 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800671 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700672
673 // This should not have affect search path for default namespace:
674 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
675 void* handle = dlopen(g_public_lib, RTLD_NOW);
676 ASSERT_TRUE(handle != nullptr) << dlerror();
677 dlclose(handle);
678
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700679 // dlopen for a public library using an absolute path should work
680 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700681 android_dlextinfo extinfo;
682 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700683 extinfo.library_namespace = ns2;
684 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
685 ASSERT_TRUE(handle != nullptr) << dlerror();
686 ASSERT_TRUE(handle == handle_public);
687
688 dlclose(handle);
689
690 // 1.1 even if it wasn't loaded before
691 dlclose(handle_public);
692
693 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
694 ASSERT_TRUE(handle_public == nullptr);
695 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
696 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
697
698 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
699 ASSERT_TRUE(handle != nullptr) << dlerror();
700
701 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
702 ASSERT_TRUE(handle == handle_public);
703
704 dlclose(handle);
705
706 // 2. And for regular namespaces (make sure it does not load second copy of the library)
707 extinfo.library_namespace = ns1;
708 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
709 ASSERT_TRUE(handle != nullptr) << dlerror();
710 ASSERT_TRUE(handle == handle_public);
711
712 dlclose(handle);
713
714 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
715 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
716 dlclose(handle_public);
717
718 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
719 ASSERT_TRUE(handle_public == nullptr);
720 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
721 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
722
723 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
724 ASSERT_TRUE(handle != nullptr) << dlerror();
725
726 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
727
728 ASSERT_TRUE(handle != handle_public);
729
730 dlclose(handle);
731
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700732 extinfo.library_namespace = ns1;
733
734 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
735 ASSERT_TRUE(handle1 != nullptr) << dlerror();
736
737 extinfo.library_namespace = ns2;
738 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
739 ASSERT_TRUE(handle2 != nullptr) << dlerror();
740
741 ASSERT_TRUE(handle1 != handle2);
742
743 typedef const char* (*fn_t)();
744
745 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
746 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
747 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
748 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
749
750 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
751 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
752
753 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
754
755 fn_t ns_get_private_extern_string1 =
756 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
757 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
758 fn_t ns_get_private_extern_string2 =
759 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
760 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
761
762 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
763 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
764
765 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
766
767 fn_t ns_get_public_extern_string1 =
768 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
769 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
770 fn_t ns_get_public_extern_string2 =
771 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
772 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
773
774 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
775 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
776
777 // and now check that dlopen() does the right thing in terms of preserving namespace
778 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
779 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
780 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
781 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
782
783 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
784 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
785
786 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
787
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800788 // Check that symbols from non-shared libraries a shared library depends on are not visible
789 // from original namespace.
790
791 fn_t ns_get_internal_extern_string =
792 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
793 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
794 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
795 "ns_get_internal_extern_string() expected to return null but returns \"" <<
796 ns_get_internal_extern_string() << "\"";
797
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700798 dlclose(handle1);
799
800 // Check if handle2 is still alive (and well)
801 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
802 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
803 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
804 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
805
806 dlclose(handle2);
807}
808
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700809TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
810 const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
811
812 int tmpfd = TEMP_FAILURE_RETRY(
813 open(get_testlib_root().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL));
814
815 // Ignore kernels without O_TMPFILE flag support
816 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
817 return;
818 }
819
820 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
821
822 android_namespace_t* ns =
823 android_create_namespace("testing-o_tmpfile",
824 nullptr,
825 get_testlib_root().c_str(),
826 ANDROID_NAMESPACE_TYPE_ISOLATED,
827 nullptr,
828 nullptr);
829
830 ASSERT_DL_NOTNULL(ns);
831
832 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
833
834 std::string content;
835 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
836 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
837
838 android_dlextinfo extinfo;
839 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
840 extinfo.library_fd = tmpfd;
841 extinfo.library_namespace = ns;
842
843 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
844
845 ASSERT_DL_NOTNULL(handle);
846
847 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
848 ASSERT_DL_NOTNULL(taxicab_number);
849 EXPECT_EQ(1729U, *taxicab_number);
850 dlclose(handle);
851}
852
853TEST(dlext, dlopen_ext_use_memfd) {
854 const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
855
856 // create memfd
857 int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
858 if (memfd == -1 && errno == ENOSYS) {
859 return;
860 }
861
862 ASSERT_TRUE(memfd != -1) << strerror(errno);
863
864 // Check st.f_type is TMPFS_MAGIC for memfd
865 struct statfs st;
866 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
867 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
868
869 android_namespace_t* ns =
870 android_create_namespace("testing-memfd",
871 nullptr,
872 get_testlib_root().c_str(),
873 ANDROID_NAMESPACE_TYPE_ISOLATED,
874 nullptr,
875 nullptr);
876
877 ASSERT_DL_NOTNULL(ns);
878
879 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
880
881 // read file into memfd backed one.
882 std::string content;
883 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
884 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
885
886 android_dlextinfo extinfo;
887 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
888 extinfo.library_fd = memfd;
889 extinfo.library_namespace = ns;
890
891 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
892
893 ASSERT_DL_NOTNULL(handle);
894
895 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
896 ASSERT_DL_NOTNULL(taxicab_number);
897 EXPECT_EQ(1729U, *taxicab_number);
898 dlclose(handle);
899}
900
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800901TEST(dlext, ns_symbol_visibilty_one_namespace) {
902 static const char* root_lib = "libnstest_root.so";
903 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
904
905 const std::string ns_search_path = get_testlib_root() + "/public_namespace_libs:" +
906 get_testlib_root() + "/private_namespace_libs";
907
908 android_namespace_t* ns =
909 android_create_namespace("one",
910 nullptr,
911 ns_search_path.c_str(),
912 ANDROID_NAMESPACE_TYPE_ISOLATED,
913 nullptr,
914 nullptr);
915
916 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
917
918 android_dlextinfo extinfo;
919 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
920 extinfo.library_namespace = ns;
921
922 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
923 ASSERT_TRUE(handle != nullptr) << dlerror();
924
925 typedef const char* (*fn_t)();
926
927 // Check that relocation worked correctly
928 fn_t ns_get_internal_extern_string =
929 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
930 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
931 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
932
933 fn_t internal_extern_string_fn =
934 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
935 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
936 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
937}
938
939TEST(dlext, ns_symbol_visibilty_between_namespaces) {
940 static const char* root_lib = "libnstest_root.so";
941 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
942
943 const std::string public_ns_search_path = get_testlib_root() + "/public_namespace_libs";
944 const std::string private_ns_search_path = get_testlib_root() + "/private_namespace_libs";
945
946 android_namespace_t* ns_public =
947 android_create_namespace("public",
948 nullptr,
949 public_ns_search_path.c_str(),
950 ANDROID_NAMESPACE_TYPE_ISOLATED,
951 nullptr,
952 nullptr);
953
954 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
955
956 android_namespace_t* ns_private =
957 android_create_namespace("private",
958 nullptr,
959 private_ns_search_path.c_str(),
960 ANDROID_NAMESPACE_TYPE_ISOLATED,
961 nullptr,
962 nullptr);
963
964 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
965 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
966
967 android_dlextinfo extinfo;
968 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
969 extinfo.library_namespace = ns_private;
970
971 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
972 ASSERT_TRUE(handle != nullptr) << dlerror();
973
974 typedef const char* (*fn_t)();
975
976 // Check that relocation worked correctly
977 fn_t ns_get_internal_extern_string =
978 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
979 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
980 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
981 "ns_get_internal_extern_string() expected to return null but returns \"" <<
982 ns_get_internal_extern_string() << "\"";
983
984 fn_t internal_extern_string_fn =
985 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
986 ASSERT_TRUE(internal_extern_string_fn == nullptr);
987 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
988}
989
990TEST(dlext, ns_unload_between_namespaces) {
991 static const char* root_lib = "libnstest_root.so";
992 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
993
994 const std::string public_ns_search_path = get_testlib_root() + "/public_namespace_libs";
995 const std::string private_ns_search_path = get_testlib_root() + "/private_namespace_libs";
996
997 android_namespace_t* ns_public =
998 android_create_namespace("public",
999 nullptr,
1000 public_ns_search_path.c_str(),
1001 ANDROID_NAMESPACE_TYPE_ISOLATED,
1002 nullptr,
1003 nullptr);
1004
1005 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1006
1007 android_namespace_t* ns_private =
1008 android_create_namespace("private",
1009 nullptr,
1010 private_ns_search_path.c_str(),
1011 ANDROID_NAMESPACE_TYPE_ISOLATED,
1012 nullptr,
1013 nullptr);
1014
1015 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1016 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1017
1018 android_dlextinfo extinfo;
1019 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1020 extinfo.library_namespace = ns_private;
1021
1022 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1023 ASSERT_TRUE(handle != nullptr) << dlerror();
1024
1025 dlclose(handle);
1026 // Check that root_lib was unloaded
1027 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1028 ASSERT_TRUE(handle == nullptr);
1029 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1030 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1031
1032 // Check that shared library was unloaded in public ns
1033 extinfo.library_namespace = ns_public;
1034 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1035 ASSERT_TRUE(handle == nullptr);
1036 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1037 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1038}
1039
Dimitry Ivanov18623142017-02-21 13:41:08 -08001040TEST(dlext, ns_greylist) {
1041 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1042
1043 const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs";
1044
1045 android_namespace_t* ns =
1046 android_create_namespace("namespace",
1047 nullptr,
1048 ns_search_path.c_str(),
1049 ANDROID_NAMESPACE_TYPE_ISOLATED,
1050 nullptr,
1051 nullptr);
1052
1053 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1054
1055 android_dlextinfo extinfo;
1056 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1057 extinfo.library_namespace = ns;
1058
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001059 // An app targeting M can open libnativehelper.so because it's on the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001060 android_set_application_target_sdk_version(__ANDROID_API_M__);
1061 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1062 ASSERT_TRUE(handle != nullptr) << dlerror();
1063
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001064 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1065 void* dlsym_ptr = dlsym(handle, "dlsym");
1066 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1067 ASSERT_EQ(&dlsym, dlsym_ptr);
1068
Dimitry Ivanov18623142017-02-21 13:41:08 -08001069 dlclose(handle);
1070
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001071 // An app targeting N no longer has the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001072 android_set_application_target_sdk_version(__ANDROID_API_N__);
1073 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1074 ASSERT_TRUE(handle == nullptr);
1075 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1076}
1077
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001078TEST(dlext, ns_cyclic_namespaces) {
1079 // Test that ns1->ns2->ns1 link does not break the loader
1080 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1081 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1082
1083 const std::string ns_search_path = get_testlib_root() + "/public_namespace_libs";
1084
1085 android_namespace_t* ns1 =
1086 android_create_namespace("ns1",
1087 nullptr,
1088 ns_search_path.c_str(),
1089 ANDROID_NAMESPACE_TYPE_ISOLATED,
1090 nullptr,
1091 nullptr);
1092
1093 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1094
1095 android_namespace_t* ns2 =
1096 android_create_namespace("ns1",
1097 nullptr,
1098 ns_search_path.c_str(),
1099 ANDROID_NAMESPACE_TYPE_ISOLATED,
1100 nullptr,
1101 nullptr);
1102
1103 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1104
1105 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1106 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1107
1108 android_dlextinfo extinfo;
1109 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1110 extinfo.library_namespace = ns1;
1111
1112 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1113 ASSERT_TRUE(handle == nullptr);
1114 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1115}
1116
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001117TEST(dlext, ns_isolated) {
1118 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001119 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001120
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001121 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001122 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001123 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1124
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001125 android_set_application_target_sdk_version(42U); // something > 23
1126
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001127 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001128
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001129 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001130 android_create_namespace("private",
1131 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001132 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001133 ANDROID_NAMESPACE_TYPE_REGULAR,
1134 nullptr,
1135 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001136 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001137 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001138
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001139 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001140 android_create_namespace("private_isolated1",
1141 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001142 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001143 ANDROID_NAMESPACE_TYPE_ISOLATED,
1144 nullptr,
1145 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001146 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001147 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001148
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001149 android_namespace_t* ns_isolated2 =
1150 android_create_namespace("private_isolated2",
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001151 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001152 nullptr,
1153 ANDROID_NAMESPACE_TYPE_ISOLATED,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001154 get_testlib_root().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001155 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001156 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001157 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001158
1159 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1160 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1161
1162 std::string lib_private_external_path =
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001163 get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001164
1165 // Load lib_private_external_path to default namespace
1166 // (it should remain invisible for the isolated namespaces after this)
1167 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1168 ASSERT_TRUE(handle != nullptr) << dlerror();
1169
1170 android_dlextinfo extinfo;
1171 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1172 extinfo.library_namespace = ns_not_isolated;
1173
1174 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1175 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1176
1177 extinfo.library_namespace = ns_isolated;
1178
1179 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1180 ASSERT_TRUE(handle2 == nullptr);
1181 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1182
1183 // Check dlopen by absolute path
1184 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1185 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001186 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -07001187 " or dlopened by \"" + get_executable_path() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001188 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001189
1190 extinfo.library_namespace = ns_isolated2;
1191
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001192 // this should work because isolation_path for private_isolated2 includes get_testlib_root()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001193 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001194 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1195 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001196
1197 // Check dlopen by absolute path
1198 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001199 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1200 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001201
1202 typedef const char* (*fn_t)();
1203 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1204 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1205
1206 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1207
1208 fn_t ns_get_private_extern_string =
1209 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1210 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1211
1212 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1213
1214 fn_t ns_get_public_extern_string =
1215 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1216 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1217
1218 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1219
1220 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1221 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1222
1223 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1224
1225 dlclose(handle1);
1226}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001227
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001228TEST(dlext, ns_shared) {
1229 static const char* root_lib = "libnstest_root_not_isolated.so";
1230 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001231
1232 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001233
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001234 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001235 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1236 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1237
1238 android_set_application_target_sdk_version(42U); // something > 23
1239
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001240 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001241
1242 // preload this library to the default namespace to check if it
1243 // is shared later on.
1244 void* handle_dlopened =
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001245 dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001246 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1247
1248 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001249 android_create_namespace("private",
1250 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001251 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001252 ANDROID_NAMESPACE_TYPE_REGULAR,
1253 nullptr,
1254 nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001255 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001256 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001257
1258 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001259 android_create_namespace("private_isolated_shared",
1260 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001261 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001262 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001263 nullptr,
1264 nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001265 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001266 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001267
1268 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1269 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1270
1271 std::string lib_private_external_path =
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001272 get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001273
1274 // Load lib_private_external_path to default namespace
1275 // (it should remain invisible for the isolated namespaces after this)
1276 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1277 ASSERT_TRUE(handle != nullptr) << dlerror();
1278
1279 android_dlextinfo extinfo;
1280 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1281 extinfo.library_namespace = ns_not_isolated;
1282
1283 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1284 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1285
1286 extinfo.library_namespace = ns_isolated_shared;
1287
1288 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1289 ASSERT_TRUE(handle2 == nullptr);
1290 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1291
1292 // Check dlopen by absolute path
1293 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1294 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001295 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -07001296 " or dlopened by \"" + get_executable_path() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001297 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001298
1299 // load libnstest_root.so to shared namespace in order to check that everything is different
1300 // except shared libnstest_dlopened.so
1301
1302 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1303
1304 typedef const char* (*fn_t)();
1305 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1306 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1307 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1308 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1309
1310 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1311 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1312 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1313
1314 fn_t ns_get_private_extern_string =
1315 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1316 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1317 fn_t ns_get_private_extern_string_shared =
1318 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1319 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1320
1321 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1322 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1323 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1324
1325 fn_t ns_get_public_extern_string =
1326 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1327 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1328 fn_t ns_get_public_extern_string_shared =
1329 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1330 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1331
1332 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1333 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1334 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1335
1336 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1337 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1338 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1339 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1340 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1341 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1342
1343 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1344 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1345 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1346 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1347 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1348
1349 dlclose(handle1);
1350 dlclose(handle2);
1351}
1352
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001353TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001354 android_set_application_target_sdk_version(42U); // something > 23
1355
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001356 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001357
1358 // preload this library to the default namespace to check if it
1359 // is shared later on.
1360 void* handle_dlopened =
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001361 dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001362 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1363
1364 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001365 android_create_namespace("private_isolated_shared",
1366 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001367 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001368 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001369 nullptr,
1370 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001371 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001372 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001373
1374 // Check if "libnstest_dlopened.so" is loaded (and the same)
1375 android_dlextinfo extinfo;
1376 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1377 extinfo.library_namespace = ns_isolated_shared;
1378
1379 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1380 ASSERT_TRUE(handle != nullptr) << dlerror();
1381 ASSERT_TRUE(handle == handle_dlopened);
1382 dlclose(handle);
1383 dlclose(handle_dlopened);
1384
1385 // And now check that the library cannot be found by soname (and is no longer loaded)
1386 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1387 ASSERT_TRUE(handle == nullptr)
1388 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1389
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001390 handle = android_dlopen_ext((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001391 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1392 ASSERT_TRUE(handle == nullptr)
1393 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1394
1395 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1396 ASSERT_TRUE(handle == nullptr)
1397 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1398
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001399 handle = dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001400 RTLD_NOW | RTLD_NOLOAD);
1401 ASSERT_TRUE(handle == nullptr)
1402 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1403
1404 // Now lets see if the soinfo area gets reused in the wrong way:
1405 // load a library to default namespace.
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001406 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001407 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1408 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1409
1410 // try to find it in shared namespace
1411 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1412 ASSERT_TRUE(handle == nullptr)
1413 << "Error: " << g_public_lib << " is accessible in shared namespace";
1414}
1415
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001416TEST(dlext, ns_isolated_rtld_global) {
1417 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001418 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001419
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001420 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001421
1422 android_namespace_t* ns1 =
1423 android_create_namespace("isolated1",
1424 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001425 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001426 ANDROID_NAMESPACE_TYPE_ISOLATED,
1427 lib_public_path.c_str(),
1428 nullptr);
1429 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001430 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001431
1432 android_namespace_t* ns2 =
1433 android_create_namespace("isolated2",
1434 nullptr,
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001435 (get_testlib_root() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001436 ANDROID_NAMESPACE_TYPE_ISOLATED,
1437 lib_public_path.c_str(),
1438 nullptr);
1439 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001440 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001441
1442 android_dlextinfo extinfo;
1443 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1444 extinfo.library_namespace = ns1;
1445
1446 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1447 RTLD_GLOBAL,
1448 &extinfo);
1449
1450 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1451
1452 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001453 android_create_namespace("isolated1_child",
1454 nullptr,
1455 (get_testlib_root() + "/private_namespace_libs").c_str(),
1456 ANDROID_NAMESPACE_TYPE_ISOLATED,
1457 nullptr,
1458 ns1);
1459
1460 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1461 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001462
1463 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1464 // attempt to use ns2 should result in dlerror()
1465
1466 // Check ns1_child first.
1467 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1468 extinfo.library_namespace = ns1_child;
1469
1470 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1471 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1472
1473 // now ns1
1474 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1475 extinfo.library_namespace = ns1;
1476
1477 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1478 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1479
1480 // and ns2 should fail
1481 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1482 extinfo.library_namespace = ns2;
1483
1484 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1485 ASSERT_TRUE(handle1 == nullptr);
1486 ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
1487}
1488
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001489TEST(dlext, ns_anonymous) {
1490 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001491 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001492
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001493 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001494 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1495
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001496 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1497
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001498 ASSERT_TRUE(
1499 android_init_anonymous_namespace(shared_libs.c_str(),
1500 (get_testlib_root() + "/private_namespace_libs").c_str())
1501 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001502
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001503 android_namespace_t* ns =
1504 android_create_namespace("private",
1505 nullptr,
1506 (get_testlib_root() + "/private_namespace_libs").c_str(),
1507 ANDROID_NAMESPACE_TYPE_REGULAR,
1508 nullptr,
1509 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001510
1511 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001512 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001513
Dimitry Ivanovd0b5c3a2016-11-25 12:23:11 -08001514 std::string private_library_absolute_path = get_testlib_root() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001515
1516 android_dlextinfo extinfo;
1517 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1518 extinfo.library_namespace = ns;
1519
1520 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1521 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1522 ASSERT_TRUE(handle != nullptr) << dlerror();
1523
1524 uintptr_t ns_get_dlopened_string_addr =
1525 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1526 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1527 typedef const char* (*fn_t)();
1528 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1529
1530 std::vector<map_record> maps;
1531 Maps::parse_maps(&maps);
1532
1533 uintptr_t addr_start = 0;
1534 uintptr_t addr_end = 0;
1535 std::vector<map_record> maps_to_copy;
1536
1537 for (const auto& rec : maps) {
1538 if (rec.pathname == private_library_absolute_path) {
1539 if (addr_start == 0) {
1540 addr_start = rec.addr_start;
1541 }
1542 addr_end = rec.addr_end;
1543
1544 maps_to_copy.push_back(rec);
1545 }
1546 }
1547
1548 // some sanity checks..
1549 ASSERT_TRUE(addr_start > 0);
1550 ASSERT_TRUE(addr_end > 0);
1551 ASSERT_EQ(3U, maps_to_copy.size());
1552 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
1553 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
1554
1555 // copy
1556 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
1557 PROT_NONE, MAP_ANON | MAP_PRIVATE,
1558 -1, 0));
1559 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
1560
1561 for (const auto& rec : maps_to_copy) {
1562 uintptr_t offset = rec.addr_start - addr_start;
1563 size_t size = rec.addr_end - rec.addr_start;
1564 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
1565 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
1566 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
1567 ASSERT_TRUE(map != MAP_FAILED);
1568 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
1569 mprotect(map, size, rec.perms);
1570 }
1571
1572 // call the function copy
1573 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
1574 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
1575 ASSERT_STREQ("This string is from private namespace (dlopened library)",
1576 ns_get_dlopened_string_anon());
1577
1578 // They should belong to different namespaces (private and anonymous)
1579 ASSERT_STREQ("This string is from private namespace (dlopened library)",
1580 ns_get_dlopened_string_private());
1581
1582 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
1583}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07001584
1585TEST(dlext, dlopen_handle_value_platform) {
1586 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
1587 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
1588 << "dlopen should return odd value for the handle";
1589 dlclose(handle);
1590}
1591
1592TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08001593 android_set_application_target_sdk_version(__ANDROID_API_M__);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07001594 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
1595 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
1596 << "dlopen should return valid pointer";
1597 dlclose(handle);
1598}