blob: bea18e5631153b634962aca738ff4997ea7167c5 [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>
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -070029#include <android-base/file.h>
Zhenhua WANG81aad002017-04-25 11:07:19 +080030#include <android-base/strings.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070031
32#include <linux/memfd.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000033#include <sys/mman.h>
Elliott Hughesd7c52622017-06-20 14:26:56 -070034#include <sys/syscall.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010035#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070036#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000037#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000038
Torne (Richard Coles)26052612014-05-02 14:57:42 +010039#include <pagemap/pagemap.h>
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -080040#include <ziparchive/zip_archive.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010041
Dimitry Ivanov927877c2016-09-21 11:17:13 -070042#include "gtest_globals.h"
Yabin Cui294d1e22014-12-07 20:43:37 -080043#include "TemporaryFile.h"
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -080044#include "utils.h"
Dimitry Ivanov41fd2952016-05-09 17:37:39 -070045#include "dlext_private.h"
Dimitry Ivanov708589f2016-09-19 10:50:28 -070046#include "dlfcn_symlink_support.h"
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000047
48#define ASSERT_DL_NOTNULL(ptr) \
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070049 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000050
51#define ASSERT_DL_ZERO(i) \
52 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
53
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000054#define ASSERT_NOERROR(i) \
55 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
56
Yabin Cui16f7f8d2014-11-04 11:08:05 -080057#define ASSERT_SUBSTR(needle, haystack) \
58 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
59
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000060
61typedef int (*fn)(void);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070062constexpr const char* kLibName = "libdlext_test.so";
63constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
64constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
65constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070066
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000067class DlExtTest : public ::testing::Test {
68protected:
69 virtual void SetUp() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070070 handle_ = nullptr;
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000071 // verify that we don't have the library loaded already
Dimitry Ivanov927877c2016-09-21 11:17:13 -070072 void* h = dlopen(kLibName, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070073 ASSERT_TRUE(h == nullptr);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070074 h = dlopen(kLibNameNoRelro, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070075 ASSERT_TRUE(h == nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000076 // call dlerror() to swallow the error, and check it was the one we wanted
Dimitry Ivanov927877c2016-09-21 11:17:13 -070077 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 +000078 }
79
80 virtual void TearDown() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070081 if (handle_ != nullptr) {
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000082 ASSERT_DL_ZERO(dlclose(handle_));
83 }
84 }
85
86 void* handle_;
87};
88
89TEST_F(DlExtTest, ExtInfoNull) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -070090 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000091 ASSERT_DL_NOTNULL(handle_);
92 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
93 ASSERT_DL_NOTNULL(f);
94 EXPECT_EQ(4, f());
95}
96
97TEST_F(DlExtTest, ExtInfoNoFlags) {
98 android_dlextinfo extinfo;
99 extinfo.flags = 0;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700100 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000101 ASSERT_DL_NOTNULL(handle_);
102 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
103 ASSERT_DL_NOTNULL(f);
104 EXPECT_EQ(4, f());
105}
106
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700107TEST_F(DlExtTest, ExtInfoUseFd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700108 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_fd/libdlext_test_fd.so";
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700109
110 android_dlextinfo extinfo;
111 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700112 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700113 ASSERT_TRUE(extinfo.library_fd != -1);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700114 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700115 ASSERT_DL_NOTNULL(handle_);
116 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
117 ASSERT_DL_NOTNULL(f);
118 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700119
120 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
121 ASSERT_DL_NOTNULL(taxicab_number);
122 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700123}
124
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700125TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700126 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700127
128 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700129 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700130 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800131
132 // Find the offset of the shared library in the zip.
133 ZipArchiveHandle handle;
134 ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
135 ZipEntry zip_entry;
136 ZipString zip_name;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700137 zip_name.name = reinterpret_cast<const uint8_t*>(kLibZipSimpleZip);
138 zip_name.name_length = strlen(kLibZipSimpleZip);
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800139 ASSERT_EQ(0, FindEntry(handle, zip_name, &zip_entry));
140 extinfo.library_fd_offset = zip_entry.offset;
141 CloseArchive(handle);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700142
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700143 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700144 ASSERT_DL_NOTNULL(handle_);
145
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700146 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
147 ASSERT_DL_NOTNULL(taxicab_number);
148 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700149}
150
151TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700152 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700153
154 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700155 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700156 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700157 extinfo.library_fd_offset = 17;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700158
159 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
160 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700161 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
162
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800163 // Test an address above 2^44, for http://b/18178121 .
164 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700165 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700166 ASSERT_TRUE(handle_ == nullptr);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800167 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
168
169 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
170 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
171 ASSERT_TRUE(handle_ == nullptr);
172 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
173
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700174 extinfo.library_fd_offset = 0;
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700175 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800176 ASSERT_TRUE(handle_ == nullptr);
Elliott Hughesa8971512018-06-27 14:39:06 -0700177 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700178
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -0800179 // Check if dlsym works after unsuccessful dlopen().
180 // Supply non-exiting one to make linker visit every soinfo.
181 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
182 ASSERT_TRUE(sym == nullptr);
183
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700184 close(extinfo.library_fd);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700185}
186
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800187TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700188 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700189 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800190 // This offset will not be used, so it doesn't matter.
191 extinfo.library_fd_offset = 0;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700192
193 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
194 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700195 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 -0700196}
197
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700198TEST(dlext, android_dlopen_ext_force_load_smoke) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700199 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
200 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700201 // 1. Open actual file
202 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
203 ASSERT_DL_NOTNULL(handle);
204 // 2. Open link with force_load flag set
205 android_dlextinfo extinfo;
206 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700207 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700208 ASSERT_DL_NOTNULL(handle2);
209 ASSERT_TRUE(handle != handle2);
210
211 dlclose(handle2);
212 dlclose(handle);
213}
214
215TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700216 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
217 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700218 // Check if soname lookup still returns already loaded library
219 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700220 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700221 ASSERT_DL_NOTNULL(handle);
222
223 android_dlextinfo extinfo;
224 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
225
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700226 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700227 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
228
229 ASSERT_DL_NOTNULL(handle2);
230 ASSERT_TRUE(handle == handle2);
231
232 dlclose(handle2);
233 dlclose(handle);
234}
235
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700236TEST(dlfcn, dlopen_from_zip_absolute_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700237 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700238 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700239
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700240 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700241 ASSERT_TRUE(handle != nullptr) << dlerror();
242
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700243 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
244 ASSERT_DL_NOTNULL(taxicab_number);
245 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700246
247 dlclose(handle);
248}
249
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700250TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700251 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700252 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700253
254 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
255
256 ASSERT_TRUE(handle != nullptr) << dlerror();
257
258 typedef void *(* dlopen_b_fn)();
259 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
260 ASSERT_TRUE(fn != nullptr) << dlerror();
261
262 void *p = fn();
263 ASSERT_TRUE(p != nullptr) << dlerror();
264
265 dlclose(p);
266 dlclose(handle);
267}
268
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700269TEST(dlfcn, dlopen_from_zip_ld_library_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700270 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700271 const std::string lib_path = GetTestlibRoot() + lib_zip_path + "!/libdir";
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700272
273 typedef void (*fn_t)(const char*);
274 fn_t android_update_LD_LIBRARY_PATH =
275 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
276
277 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
278
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700279 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700280 ASSERT_TRUE(handle == nullptr);
281
282 android_update_LD_LIBRARY_PATH(lib_path.c_str());
283
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700284 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700285 ASSERT_TRUE(handle != nullptr) << dlerror();
286
287 int (*fn)(void);
288 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
289 ASSERT_TRUE(fn != nullptr);
290 EXPECT_EQ(4, fn());
291
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800292 uint32_t* taxicab_number =
293 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700294 ASSERT_DL_NOTNULL(taxicab_number);
295 EXPECT_EQ(1729U, *taxicab_number);
296
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700297 dlclose(handle);
298}
299
300
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000301TEST_F(DlExtTest, Reserved) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700302 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000303 ASSERT_TRUE(start != MAP_FAILED);
304 android_dlextinfo extinfo;
305 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
306 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700307 extinfo.reserved_size = kLibSize;
308 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000309 ASSERT_DL_NOTNULL(handle_);
310 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
311 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700312 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000313 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700314 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000315 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800316
317 // Check that after dlclose reserved address space is unmapped (and can be reused)
318 dlclose(handle_);
319 handle_ = nullptr;
320
321 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
322 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000323}
324
325TEST_F(DlExtTest, ReservedTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800326 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000327 ASSERT_TRUE(start != MAP_FAILED);
328 android_dlextinfo extinfo;
329 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
330 extinfo.reserved_addr = start;
331 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700332 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700333 EXPECT_EQ(nullptr, handle_);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000334}
335
336TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700337 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000338 ASSERT_TRUE(start != MAP_FAILED);
339 android_dlextinfo extinfo;
340 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
341 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700342 extinfo.reserved_size = kLibSize;
343 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000344 ASSERT_DL_NOTNULL(handle_);
345 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
346 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700347 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000348 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700349 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000350 EXPECT_EQ(4, f());
351}
352
353TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800354 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000355 ASSERT_TRUE(start != MAP_FAILED);
356 android_dlextinfo extinfo;
357 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
358 extinfo.reserved_addr = start;
359 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700360 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000361 ASSERT_DL_NOTNULL(handle_);
362 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
363 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700364 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
365 (reinterpret_cast<void*>(f) >=
366 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000367 EXPECT_EQ(4, f());
368}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000369
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100370class DlExtRelroSharingTest : public DlExtTest {
371protected:
372 virtual void SetUp() {
373 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700374 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100375 ASSERT_TRUE(start != MAP_FAILED);
376 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
377 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700378 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100379 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000380 }
381
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100382 virtual void TearDown() {
383 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100384 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000385
Yabin Cui294d1e22014-12-07 20:43:37 -0800386 void CreateRelroFile(const char* lib, const char* relro_file) {
Elliott Hughes5cec3772018-01-19 15:45:23 -0800387 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100388 ASSERT_NOERROR(relro_fd);
389
390 pid_t pid = fork();
391 if (pid == 0) {
392 // child process
393 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
394 extinfo_.relro_fd = relro_fd;
395 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700396 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100397 fprintf(stderr, "in child: %s\n", dlerror());
398 exit(1);
399 }
400 exit(0);
401 }
402
403 // continuing in parent
404 ASSERT_NOERROR(close(relro_fd));
405 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800406 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100407
408 // reopen file for reading so it can be used
Elliott Hughes5cec3772018-01-19 15:45:23 -0800409 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100410 ASSERT_NOERROR(relro_fd);
411 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
412 extinfo_.relro_fd = relro_fd;
413 }
414
415 void TryUsingRelro(const char* lib) {
416 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
417 ASSERT_DL_NOTNULL(handle_);
418 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
419 ASSERT_DL_NOTNULL(f);
420 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700421
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800422 uint32_t* taxicab_number =
423 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700424 ASSERT_DL_NOTNULL(taxicab_number);
425 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100426 }
427
Zhenhua WANG81aad002017-04-25 11:07:19 +0800428 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
429 size_t* pss_out);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100430
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100431 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100432};
433
434TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800435 TemporaryFile tf; // Use tf to get an unique filename.
436 ASSERT_NOERROR(close(tf.fd));
437
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700438 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
439 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
Yabin Cui294d1e22014-12-07 20:43:37 -0800440
441 // Use destructor of tf to close and unlink the file.
442 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100443}
444
445TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800446 TemporaryFile tf; // // Use tf to get an unique filename.
447 ASSERT_NOERROR(close(tf.fd));
448
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700449 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.filename));
450 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro));
Yabin Cui294d1e22014-12-07 20:43:37 -0800451
452 // Use destructor of tf to close and unlink the file.
453 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100454}
455
456TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700457 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000458}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100459
460TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Dan Albert69fb9f32014-09-03 11:30:21 -0700461 if (geteuid() != 0) {
462 GTEST_LOG_(INFO) << "This test must be run as root.\n";
463 return;
464 }
465
Yabin Cui294d1e22014-12-07 20:43:37 -0800466 TemporaryFile tf; // Use tf to get an unique filename.
467 ASSERT_NOERROR(close(tf.fd));
468
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700469 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
Yabin Cui294d1e22014-12-07 20:43:37 -0800470
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100471 int pipefd[2];
472 ASSERT_NOERROR(pipe(pipefd));
473
474 size_t without_sharing, with_sharing;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800475 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, false, &without_sharing));
476 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, true, &with_sharing));
477 ASSERT_LT(with_sharing, without_sharing);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100478
Zhenhua WANG81aad002017-04-25 11:07:19 +0800479 // We expect the sharing to save at least 50% of the library's total PSS.
480 // In practice it saves 80%+ for this library in the test.
481 size_t pss_saved = without_sharing - with_sharing;
482 size_t expected_min_saved = without_sharing / 2;
483
484 EXPECT_LT(expected_min_saved, pss_saved);
Yabin Cui294d1e22014-12-07 20:43:37 -0800485
486 // Use destructor of tf to close and unlink the file.
487 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100488}
489
Zhenhua WANG81aad002017-04-25 11:07:19 +0800490void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
491 size_t* total_pss) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100492 pm_kernel_t* kernel;
493 ASSERT_EQ(0, pm_kernel_create(&kernel));
494
495 pm_process_t* process;
496 ASSERT_EQ(0, pm_process_create(kernel, pid, &process));
497
498 pm_map_t** maps;
499 size_t num_maps;
500 ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
501
Zhenhua WANG81aad002017-04-25 11:07:19 +0800502 // Calculate total PSS of the library.
503 *total_pss = 0;
504 bool saw_relro_file = false;
505 for (size_t i = 0; i < num_maps; ++i) {
506 if (android::base::EndsWith(maps[i]->name, lib) || strcmp(maps[i]->name, relro_file) == 0) {
507 if (strcmp(maps[i]->name, relro_file) == 0) saw_relro_file = true;
508
509 pm_memusage_t usage;
510 ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
511 *total_pss += usage.pss;
512 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100513 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100514
515 free(maps);
516 pm_process_destroy(process);
517 pm_kernel_destroy(kernel);
Zhenhua WANG81aad002017-04-25 11:07:19 +0800518
519 if (shared_relro) ASSERT_TRUE(saw_relro_file);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100520}
521
Zhenhua WANG81aad002017-04-25 11:07:19 +0800522void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
523 bool share_relro, size_t* pss_out) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100524 const int CHILDREN = 20;
525
526 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800527 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100528 int childpipe[CHILDREN];
529 for (int i=0; i<CHILDREN; ++i) {
530 char read_buf;
531 int child_done_pipe[2], parent_done_pipe[2];
532 ASSERT_NOERROR(pipe(child_done_pipe));
533 ASSERT_NOERROR(pipe(parent_done_pipe));
534
535 pid_t child = fork();
536 if (child == 0) {
537 // close the 'wrong' ends of the pipes in the child
538 close(child_done_pipe[0]);
539 close(parent_done_pipe[1]);
540
541 // open the library
542 void* handle;
543 if (share_relro) {
544 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
545 } else {
546 handle = dlopen(lib, RTLD_NOW);
547 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700548 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100549 fprintf(stderr, "in child: %s\n", dlerror());
550 exit(1);
551 }
552
553 // close write end of child_done_pipe to signal the parent that we're done.
554 close(child_done_pipe[1]);
555
556 // wait for the parent to close parent_done_pipe, then exit
557 read(parent_done_pipe[0], &read_buf, 1);
558 exit(0);
559 }
560
561 ASSERT_NOERROR(child);
562
563 // close the 'wrong' ends of the pipes in the parent
564 close(child_done_pipe[1]);
565 close(parent_done_pipe[0]);
566
567 // wait for the child to be done
568 read(child_done_pipe[0], &read_buf, 1);
569 close(child_done_pipe[0]);
570
571 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800572 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100573 childpipe[i] = parent_done_pipe[1];
574 }
575
Zhenhua WANG81aad002017-04-25 11:07:19 +0800576 // Sum the PSS of tested library of all the children
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100577 size_t total_pss = 0;
578 for (int i=0; i<CHILDREN; ++i) {
579 size_t child_pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800580 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100581 total_pss += child_pss;
582 }
583 *pss_out = total_pss;
584
585 // Close pipes and wait for children to exit
586 for (int i=0; i<CHILDREN; ++i) {
587 ASSERT_NOERROR(close(childpipe[i]));
588 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800589 for (int i = 0; i < CHILDREN; ++i) {
590 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100591 }
592}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700593
594// Testing namespaces
595static const char* g_public_lib = "libnstest_public.so";
596
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800597// These are libs shared with default namespace
598static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
599
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700600TEST(dlext, ns_smoke) {
601 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800602 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700603
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800604 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
605 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
606 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
607 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700608
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700609 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800610 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700611 ASSERT_TRUE(handle_public != nullptr) << dlerror();
612
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800613 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700614
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800615 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700616 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800617 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800618 ASSERT_TRUE(handle_public == nullptr);
619 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
620 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
621
622 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700623
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800624 // create "public namespace", share limited set of public libraries with
625
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800626 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800627 android_create_namespace("private",
628 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700629 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800630 ANDROID_NAMESPACE_TYPE_REGULAR,
631 nullptr,
632 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700633 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800634 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700635
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800636 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800637 android_create_namespace("private_isolated",
638 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700639 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800640 ANDROID_NAMESPACE_TYPE_ISOLATED,
641 nullptr,
642 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700643 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800644 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700645
646 // This should not have affect search path for default namespace:
647 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
648 void* handle = dlopen(g_public_lib, RTLD_NOW);
649 ASSERT_TRUE(handle != nullptr) << dlerror();
650 dlclose(handle);
651
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700652 // dlopen for a public library using an absolute path should work
653 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700654 android_dlextinfo extinfo;
655 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700656 extinfo.library_namespace = ns2;
657 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
658 ASSERT_TRUE(handle != nullptr) << dlerror();
659 ASSERT_TRUE(handle == handle_public);
660
661 dlclose(handle);
662
663 // 1.1 even if it wasn't loaded before
664 dlclose(handle_public);
665
666 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
667 ASSERT_TRUE(handle_public == nullptr);
668 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
669 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
670
671 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
672 ASSERT_TRUE(handle != nullptr) << dlerror();
673
674 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
675 ASSERT_TRUE(handle == handle_public);
676
677 dlclose(handle);
678
679 // 2. And for regular namespaces (make sure it does not load second copy of the library)
680 extinfo.library_namespace = ns1;
681 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
682 ASSERT_TRUE(handle != nullptr) << dlerror();
683 ASSERT_TRUE(handle == handle_public);
684
685 dlclose(handle);
686
687 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
688 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
689 dlclose(handle_public);
690
691 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
692 ASSERT_TRUE(handle_public == nullptr);
693 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
694 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
695
696 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
697 ASSERT_TRUE(handle != nullptr) << dlerror();
698
699 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
700
701 ASSERT_TRUE(handle != handle_public);
702
703 dlclose(handle);
704
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700705 extinfo.library_namespace = ns1;
706
707 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
708 ASSERT_TRUE(handle1 != nullptr) << dlerror();
709
710 extinfo.library_namespace = ns2;
711 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
712 ASSERT_TRUE(handle2 != nullptr) << dlerror();
713
714 ASSERT_TRUE(handle1 != handle2);
715
716 typedef const char* (*fn_t)();
717
718 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
719 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
720 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
721 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
722
723 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
724 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
725
726 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
727
728 fn_t ns_get_private_extern_string1 =
729 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
730 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
731 fn_t ns_get_private_extern_string2 =
732 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
733 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
734
735 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
736 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
737
738 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
739
740 fn_t ns_get_public_extern_string1 =
741 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
742 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
743 fn_t ns_get_public_extern_string2 =
744 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
745 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
746
747 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
748 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
749
750 // and now check that dlopen() does the right thing in terms of preserving namespace
751 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
752 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
753 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
754 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
755
756 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
757 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
758
759 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
760
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800761 // Check that symbols from non-shared libraries a shared library depends on are not visible
762 // from original namespace.
763
764 fn_t ns_get_internal_extern_string =
765 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
766 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
767 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
768 "ns_get_internal_extern_string() expected to return null but returns \"" <<
769 ns_get_internal_extern_string() << "\"";
770
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700771 dlclose(handle1);
772
773 // Check if handle2 is still alive (and well)
774 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
775 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
776 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
777 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
778
779 dlclose(handle2);
780}
781
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700782TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700783 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700784
785 int tmpfd = TEMP_FAILURE_RETRY(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700786 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700787
788 // Ignore kernels without O_TMPFILE flag support
789 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
790 return;
791 }
792
793 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
794
795 android_namespace_t* ns =
796 android_create_namespace("testing-o_tmpfile",
797 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700798 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700799 ANDROID_NAMESPACE_TYPE_ISOLATED,
800 nullptr,
801 nullptr);
802
803 ASSERT_DL_NOTNULL(ns);
804
805 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
806
807 std::string content;
808 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
809 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
810
811 android_dlextinfo extinfo;
812 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
813 extinfo.library_fd = tmpfd;
814 extinfo.library_namespace = ns;
815
816 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
817
818 ASSERT_DL_NOTNULL(handle);
819
820 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
821 ASSERT_DL_NOTNULL(taxicab_number);
822 EXPECT_EQ(1729U, *taxicab_number);
823 dlclose(handle);
824}
825
826TEST(dlext, dlopen_ext_use_memfd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700827 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700828
829 // create memfd
830 int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
831 if (memfd == -1 && errno == ENOSYS) {
832 return;
833 }
834
835 ASSERT_TRUE(memfd != -1) << strerror(errno);
836
837 // Check st.f_type is TMPFS_MAGIC for memfd
838 struct statfs st;
839 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
840 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
841
842 android_namespace_t* ns =
843 android_create_namespace("testing-memfd",
844 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700845 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700846 ANDROID_NAMESPACE_TYPE_ISOLATED,
847 nullptr,
848 nullptr);
849
850 ASSERT_DL_NOTNULL(ns);
851
852 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
853
854 // read file into memfd backed one.
855 std::string content;
856 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
857 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
858
859 android_dlextinfo extinfo;
860 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
861 extinfo.library_fd = memfd;
862 extinfo.library_namespace = ns;
863
864 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
865
866 ASSERT_DL_NOTNULL(handle);
867
868 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
869 ASSERT_DL_NOTNULL(taxicab_number);
870 EXPECT_EQ(1729U, *taxicab_number);
871 dlclose(handle);
872}
873
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800874TEST(dlext, ns_symbol_visibilty_one_namespace) {
875 static const char* root_lib = "libnstest_root.so";
876 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
877
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700878 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
879 GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800880
881 android_namespace_t* ns =
882 android_create_namespace("one",
883 nullptr,
884 ns_search_path.c_str(),
885 ANDROID_NAMESPACE_TYPE_ISOLATED,
886 nullptr,
887 nullptr);
888
889 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
890
891 android_dlextinfo extinfo;
892 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
893 extinfo.library_namespace = ns;
894
895 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
896 ASSERT_TRUE(handle != nullptr) << dlerror();
897
898 typedef const char* (*fn_t)();
899
900 // Check that relocation worked correctly
901 fn_t ns_get_internal_extern_string =
902 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
903 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
904 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
905
906 fn_t internal_extern_string_fn =
907 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
908 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
909 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
910}
911
912TEST(dlext, ns_symbol_visibilty_between_namespaces) {
913 static const char* root_lib = "libnstest_root.so";
914 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
915
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700916 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
917 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800918
919 android_namespace_t* ns_public =
920 android_create_namespace("public",
921 nullptr,
922 public_ns_search_path.c_str(),
923 ANDROID_NAMESPACE_TYPE_ISOLATED,
924 nullptr,
925 nullptr);
926
927 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
928
929 android_namespace_t* ns_private =
930 android_create_namespace("private",
931 nullptr,
932 private_ns_search_path.c_str(),
933 ANDROID_NAMESPACE_TYPE_ISOLATED,
934 nullptr,
935 nullptr);
936
937 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
938 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
939
940 android_dlextinfo extinfo;
941 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
942 extinfo.library_namespace = ns_private;
943
944 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
945 ASSERT_TRUE(handle != nullptr) << dlerror();
946
947 typedef const char* (*fn_t)();
948
949 // Check that relocation worked correctly
950 fn_t ns_get_internal_extern_string =
951 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
952 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
953 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
954 "ns_get_internal_extern_string() expected to return null but returns \"" <<
955 ns_get_internal_extern_string() << "\"";
956
957 fn_t internal_extern_string_fn =
958 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
959 ASSERT_TRUE(internal_extern_string_fn == nullptr);
960 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
961}
962
963TEST(dlext, ns_unload_between_namespaces) {
964 static const char* root_lib = "libnstest_root.so";
965 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
966
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700967 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
968 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800969
970 android_namespace_t* ns_public =
971 android_create_namespace("public",
972 nullptr,
973 public_ns_search_path.c_str(),
974 ANDROID_NAMESPACE_TYPE_ISOLATED,
975 nullptr,
976 nullptr);
977
978 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
979
980 android_namespace_t* ns_private =
981 android_create_namespace("private",
982 nullptr,
983 private_ns_search_path.c_str(),
984 ANDROID_NAMESPACE_TYPE_ISOLATED,
985 nullptr,
986 nullptr);
987
988 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
989 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
990
991 android_dlextinfo extinfo;
992 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
993 extinfo.library_namespace = ns_private;
994
995 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
996 ASSERT_TRUE(handle != nullptr) << dlerror();
997
998 dlclose(handle);
999 // Check that root_lib was unloaded
1000 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1001 ASSERT_TRUE(handle == nullptr);
1002 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1003 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1004
1005 // Check that shared library was unloaded in public ns
1006 extinfo.library_namespace = ns_public;
1007 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1008 ASSERT_TRUE(handle == nullptr);
1009 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1010 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1011}
1012
dimitry965d06d2017-11-28 16:03:07 +01001013TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1014 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1015
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001016 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1017 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001018
1019 android_namespace_t* ns_public =
1020 android_create_namespace("public",
1021 nullptr,
1022 public_ns_search_path.c_str(),
1023 ANDROID_NAMESPACE_TYPE_ISOLATED,
1024 nullptr,
1025 nullptr);
1026
1027 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1028
1029 android_namespace_t* ns_private =
1030 android_create_namespace("private",
1031 nullptr,
1032 private_ns_search_path.c_str(),
1033 ANDROID_NAMESPACE_TYPE_ISOLATED,
1034 nullptr,
1035 nullptr);
1036
1037 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1038 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1039
1040 android_dlextinfo extinfo;
1041 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1042 extinfo.library_namespace = ns_private;
1043
1044 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1045 RTLD_NOW,
1046 &extinfo);
1047 ASSERT_TRUE(handle == nullptr);
1048 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1049 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1050 dlerror());
1051}
1052
1053TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1054 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1055
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001056 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1057 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001058
1059 android_namespace_t* ns_public =
1060 android_create_namespace("public",
1061 nullptr,
1062 public_ns_search_path.c_str(),
1063 ANDROID_NAMESPACE_TYPE_ISOLATED,
1064 nullptr,
1065 nullptr);
1066
1067 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1068
1069 android_namespace_t* ns_private =
1070 android_create_namespace("private",
1071 nullptr,
1072 private_ns_search_path.c_str(),
1073 ANDROID_NAMESPACE_TYPE_ISOLATED,
1074 nullptr,
1075 nullptr);
1076
1077 ASSERT_TRUE(android_link_namespaces(ns_private,
1078 ns_public,
1079 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1080 ) << dlerror();
1081 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1082
1083 android_dlextinfo extinfo;
1084 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1085 extinfo.library_namespace = ns_private;
1086
1087 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1088 ASSERT_TRUE(handle == nullptr);
1089 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1090 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1091 dlerror());
1092}
1093
Jiyong Park37b91af2017-05-05 22:07:05 +09001094TEST(dlext, ns_greylist_enabled) {
Dimitry Ivanov18623142017-02-21 13:41:08 -08001095 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1096
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001097 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov18623142017-02-21 13:41:08 -08001098
1099 android_namespace_t* ns =
1100 android_create_namespace("namespace",
1101 nullptr,
1102 ns_search_path.c_str(),
Jiyong Park37b91af2017-05-05 22:07:05 +09001103 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
Dimitry Ivanov18623142017-02-21 13:41:08 -08001104 nullptr,
1105 nullptr);
1106
1107 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1108
1109 android_dlextinfo extinfo;
1110 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1111 extinfo.library_namespace = ns;
1112
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001113 // An app targeting M can open libnativehelper.so because it's on the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001114 android_set_application_target_sdk_version(__ANDROID_API_M__);
1115 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1116 ASSERT_TRUE(handle != nullptr) << dlerror();
1117
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001118 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1119 void* dlsym_ptr = dlsym(handle, "dlsym");
1120 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1121 ASSERT_EQ(&dlsym, dlsym_ptr);
1122
Dimitry Ivanov18623142017-02-21 13:41:08 -08001123 dlclose(handle);
1124
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001125 // An app targeting N no longer has the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001126 android_set_application_target_sdk_version(__ANDROID_API_N__);
1127 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1128 ASSERT_TRUE(handle == nullptr);
1129 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1130}
1131
Jiyong Park37b91af2017-05-05 22:07:05 +09001132TEST(dlext, ns_greylist_disabled_by_default) {
1133 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1134
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001135 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Jiyong Park37b91af2017-05-05 22:07:05 +09001136
1137 android_namespace_t* ns =
1138 android_create_namespace("namespace",
1139 nullptr,
1140 ns_search_path.c_str(),
1141 ANDROID_NAMESPACE_TYPE_ISOLATED,
1142 nullptr,
1143 nullptr);
1144
1145 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1146
1147 android_dlextinfo extinfo;
1148 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1149 extinfo.library_namespace = ns;
1150
1151 android_set_application_target_sdk_version(__ANDROID_API_M__);
1152 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1153 ASSERT_TRUE(handle == nullptr);
1154 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1155}
1156
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001157TEST(dlext, ns_cyclic_namespaces) {
1158 // Test that ns1->ns2->ns1 link does not break the loader
1159 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1160 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1161
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001162 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001163
1164 android_namespace_t* ns1 =
1165 android_create_namespace("ns1",
1166 nullptr,
1167 ns_search_path.c_str(),
1168 ANDROID_NAMESPACE_TYPE_ISOLATED,
1169 nullptr,
1170 nullptr);
1171
1172 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1173
1174 android_namespace_t* ns2 =
1175 android_create_namespace("ns1",
1176 nullptr,
1177 ns_search_path.c_str(),
1178 ANDROID_NAMESPACE_TYPE_ISOLATED,
1179 nullptr,
1180 nullptr);
1181
1182 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1183
1184 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1185 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1186
1187 android_dlextinfo extinfo;
1188 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1189 extinfo.library_namespace = ns1;
1190
1191 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1192 ASSERT_TRUE(handle == nullptr);
1193 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1194}
1195
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001196TEST(dlext, ns_isolated) {
1197 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001198 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001199
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001200 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001201 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001202 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1203
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001204 android_set_application_target_sdk_version(42U); // something > 23
1205
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001206 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001207
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001208 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001209 android_create_namespace("private",
1210 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001211 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001212 ANDROID_NAMESPACE_TYPE_REGULAR,
1213 nullptr,
1214 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001215 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001216 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001217
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001218 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001219 android_create_namespace("private_isolated1",
1220 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001221 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001222 ANDROID_NAMESPACE_TYPE_ISOLATED,
1223 nullptr,
1224 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001225 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001226 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001227
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001228 android_namespace_t* ns_isolated2 =
1229 android_create_namespace("private_isolated2",
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001230 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001231 nullptr,
1232 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001233 GetTestlibRoot().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001234 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001235 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001236 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001237
1238 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1239 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1240
1241 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001242 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001243
1244 // Load lib_private_external_path to default namespace
1245 // (it should remain invisible for the isolated namespaces after this)
1246 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1247 ASSERT_TRUE(handle != nullptr) << dlerror();
1248
1249 android_dlextinfo extinfo;
1250 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1251 extinfo.library_namespace = ns_not_isolated;
1252
1253 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1254 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1255
1256 extinfo.library_namespace = ns_isolated;
1257
1258 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1259 ASSERT_TRUE(handle2 == nullptr);
1260 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1261
1262 // Check dlopen by absolute path
1263 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1264 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001265 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001266 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001267 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001268
1269 extinfo.library_namespace = ns_isolated2;
1270
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001271 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001272 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001273 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1274 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001275
1276 // Check dlopen by absolute path
1277 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001278 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1279 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001280
1281 typedef const char* (*fn_t)();
1282 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1283 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1284
1285 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1286
1287 fn_t ns_get_private_extern_string =
1288 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1289 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1290
1291 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1292
1293 fn_t ns_get_public_extern_string =
1294 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1295 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1296
1297 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1298
1299 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1300 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1301
1302 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1303
1304 dlclose(handle1);
1305}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001306
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001307TEST(dlext, ns_shared) {
1308 static const char* root_lib = "libnstest_root_not_isolated.so";
1309 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001310
1311 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001312
Jiyong Park917d34a2017-08-31 14:07:13 +09001313 // create a parent namespace to use instead of the default namespace. This is
1314 // to make this test be independent from the configuration of the default
1315 // namespace.
1316 android_namespace_t* ns_parent =
1317 android_create_namespace("parent",
1318 nullptr,
1319 nullptr,
1320 ANDROID_NAMESPACE_TYPE_REGULAR,
1321 nullptr,
1322 nullptr);
1323 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1324 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1325
1326 android_dlextinfo extinfo;
1327 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1328 extinfo.library_namespace = ns_parent;
1329
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001330 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Jiyong Park917d34a2017-08-31 14:07:13 +09001331 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001332 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1333
1334 android_set_application_target_sdk_version(42U); // something > 23
1335
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001336 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001337
Jiyong Park917d34a2017-08-31 14:07:13 +09001338 // preload this library to the parent namespace to check if it
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001339 // is shared later on.
1340 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001341 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001342 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1343
Jiyong Park917d34a2017-08-31 14:07:13 +09001344 // create two child namespaces of 'ns_parent'. One with regular, the other
1345 // with isolated & shared.
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001346 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001347 android_create_namespace("private",
1348 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001349 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001350 ANDROID_NAMESPACE_TYPE_REGULAR,
1351 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001352 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001353 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001354 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1355 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001356
1357 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001358 android_create_namespace("private_isolated_shared",
1359 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001360 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001361 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001362 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001363 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001364 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001365 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1366 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001367
Jiyong Park917d34a2017-08-31 14:07:13 +09001368 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001369 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1370
1371 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001372 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001373
Jiyong Park917d34a2017-08-31 14:07:13 +09001374 // Load lib_private_external_path to the parent namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001375 // (it should remain invisible for the isolated namespaces after this)
Jiyong Park917d34a2017-08-31 14:07:13 +09001376 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001377 ASSERT_TRUE(handle != nullptr) << dlerror();
1378
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001379 extinfo.library_namespace = ns_not_isolated;
1380
1381 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1382 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1383
1384 extinfo.library_namespace = ns_isolated_shared;
1385
1386 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1387 ASSERT_TRUE(handle2 == nullptr);
1388 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1389
1390 // Check dlopen by absolute path
1391 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1392 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001393 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001394 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001395 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001396
1397 // load libnstest_root.so to shared namespace in order to check that everything is different
1398 // except shared libnstest_dlopened.so
1399
1400 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1401
1402 typedef const char* (*fn_t)();
1403 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1404 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1405 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1406 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1407
1408 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1409 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1410 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1411
1412 fn_t ns_get_private_extern_string =
1413 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1414 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1415 fn_t ns_get_private_extern_string_shared =
1416 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1417 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1418
1419 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1420 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1421 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1422
1423 fn_t ns_get_public_extern_string =
1424 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1425 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1426 fn_t ns_get_public_extern_string_shared =
1427 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1428 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1429
1430 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1431 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1432 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1433
1434 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1435 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1436 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1437 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1438 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1439 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1440
1441 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1442 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1443 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1444 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1445 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1446
1447 dlclose(handle1);
1448 dlclose(handle2);
1449}
1450
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001451TEST(dlext, ns_shared_links_and_paths) {
1452 // Create parent namespace (isolated, not shared)
1453 android_namespace_t* ns_isolated =
1454 android_create_namespace("private_isolated",
1455 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001456 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001457 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001458 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001459 nullptr);
1460 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1461 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1462
1463 // Create shared namespace with ns_isolated parent
1464 android_namespace_t* ns_shared =
1465 android_create_namespace("private_shared",
1466 nullptr,
1467 nullptr,
1468 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1469 nullptr,
1470 ns_isolated);
1471 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1472
1473 // 1. Load a library in ns_shared to check that it has inherited
1474 // search path and the link to the default namespace.
1475 android_dlextinfo extinfo;
1476 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1477 extinfo.library_namespace = ns_shared;
1478
1479 {
1480 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1481 ASSERT_TRUE(handle != nullptr) << dlerror();
1482 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1483 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1484 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1485
1486 dlclose(handle);
1487 }
1488 // 2. Load another test library by absolute path to check that
1489 // it has inherited permitted_when_isolated_path
1490 {
1491 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001492 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001493 RTLD_NOW,
1494 &extinfo);
1495
1496 ASSERT_TRUE(handle != nullptr) << dlerror();
1497 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1498 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1499 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1500
1501 dlclose(handle);
1502 }
1503
1504 // 3. Check that it is still isolated.
1505 {
1506 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001507 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001508 RTLD_NOW,
1509 &extinfo);
1510
1511 ASSERT_TRUE(handle == nullptr);
1512 }
1513}
1514
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001515TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001516 android_set_application_target_sdk_version(42U); // something > 23
1517
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001518 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001519
1520 // preload this library to the default namespace to check if it
1521 // is shared later on.
1522 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001523 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001524 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1525
1526 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001527 android_create_namespace("private_isolated_shared",
1528 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001529 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001530 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001531 nullptr,
1532 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001533 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001534 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001535
1536 // Check if "libnstest_dlopened.so" is loaded (and the same)
1537 android_dlextinfo extinfo;
1538 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1539 extinfo.library_namespace = ns_isolated_shared;
1540
1541 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1542 ASSERT_TRUE(handle != nullptr) << dlerror();
1543 ASSERT_TRUE(handle == handle_dlopened);
1544 dlclose(handle);
1545 dlclose(handle_dlopened);
1546
1547 // And now check that the library cannot be found by soname (and is no longer loaded)
1548 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1549 ASSERT_TRUE(handle == nullptr)
1550 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1551
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001552 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001553 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1554 ASSERT_TRUE(handle == nullptr)
1555 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1556
1557 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1558 ASSERT_TRUE(handle == nullptr)
1559 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1560
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001561 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001562 RTLD_NOW | RTLD_NOLOAD);
1563 ASSERT_TRUE(handle == nullptr)
1564 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1565
1566 // Now lets see if the soinfo area gets reused in the wrong way:
1567 // load a library to default namespace.
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001568 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001569 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1570 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1571
1572 // try to find it in shared namespace
1573 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1574 ASSERT_TRUE(handle == nullptr)
1575 << "Error: " << g_public_lib << " is accessible in shared namespace";
1576}
1577
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001578TEST(dlext, ns_isolated_rtld_global) {
1579 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001580 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001581
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001582 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001583
1584 android_namespace_t* ns1 =
1585 android_create_namespace("isolated1",
1586 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001587 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001588 ANDROID_NAMESPACE_TYPE_ISOLATED,
1589 lib_public_path.c_str(),
1590 nullptr);
1591 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001592 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001593
1594 android_namespace_t* ns2 =
1595 android_create_namespace("isolated2",
1596 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001597 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001598 ANDROID_NAMESPACE_TYPE_ISOLATED,
1599 lib_public_path.c_str(),
1600 nullptr);
1601 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001602 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001603
1604 android_dlextinfo extinfo;
1605 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1606 extinfo.library_namespace = ns1;
1607
1608 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1609 RTLD_GLOBAL,
1610 &extinfo);
1611
1612 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1613
1614 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001615 android_create_namespace("isolated1_child",
1616 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001617 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001618 ANDROID_NAMESPACE_TYPE_ISOLATED,
1619 nullptr,
1620 ns1);
1621
1622 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1623 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001624
1625 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1626 // attempt to use ns2 should result in dlerror()
1627
1628 // Check ns1_child first.
1629 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1630 extinfo.library_namespace = ns1_child;
1631
1632 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1633 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1634
1635 // now ns1
1636 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1637 extinfo.library_namespace = ns1;
1638
1639 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1640 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1641
1642 // and ns2 should fail
1643 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1644 extinfo.library_namespace = ns2;
1645
1646 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1647 ASSERT_TRUE(handle1 == nullptr);
1648 ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
1649}
1650
dimitry8db36a52017-10-23 15:10:10 +02001651TEST(dlext, ns_inaccessible_error_message) {
1652 // We set up 2 namespaces (a and b) and link a->b with a shared library
1653 // libtestshared.so. Then try to dlopen different library with the same
1654 // name from in namespace a. Note that library should not be accessible
1655 // in either namespace but since it's soname is in the list of shared libs
1656 // the linker will attempt to find it in linked namespace.
1657 //
1658 // Check the error message and make sure it mentions correct namespace name.
1659 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1660
1661 android_namespace_t* ns_a =
1662 android_create_namespace("ns_a",
1663 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001664 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001665 ANDROID_NAMESPACE_TYPE_ISOLATED,
1666 nullptr,
1667 nullptr);
1668 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1669 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1670
1671 android_namespace_t* ns_b =
1672 android_create_namespace("ns_b",
1673 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001674 GetTestlibRoot().c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001675 ANDROID_NAMESPACE_TYPE_ISOLATED,
1676 nullptr,
1677 nullptr);
1678 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1679 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1680
1681 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1682
1683 android_dlextinfo extinfo;
1684 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1685 extinfo.library_namespace = ns_a;
1686
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001687 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
dimitry8db36a52017-10-23 15:10:10 +02001688
1689 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1690 ASSERT_TRUE(handle == nullptr);
1691 std::string expected_dlerror =
1692 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1693 " is not accessible for the namespace \"ns_a\"",
1694 library_path.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001695 android::base::GetExecutablePath().c_str());
dimitry8db36a52017-10-23 15:10:10 +02001696 ASSERT_EQ(expected_dlerror, dlerror());
1697}
1698
dimitry321476a2018-01-29 15:32:37 +01001699extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1700 android_namespace_t* namespace_to);
1701
Logan Chien9ee45912018-01-18 12:05:09 +08001702TEST(dlext, ns_link_namespaces_invalid_arguments) {
1703 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1704
1705 android_namespace_t* ns =
1706 android_create_namespace("private",
1707 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001708 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001709 ANDROID_NAMESPACE_TYPE_REGULAR,
1710 nullptr,
1711 nullptr);
1712 ASSERT_TRUE(ns != nullptr) << dlerror();
1713
1714 // Test android_link_namespaces()
1715 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1716 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1717 dlerror());
1718
1719 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1720 ASSERT_STREQ("android_link_namespaces failed: "
1721 "error linking namespaces \"private\"->\"(default)\": "
1722 "the list of shared libraries is empty.", dlerror());
1723
1724 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1725 ASSERT_STREQ("android_link_namespaces failed: "
1726 "error linking namespaces \"private\"->\"(default)\": "
1727 "the list of shared libraries is empty.", dlerror());
1728
dimitry321476a2018-01-29 15:32:37 +01001729 // Test __loader_android_link_namespaces_all_libs()
1730 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001731 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1732 "error linking namespaces: namespace_from is null.", dlerror());
1733
dimitry321476a2018-01-29 15:32:37 +01001734 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
Logan Chien9ee45912018-01-18 12:05:09 +08001735 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1736 "error linking namespaces: namespace_from is null.", dlerror());
1737
dimitry321476a2018-01-29 15:32:37 +01001738 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001739 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1740 "error linking namespaces: namespace_to is null.", dlerror());
1741}
1742
1743TEST(dlext, ns_allow_all_shared_libs) {
1744 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1745
1746 android_namespace_t* ns_a =
1747 android_create_namespace("ns_a",
1748 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001749 (GetTestlibRoot() + "/ns_a").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001750 ANDROID_NAMESPACE_TYPE_ISOLATED,
1751 nullptr,
1752 nullptr);
1753 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1754 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1755
1756 android_namespace_t* ns_b =
1757 android_create_namespace("ns_b",
1758 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001759 (GetTestlibRoot() + "/ns_b").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001760 ANDROID_NAMESPACE_TYPE_ISOLATED,
1761 nullptr,
1762 nullptr);
1763 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1764 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1765
1766 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
dimitry321476a2018-01-29 15:32:37 +01001767 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
Logan Chien9ee45912018-01-18 12:05:09 +08001768
1769 // Load libs with android_dlopen_ext() from namespace b
1770 android_dlextinfo extinfo;
1771 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1772 extinfo.library_namespace = ns_b;
1773
1774 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1775 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1776
1777 void* ns_b_handle1_internal =
1778 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1779 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1780
1781 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1782 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1783
1784 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1785 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1786
1787 // Load libs with android_dlopen_ext() from namespace a
1788 extinfo.library_namespace = ns_a;
1789
1790 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1791 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1792
1793 void* ns_a_handle1_internal =
1794 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1795 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1796
1797 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1798 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1799
1800 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1801 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1802
1803 // Compare the dlopen handle
1804 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1805 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1806 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1807
1808 // Close libs
1809 dlclose(ns_b_handle1);
1810 dlclose(ns_b_handle2);
1811 dlclose(ns_b_handle3);
1812
1813 dlclose(ns_a_handle1);
1814 dlclose(ns_a_handle1_internal);
1815 dlclose(ns_a_handle2);
1816 dlclose(ns_a_handle3);
1817}
1818
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001819TEST(dlext, ns_anonymous) {
1820 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001821 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001822
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001823 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001824 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1825
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001826 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1827
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001828 ASSERT_TRUE(
1829 android_init_anonymous_namespace(shared_libs.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001830 (GetTestlibRoot() + "/private_namespace_libs").c_str())
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001831 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001832
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001833 android_namespace_t* ns =
1834 android_create_namespace("private",
1835 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001836 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001837 ANDROID_NAMESPACE_TYPE_REGULAR,
1838 nullptr,
1839 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001840
1841 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001842 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001843
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001844 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001845
1846 android_dlextinfo extinfo;
1847 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1848 extinfo.library_namespace = ns;
1849
1850 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1851 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1852 ASSERT_TRUE(handle != nullptr) << dlerror();
1853
1854 uintptr_t ns_get_dlopened_string_addr =
1855 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1856 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1857 typedef const char* (*fn_t)();
1858 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1859
1860 std::vector<map_record> maps;
1861 Maps::parse_maps(&maps);
1862
1863 uintptr_t addr_start = 0;
1864 uintptr_t addr_end = 0;
dimitry8eaf28d2017-10-11 10:04:14 +02001865 bool has_executable_segment = false;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001866 std::vector<map_record> maps_to_copy;
1867
1868 for (const auto& rec : maps) {
1869 if (rec.pathname == private_library_absolute_path) {
1870 if (addr_start == 0) {
1871 addr_start = rec.addr_start;
1872 }
1873 addr_end = rec.addr_end;
dimitry8eaf28d2017-10-11 10:04:14 +02001874 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001875
1876 maps_to_copy.push_back(rec);
1877 }
1878 }
1879
1880 // some sanity checks..
1881 ASSERT_TRUE(addr_start > 0);
1882 ASSERT_TRUE(addr_end > 0);
dimitry3b0a5b72018-06-06 11:11:25 +02001883 ASSERT_TRUE(maps_to_copy.size() > 0);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001884 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
1885 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
1886
dimitry8eaf28d2017-10-11 10:04:14 +02001887 if (!has_executable_segment) {
1888 // For some natively bridged environments this code might be missing
1889 // the executable flag. This is because the guest code is not supposed
1890 // to be executed directly and making it non-executable is more secure.
1891 // If this is the case we assume that the first segment is the one that
1892 // has this flag.
1893 ASSERT_TRUE((maps_to_copy[0].perms & PROT_WRITE) == 0);
1894 maps_to_copy[0].perms |= PROT_EXEC;
1895 }
1896
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001897 // copy
1898 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
1899 PROT_NONE, MAP_ANON | MAP_PRIVATE,
1900 -1, 0));
1901 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
1902
1903 for (const auto& rec : maps_to_copy) {
1904 uintptr_t offset = rec.addr_start - addr_start;
1905 size_t size = rec.addr_end - rec.addr_start;
1906 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
1907 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
1908 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
1909 ASSERT_TRUE(map != MAP_FAILED);
1910 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
1911 mprotect(map, size, rec.perms);
1912 }
1913
1914 // call the function copy
1915 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
1916 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
1917 ASSERT_STREQ("This string is from private namespace (dlopened library)",
1918 ns_get_dlopened_string_anon());
1919
1920 // They should belong to different namespaces (private and anonymous)
1921 ASSERT_STREQ("This string is from private namespace (dlopened library)",
1922 ns_get_dlopened_string_private());
1923
1924 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
1925}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07001926
1927TEST(dlext, dlopen_handle_value_platform) {
1928 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
1929 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
1930 << "dlopen should return odd value for the handle";
1931 dlclose(handle);
1932}
1933
1934TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08001935 android_set_application_target_sdk_version(__ANDROID_API_M__);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07001936 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
1937 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
1938 << "dlopen should return valid pointer";
1939 dlclose(handle);
1940}