blob: 7e772b8407b7eddb7304cf21dbf864d90f893cf8 [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>
Josh Gao16269572019-10-29 13:41:00 -070031#include <android-base/test_utils.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070032
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000033#include <sys/mman.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010034#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070035#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000036#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000037
Sandeep Patil4e02cc12019-01-21 14:22:05 -080038#include <meminfo/procmeminfo.h>
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040039#include <procinfo/process_map.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"
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -080043#include "utils.h"
Dimitry Ivanov41fd2952016-05-09 17:37:39 -070044#include "dlext_private.h"
Dimitry Ivanov708589f2016-09-19 10:50:28 -070045#include "dlfcn_symlink_support.h"
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000046
47#define ASSERT_DL_NOTNULL(ptr) \
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070048 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000049
50#define ASSERT_DL_ZERO(i) \
51 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
52
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000053#define ASSERT_NOERROR(i) \
54 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
55
Yabin Cui16f7f8d2014-11-04 11:08:05 -080056#define ASSERT_SUBSTR(needle, haystack) \
57 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
58
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000059
60typedef int (*fn)(void);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070061constexpr const char* kLibName = "libdlext_test.so";
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040062constexpr const char* kLibNameRecursive = "libdlext_test_recursive.so";
Dimitry Ivanov927877c2016-09-21 11:17:13 -070063constexpr 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:
Yi Kong358603a2019-03-29 14:25:16 -070069 void SetUp() override {
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
Yi Kong358603a2019-03-29 14:25:16 -070080 void TearDown() override {
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;
Elliott Hughesb51bb502019-05-03 22:45:41 -0700136 ASSERT_EQ(0, FindEntry(handle, kLibZipSimpleZip, &zip_entry));
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800137 extinfo.library_fd_offset = zip_entry.offset;
138 CloseArchive(handle);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700139
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700140 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700141 ASSERT_DL_NOTNULL(handle_);
142
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700143 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
144 ASSERT_DL_NOTNULL(taxicab_number);
145 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700146}
147
148TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700149 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700150
151 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700152 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700153 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700154 extinfo.library_fd_offset = 17;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700155
156 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
157 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700158 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
159
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800160 // Test an address above 2^44, for http://b/18178121 .
161 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700162 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700163 ASSERT_TRUE(handle_ == nullptr);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800164 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
165
166 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
167 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
168 ASSERT_TRUE(handle_ == nullptr);
169 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
170
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700171 extinfo.library_fd_offset = 0;
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700172 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800173 ASSERT_TRUE(handle_ == nullptr);
Elliott Hughesa8971512018-06-27 14:39:06 -0700174 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700175
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -0800176 // Check if dlsym works after unsuccessful dlopen().
177 // Supply non-exiting one to make linker visit every soinfo.
178 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
179 ASSERT_TRUE(sym == nullptr);
180
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700181 close(extinfo.library_fd);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700182}
183
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800184TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700185 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700186 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800187 // This offset will not be used, so it doesn't matter.
188 extinfo.library_fd_offset = 0;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700189
190 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
191 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700192 ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700193}
194
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700195TEST(dlext, android_dlopen_ext_force_load_smoke) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700196 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
197 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700198 // 1. Open actual file
199 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
200 ASSERT_DL_NOTNULL(handle);
201 // 2. Open link with force_load flag set
202 android_dlextinfo extinfo;
203 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700204 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700205 ASSERT_DL_NOTNULL(handle2);
206 ASSERT_TRUE(handle != handle2);
207
208 dlclose(handle2);
209 dlclose(handle);
210}
211
212TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700213 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
214 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700215 // Check if soname lookup still returns already loaded library
216 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700217 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700218 ASSERT_DL_NOTNULL(handle);
219
220 android_dlextinfo extinfo;
221 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
222
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700223 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700224 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
225
226 ASSERT_DL_NOTNULL(handle2);
227 ASSERT_TRUE(handle == handle2);
228
229 dlclose(handle2);
230 dlclose(handle);
231}
232
Victor Chang6cb719f2019-02-06 17:19:10 +0000233TEST(dlfcn, dlopen_from_nullptr_android_api_level) {
234 // Regression test for http://b/123972211. Testing dlopen(nullptr) when target sdk is P
235 android_set_application_target_sdk_version(__ANDROID_API_P__);
236 ASSERT_TRUE(dlopen(nullptr, RTLD_NOW) != nullptr);
237}
238
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700239TEST(dlfcn, dlopen_from_zip_absolute_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700240 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700241 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700242
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700243 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700244 ASSERT_TRUE(handle != nullptr) << dlerror();
245
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700246 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
247 ASSERT_DL_NOTNULL(taxicab_number);
248 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700249
250 dlclose(handle);
251}
252
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700253TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700254 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700255 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700256
257 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
258
259 ASSERT_TRUE(handle != nullptr) << dlerror();
260
261 typedef void *(* dlopen_b_fn)();
262 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
263 ASSERT_TRUE(fn != nullptr) << dlerror();
264
265 void *p = fn();
266 ASSERT_TRUE(p != nullptr) << dlerror();
267
268 dlclose(p);
269 dlclose(handle);
270}
271
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700272TEST(dlfcn, dlopen_from_zip_ld_library_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700273 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700274 const std::string lib_path = GetTestlibRoot() + lib_zip_path + "!/libdir";
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700275
276 typedef void (*fn_t)(const char*);
277 fn_t android_update_LD_LIBRARY_PATH =
278 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
279
280 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
281
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700282 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700283 ASSERT_TRUE(handle == nullptr);
284
285 android_update_LD_LIBRARY_PATH(lib_path.c_str());
286
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700287 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700288 ASSERT_TRUE(handle != nullptr) << dlerror();
289
290 int (*fn)(void);
291 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
292 ASSERT_TRUE(fn != nullptr);
293 EXPECT_EQ(4, fn());
294
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800295 uint32_t* taxicab_number =
296 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700297 ASSERT_DL_NOTNULL(taxicab_number);
298 EXPECT_EQ(1729U, *taxicab_number);
299
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700300 dlclose(handle);
301}
302
303
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000304TEST_F(DlExtTest, Reserved) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700305 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000306 ASSERT_TRUE(start != MAP_FAILED);
307 android_dlextinfo extinfo;
308 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
309 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700310 extinfo.reserved_size = kLibSize;
311 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000312 ASSERT_DL_NOTNULL(handle_);
313 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
314 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700315 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000316 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700317 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000318 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800319
320 // Check that after dlclose reserved address space is unmapped (and can be reused)
321 dlclose(handle_);
322 handle_ = nullptr;
323
324 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
325 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000326}
327
328TEST_F(DlExtTest, ReservedTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800329 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000330 ASSERT_TRUE(start != MAP_FAILED);
331 android_dlextinfo extinfo;
332 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
333 extinfo.reserved_addr = start;
334 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700335 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700336 EXPECT_EQ(nullptr, handle_);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000337}
338
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400339TEST_F(DlExtTest, ReservedRecursive) {
340 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
341 ASSERT_TRUE(start != MAP_FAILED);
342 android_dlextinfo extinfo;
343 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
344 extinfo.reserved_addr = start;
345 extinfo.reserved_size = kLibSize;
346 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
347 ASSERT_DL_NOTNULL(handle_);
348
349 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
350 ASSERT_DL_NOTNULL(f);
351 EXPECT_GE(reinterpret_cast<void*>(f), start);
352 EXPECT_LT(reinterpret_cast<void*>(f),
353 reinterpret_cast<char*>(start) + kLibSize);
354 EXPECT_EQ(4, f());
355
356 f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
357 ASSERT_DL_NOTNULL(f);
358 EXPECT_GE(reinterpret_cast<void*>(f), start);
359 EXPECT_LT(reinterpret_cast<void*>(f),
360 reinterpret_cast<char*>(start) + kLibSize);
361 EXPECT_EQ(8, f());
362
363 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
364 ASSERT_DL_NOTNULL(taxicab_number);
Peter Collingbourne191ecdc2019-08-07 19:06:00 -0700365 // Untag the pointer so that it can be compared with start, which will be untagged.
366 void* addr = reinterpret_cast<void*>(untag_address(taxicab_number));
367 EXPECT_GE(addr, start);
368 EXPECT_LT(addr, reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400369 EXPECT_EQ(1729U, *taxicab_number);
370}
371
372TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
Yi Kong1e7a1502019-03-14 16:25:45 -0700373 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400374 ASSERT_TRUE(start != MAP_FAILED);
375 android_dlextinfo extinfo;
376 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
377 extinfo.reserved_addr = start;
Yi Kong1e7a1502019-03-14 16:25:45 -0700378 extinfo.reserved_size = PAGE_SIZE;
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400379 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
380 EXPECT_EQ(nullptr, handle_);
381}
382
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000383TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700384 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000385 ASSERT_TRUE(start != MAP_FAILED);
386 android_dlextinfo extinfo;
387 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
388 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700389 extinfo.reserved_size = kLibSize;
390 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000391 ASSERT_DL_NOTNULL(handle_);
392 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
393 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700394 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000395 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700396 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000397 EXPECT_EQ(4, f());
398}
399
400TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800401 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000402 ASSERT_TRUE(start != MAP_FAILED);
403 android_dlextinfo extinfo;
404 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
405 extinfo.reserved_addr = start;
406 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700407 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000408 ASSERT_DL_NOTNULL(handle_);
409 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
410 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700411 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
412 (reinterpret_cast<void*>(f) >=
413 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000414 EXPECT_EQ(4, f());
415}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000416
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100417class DlExtRelroSharingTest : public DlExtTest {
418protected:
Yi Kong358603a2019-03-29 14:25:16 -0700419 void SetUp() override {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100420 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700421 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100422 ASSERT_TRUE(start != MAP_FAILED);
423 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
424 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700425 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100426 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000427 }
428
Yi Kong358603a2019-03-29 14:25:16 -0700429 void TearDown() override {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100430 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100431 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000432
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400433 void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
Elliott Hughes5cec3772018-01-19 15:45:23 -0800434 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100435 ASSERT_NOERROR(relro_fd);
436
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400437 if (recursive) {
438 extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
439 }
440
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100441 pid_t pid = fork();
442 if (pid == 0) {
443 // child process
444 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
445 extinfo_.relro_fd = relro_fd;
446 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700447 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100448 fprintf(stderr, "in child: %s\n", dlerror());
449 exit(1);
450 }
Torne (Richard Coles)fa9f7f22019-04-02 17:04:42 -0400451 fn f = reinterpret_cast<fn>(dlsym(handle, "getRandomNumber"));
452 ASSERT_DL_NOTNULL(f);
453 EXPECT_EQ(4, f());
454
455 if (recursive) {
456 fn f = reinterpret_cast<fn>(dlsym(handle, "getBiggerRandomNumber"));
457 ASSERT_DL_NOTNULL(f);
458 EXPECT_EQ(8, f());
459 }
460
461 uint32_t* taxicab_number =
462 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
463 ASSERT_DL_NOTNULL(taxicab_number);
464 EXPECT_EQ(1729U, *taxicab_number);
465 exit(testing::Test::HasFailure());
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100466 }
467
468 // continuing in parent
469 ASSERT_NOERROR(close(relro_fd));
470 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800471 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100472
473 // reopen file for reading so it can be used
Elliott Hughes5cec3772018-01-19 15:45:23 -0800474 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100475 ASSERT_NOERROR(relro_fd);
476 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
477 extinfo_.relro_fd = relro_fd;
478 }
479
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400480 void TryUsingRelro(const char* lib, bool recursive) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100481 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
482 ASSERT_DL_NOTNULL(handle_);
483 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
484 ASSERT_DL_NOTNULL(f);
485 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700486
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400487 if (recursive) {
488 fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
489 ASSERT_DL_NOTNULL(f);
490 EXPECT_EQ(8, f());
491 }
492
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800493 uint32_t* taxicab_number =
494 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700495 ASSERT_DL_NOTNULL(taxicab_number);
496 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100497 }
498
Zhenhua WANG81aad002017-04-25 11:07:19 +0800499 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
500 size_t* pss_out);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100501
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400502 std::string FindMappingName(void* ptr);
503
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100504 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100505};
506
507TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800508 TemporaryFile tf; // Use tf to get an unique filename.
509 ASSERT_NOERROR(close(tf.fd));
510
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400511 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
512 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
513 void* relro_data = dlsym(handle_, "lots_of_relro");
514 ASSERT_DL_NOTNULL(relro_data);
515 EXPECT_EQ(tf.path, FindMappingName(relro_data));
516
517 // Use destructor of tf to close and unlink the file.
518 tf.fd = extinfo_.relro_fd;
519}
520
521TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
522 TemporaryFile tf; // Use tf to get an unique filename.
523 ASSERT_NOERROR(close(tf.fd));
524
525 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
526 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
527 void* relro_data = dlsym(handle_, "lots_of_relro");
528 ASSERT_DL_NOTNULL(relro_data);
529 EXPECT_EQ(tf.path, FindMappingName(relro_data));
530 void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
531 ASSERT_DL_NOTNULL(recursive_relro_data);
532 EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
533
Yabin Cui294d1e22014-12-07 20:43:37 -0800534
535 // Use destructor of tf to close and unlink the file.
536 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100537}
538
Torne (Richard Coles)5d103742019-04-11 12:25:06 -0400539TEST_F(DlExtRelroSharingTest, CheckRelroSizes) {
540 TemporaryFile tf1, tf2;
541 ASSERT_NOERROR(close(tf1.fd));
542 ASSERT_NOERROR(close(tf2.fd));
543
544 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf1.path, false));
545 struct stat no_recursive;
546 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &no_recursive));
547 tf1.fd = extinfo_.relro_fd;
548
549 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf2.path, true));
550 struct stat with_recursive;
551 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &with_recursive));
552 tf2.fd = extinfo_.relro_fd;
553
554 // RELRO file should end up bigger when we use the recursive flag, since it
555 // includes data for more than one library.
556 ASSERT_GT(with_recursive.st_size, no_recursive.st_size);
557}
558
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100559TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800560 TemporaryFile tf; // // Use tf to get an unique filename.
561 ASSERT_NOERROR(close(tf.fd));
562
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400563 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
564 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800565
566 // Use destructor of tf to close and unlink the file.
567 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100568}
569
570TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400571 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000572}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100573
574TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800575 if (geteuid() != 0) GTEST_SKIP() << "This test must be run as root";
Dan Albert69fb9f32014-09-03 11:30:21 -0700576
Yabin Cui294d1e22014-12-07 20:43:37 -0800577 TemporaryFile tf; // Use tf to get an unique filename.
578 ASSERT_NOERROR(close(tf.fd));
579
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400580 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800581
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100582 int pipefd[2];
583 ASSERT_NOERROR(pipe(pipefd));
584
585 size_t without_sharing, with_sharing;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -0800586 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
587 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
Zhenhua WANG81aad002017-04-25 11:07:19 +0800588 ASSERT_LT(with_sharing, without_sharing);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100589
Zhenhua WANG81aad002017-04-25 11:07:19 +0800590 // We expect the sharing to save at least 50% of the library's total PSS.
591 // In practice it saves 80%+ for this library in the test.
592 size_t pss_saved = without_sharing - with_sharing;
593 size_t expected_min_saved = without_sharing / 2;
594
595 EXPECT_LT(expected_min_saved, pss_saved);
Yabin Cui294d1e22014-12-07 20:43:37 -0800596
597 // Use destructor of tf to close and unlink the file.
598 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100599}
600
Zhenhua WANG81aad002017-04-25 11:07:19 +0800601void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
602 size_t* total_pss) {
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800603 android::meminfo::ProcMemInfo proc_mem(pid);
Christopher Ferris89b658c2019-10-10 13:27:54 -0700604 const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats();
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800605 ASSERT_GT(maps.size(), 0UL);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100606
Zhenhua WANG81aad002017-04-25 11:07:19 +0800607 // Calculate total PSS of the library.
608 *total_pss = 0;
609 bool saw_relro_file = false;
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800610 for (auto& vma : maps) {
611 if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
612 if (vma.name == relro_file) {
613 saw_relro_file = true;
614 }
Zhenhua WANG81aad002017-04-25 11:07:19 +0800615
Christopher Ferris89b658c2019-10-10 13:27:54 -0700616 android::meminfo::Vma update_vma(vma);
617 ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma));
618 *total_pss += update_vma.usage.pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800619 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100620 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100621
Zhenhua WANG81aad002017-04-25 11:07:19 +0800622 if (shared_relro) ASSERT_TRUE(saw_relro_file);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100623}
624
Zhenhua WANG81aad002017-04-25 11:07:19 +0800625void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
626 bool share_relro, size_t* pss_out) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100627 const int CHILDREN = 20;
628
629 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800630 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100631 int childpipe[CHILDREN];
632 for (int i=0; i<CHILDREN; ++i) {
633 char read_buf;
634 int child_done_pipe[2], parent_done_pipe[2];
635 ASSERT_NOERROR(pipe(child_done_pipe));
636 ASSERT_NOERROR(pipe(parent_done_pipe));
637
638 pid_t child = fork();
639 if (child == 0) {
640 // close the 'wrong' ends of the pipes in the child
641 close(child_done_pipe[0]);
642 close(parent_done_pipe[1]);
643
644 // open the library
645 void* handle;
646 if (share_relro) {
647 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
648 } else {
649 handle = dlopen(lib, RTLD_NOW);
650 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700651 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100652 fprintf(stderr, "in child: %s\n", dlerror());
653 exit(1);
654 }
655
656 // close write end of child_done_pipe to signal the parent that we're done.
657 close(child_done_pipe[1]);
658
659 // wait for the parent to close parent_done_pipe, then exit
660 read(parent_done_pipe[0], &read_buf, 1);
661 exit(0);
662 }
663
664 ASSERT_NOERROR(child);
665
666 // close the 'wrong' ends of the pipes in the parent
667 close(child_done_pipe[1]);
668 close(parent_done_pipe[0]);
669
670 // wait for the child to be done
671 read(child_done_pipe[0], &read_buf, 1);
672 close(child_done_pipe[0]);
673
674 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800675 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100676 childpipe[i] = parent_done_pipe[1];
677 }
678
Zhenhua WANG81aad002017-04-25 11:07:19 +0800679 // Sum the PSS of tested library of all the children
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100680 size_t total_pss = 0;
681 for (int i=0; i<CHILDREN; ++i) {
682 size_t child_pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800683 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100684 total_pss += child_pss;
685 }
686 *pss_out = total_pss;
687
688 // Close pipes and wait for children to exit
689 for (int i=0; i<CHILDREN; ++i) {
690 ASSERT_NOERROR(close(childpipe[i]));
691 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800692 for (int i = 0; i < CHILDREN; ++i) {
693 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100694 }
695}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700696
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400697std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
698 uint64_t addr = reinterpret_cast<uint64_t>(ptr);
699 std::string found_name = "<not found>";
700
701 EXPECT_TRUE(android::procinfo::ReadMapFile(
702 "/proc/self/maps",
703 [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
704 if (addr >= start && addr < end) {
705 found_name = name;
706 }
707 }));
708
709 return found_name;
710}
711
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700712// Testing namespaces
713static const char* g_public_lib = "libnstest_public.so";
714
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800715// These are libs shared with default namespace
716static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
717
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700718TEST(dlext, ns_smoke) {
719 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800720 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700721
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800722 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
723 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
724 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
725 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700726
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700727 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800728 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700729 ASSERT_TRUE(handle_public != nullptr) << dlerror();
730
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800731 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700732
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800733 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700734 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800735 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800736 ASSERT_TRUE(handle_public == nullptr);
737 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
738 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
739
740 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700741
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800742 // create "public namespace", share limited set of public libraries with
743
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800744 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800745 android_create_namespace("private",
746 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700747 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800748 ANDROID_NAMESPACE_TYPE_REGULAR,
749 nullptr,
750 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700751 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800752 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700753
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800754 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800755 android_create_namespace("private_isolated",
756 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700757 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800758 ANDROID_NAMESPACE_TYPE_ISOLATED,
759 nullptr,
760 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700761 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800762 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700763
764 // This should not have affect search path for default namespace:
765 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
766 void* handle = dlopen(g_public_lib, RTLD_NOW);
767 ASSERT_TRUE(handle != nullptr) << dlerror();
768 dlclose(handle);
769
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700770 // dlopen for a public library using an absolute path should work
771 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700772 android_dlextinfo extinfo;
773 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700774 extinfo.library_namespace = ns2;
775 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
776 ASSERT_TRUE(handle != nullptr) << dlerror();
777 ASSERT_TRUE(handle == handle_public);
778
779 dlclose(handle);
780
781 // 1.1 even if it wasn't loaded before
782 dlclose(handle_public);
783
784 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
785 ASSERT_TRUE(handle_public == nullptr);
786 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
787 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
788
789 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
790 ASSERT_TRUE(handle != nullptr) << dlerror();
791
792 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
793 ASSERT_TRUE(handle == handle_public);
794
795 dlclose(handle);
796
797 // 2. And for regular namespaces (make sure it does not load second copy of the library)
798 extinfo.library_namespace = ns1;
799 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
800 ASSERT_TRUE(handle != nullptr) << dlerror();
801 ASSERT_TRUE(handle == handle_public);
802
803 dlclose(handle);
804
805 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
806 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
807 dlclose(handle_public);
808
809 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
810 ASSERT_TRUE(handle_public == nullptr);
811 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
812 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
813
814 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
815 ASSERT_TRUE(handle != nullptr) << dlerror();
816
817 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
818
819 ASSERT_TRUE(handle != handle_public);
820
821 dlclose(handle);
822
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700823 extinfo.library_namespace = ns1;
824
825 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
826 ASSERT_TRUE(handle1 != nullptr) << dlerror();
827
828 extinfo.library_namespace = ns2;
829 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
830 ASSERT_TRUE(handle2 != nullptr) << dlerror();
831
832 ASSERT_TRUE(handle1 != handle2);
833
834 typedef const char* (*fn_t)();
835
836 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
837 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
838 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
839 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
840
841 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
842 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
843
844 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
845
846 fn_t ns_get_private_extern_string1 =
847 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
848 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
849 fn_t ns_get_private_extern_string2 =
850 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
851 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
852
853 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
854 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
855
856 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
857
858 fn_t ns_get_public_extern_string1 =
859 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
860 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
861 fn_t ns_get_public_extern_string2 =
862 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
863 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
864
865 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
866 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
867
868 // and now check that dlopen() does the right thing in terms of preserving namespace
869 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
870 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
871 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
872 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
873
874 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
875 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
876
877 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
878
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800879 // Check that symbols from non-shared libraries a shared library depends on are not visible
880 // from original namespace.
881
882 fn_t ns_get_internal_extern_string =
883 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
884 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
885 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
886 "ns_get_internal_extern_string() expected to return null but returns \"" <<
887 ns_get_internal_extern_string() << "\"";
888
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700889 dlclose(handle1);
890
891 // Check if handle2 is still alive (and well)
892 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
893 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
894 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
895 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
896
897 dlclose(handle2);
898}
899
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700900TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700901 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700902
903 int tmpfd = TEMP_FAILURE_RETRY(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700904 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700905
906 // Ignore kernels without O_TMPFILE flag support
907 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
908 return;
909 }
910
911 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
912
913 android_namespace_t* ns =
914 android_create_namespace("testing-o_tmpfile",
915 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700916 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700917 ANDROID_NAMESPACE_TYPE_ISOLATED,
918 nullptr,
919 nullptr);
920
921 ASSERT_DL_NOTNULL(ns);
922
923 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
924
925 std::string content;
926 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
927 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
928
929 android_dlextinfo extinfo;
930 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
931 extinfo.library_fd = tmpfd;
932 extinfo.library_namespace = ns;
933
934 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
935
936 ASSERT_DL_NOTNULL(handle);
937
938 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
939 ASSERT_DL_NOTNULL(taxicab_number);
940 EXPECT_EQ(1729U, *taxicab_number);
941 dlclose(handle);
942}
943
944TEST(dlext, dlopen_ext_use_memfd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700945 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700946
947 // create memfd
Elliott Hughes3d24d2b2019-08-05 13:53:01 -0700948 int memfd = memfd_create("foobar", MFD_CLOEXEC);
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700949 if (memfd == -1 && errno == ENOSYS) {
950 return;
951 }
952
953 ASSERT_TRUE(memfd != -1) << strerror(errno);
954
955 // Check st.f_type is TMPFS_MAGIC for memfd
956 struct statfs st;
957 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
958 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
959
960 android_namespace_t* ns =
961 android_create_namespace("testing-memfd",
962 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700963 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700964 ANDROID_NAMESPACE_TYPE_ISOLATED,
965 nullptr,
966 nullptr);
967
968 ASSERT_DL_NOTNULL(ns);
969
970 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
971
972 // read file into memfd backed one.
973 std::string content;
974 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
975 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
976
977 android_dlextinfo extinfo;
978 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
979 extinfo.library_fd = memfd;
980 extinfo.library_namespace = ns;
981
982 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
983
984 ASSERT_DL_NOTNULL(handle);
985
986 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
987 ASSERT_DL_NOTNULL(taxicab_number);
988 EXPECT_EQ(1729U, *taxicab_number);
989 dlclose(handle);
990}
991
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800992TEST(dlext, ns_symbol_visibilty_one_namespace) {
993 static const char* root_lib = "libnstest_root.so";
994 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
995
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700996 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
997 GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800998
999 android_namespace_t* ns =
1000 android_create_namespace("one",
1001 nullptr,
1002 ns_search_path.c_str(),
1003 ANDROID_NAMESPACE_TYPE_ISOLATED,
1004 nullptr,
1005 nullptr);
1006
1007 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1008
1009 android_dlextinfo extinfo;
1010 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1011 extinfo.library_namespace = ns;
1012
1013 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1014 ASSERT_TRUE(handle != nullptr) << dlerror();
1015
1016 typedef const char* (*fn_t)();
1017
1018 // Check that relocation worked correctly
1019 fn_t ns_get_internal_extern_string =
1020 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1021 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1022 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
1023
1024 fn_t internal_extern_string_fn =
1025 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1026 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
1027 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
1028}
1029
1030TEST(dlext, ns_symbol_visibilty_between_namespaces) {
1031 static const char* root_lib = "libnstest_root.so";
1032 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1033
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001034 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1035 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001036
1037 android_namespace_t* ns_public =
1038 android_create_namespace("public",
1039 nullptr,
1040 public_ns_search_path.c_str(),
1041 ANDROID_NAMESPACE_TYPE_ISOLATED,
1042 nullptr,
1043 nullptr);
1044
1045 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1046
1047 android_namespace_t* ns_private =
1048 android_create_namespace("private",
1049 nullptr,
1050 private_ns_search_path.c_str(),
1051 ANDROID_NAMESPACE_TYPE_ISOLATED,
1052 nullptr,
1053 nullptr);
1054
1055 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1056 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1057
1058 android_dlextinfo extinfo;
1059 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1060 extinfo.library_namespace = ns_private;
1061
1062 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1063 ASSERT_TRUE(handle != nullptr) << dlerror();
1064
1065 typedef const char* (*fn_t)();
1066
1067 // Check that relocation worked correctly
1068 fn_t ns_get_internal_extern_string =
1069 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1070 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1071 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
1072 "ns_get_internal_extern_string() expected to return null but returns \"" <<
1073 ns_get_internal_extern_string() << "\"";
1074
1075 fn_t internal_extern_string_fn =
1076 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1077 ASSERT_TRUE(internal_extern_string_fn == nullptr);
1078 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
1079}
1080
1081TEST(dlext, ns_unload_between_namespaces) {
1082 static const char* root_lib = "libnstest_root.so";
1083 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1084
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001085 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1086 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001087
1088 android_namespace_t* ns_public =
1089 android_create_namespace("public",
1090 nullptr,
1091 public_ns_search_path.c_str(),
1092 ANDROID_NAMESPACE_TYPE_ISOLATED,
1093 nullptr,
1094 nullptr);
1095
1096 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1097
1098 android_namespace_t* ns_private =
1099 android_create_namespace("private",
1100 nullptr,
1101 private_ns_search_path.c_str(),
1102 ANDROID_NAMESPACE_TYPE_ISOLATED,
1103 nullptr,
1104 nullptr);
1105
1106 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1107 ASSERT_TRUE(android_link_namespaces(ns_private, 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_private;
1112
1113 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1114 ASSERT_TRUE(handle != nullptr) << dlerror();
1115
1116 dlclose(handle);
1117 // Check that root_lib was unloaded
1118 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1119 ASSERT_TRUE(handle == nullptr);
1120 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1121 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1122
1123 // Check that shared library was unloaded in public ns
1124 extinfo.library_namespace = ns_public;
1125 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1126 ASSERT_TRUE(handle == nullptr);
1127 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1128 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1129}
1130
dimitry965d06d2017-11-28 16:03:07 +01001131TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1132 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1133
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001134 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1135 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001136
1137 android_namespace_t* ns_public =
1138 android_create_namespace("public",
1139 nullptr,
1140 public_ns_search_path.c_str(),
1141 ANDROID_NAMESPACE_TYPE_ISOLATED,
1142 nullptr,
1143 nullptr);
1144
1145 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1146
1147 android_namespace_t* ns_private =
1148 android_create_namespace("private",
1149 nullptr,
1150 private_ns_search_path.c_str(),
1151 ANDROID_NAMESPACE_TYPE_ISOLATED,
1152 nullptr,
1153 nullptr);
1154
1155 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1156 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1157
1158 android_dlextinfo extinfo;
1159 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1160 extinfo.library_namespace = ns_private;
1161
1162 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1163 RTLD_NOW,
1164 &extinfo);
1165 ASSERT_TRUE(handle == nullptr);
1166 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1167 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1168 dlerror());
1169}
1170
1171TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1172 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1173
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001174 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1175 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001176
1177 android_namespace_t* ns_public =
1178 android_create_namespace("public",
1179 nullptr,
1180 public_ns_search_path.c_str(),
1181 ANDROID_NAMESPACE_TYPE_ISOLATED,
1182 nullptr,
1183 nullptr);
1184
1185 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1186
1187 android_namespace_t* ns_private =
1188 android_create_namespace("private",
1189 nullptr,
1190 private_ns_search_path.c_str(),
1191 ANDROID_NAMESPACE_TYPE_ISOLATED,
1192 nullptr,
1193 nullptr);
1194
1195 ASSERT_TRUE(android_link_namespaces(ns_private,
1196 ns_public,
1197 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1198 ) << dlerror();
1199 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1200
1201 android_dlextinfo extinfo;
1202 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1203 extinfo.library_namespace = ns_private;
1204
1205 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1206 ASSERT_TRUE(handle == nullptr);
1207 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1208 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1209 dlerror());
1210}
1211
Jiyong Park37b91af2017-05-05 22:07:05 +09001212TEST(dlext, ns_greylist_enabled) {
Dimitry Ivanov18623142017-02-21 13:41:08 -08001213 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1214
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001215 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov18623142017-02-21 13:41:08 -08001216
1217 android_namespace_t* ns =
1218 android_create_namespace("namespace",
1219 nullptr,
1220 ns_search_path.c_str(),
Jiyong Park37b91af2017-05-05 22:07:05 +09001221 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
Dimitry Ivanov18623142017-02-21 13:41:08 -08001222 nullptr,
1223 nullptr);
1224
1225 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1226
1227 android_dlextinfo extinfo;
1228 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1229 extinfo.library_namespace = ns;
1230
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001231 // An app targeting M can open libnativehelper.so because it's on the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001232 android_set_application_target_sdk_version(__ANDROID_API_M__);
1233 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1234 ASSERT_TRUE(handle != nullptr) << dlerror();
1235
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001236 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1237 void* dlsym_ptr = dlsym(handle, "dlsym");
1238 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1239 ASSERT_EQ(&dlsym, dlsym_ptr);
1240
Dimitry Ivanov18623142017-02-21 13:41:08 -08001241 dlclose(handle);
1242
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001243 // An app targeting N no longer has the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001244 android_set_application_target_sdk_version(__ANDROID_API_N__);
1245 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1246 ASSERT_TRUE(handle == nullptr);
1247 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1248}
1249
Jiyong Park37b91af2017-05-05 22:07:05 +09001250TEST(dlext, ns_greylist_disabled_by_default) {
1251 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1252
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001253 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Jiyong Park37b91af2017-05-05 22:07:05 +09001254
1255 android_namespace_t* ns =
1256 android_create_namespace("namespace",
1257 nullptr,
1258 ns_search_path.c_str(),
1259 ANDROID_NAMESPACE_TYPE_ISOLATED,
1260 nullptr,
1261 nullptr);
1262
1263 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1264
1265 android_dlextinfo extinfo;
1266 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1267 extinfo.library_namespace = ns;
1268
1269 android_set_application_target_sdk_version(__ANDROID_API_M__);
1270 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1271 ASSERT_TRUE(handle == nullptr);
1272 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1273}
1274
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001275TEST(dlext, ns_cyclic_namespaces) {
1276 // Test that ns1->ns2->ns1 link does not break the loader
1277 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1278 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1279
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001280 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001281
1282 android_namespace_t* ns1 =
1283 android_create_namespace("ns1",
1284 nullptr,
1285 ns_search_path.c_str(),
1286 ANDROID_NAMESPACE_TYPE_ISOLATED,
1287 nullptr,
1288 nullptr);
1289
1290 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1291
1292 android_namespace_t* ns2 =
1293 android_create_namespace("ns1",
1294 nullptr,
1295 ns_search_path.c_str(),
1296 ANDROID_NAMESPACE_TYPE_ISOLATED,
1297 nullptr,
1298 nullptr);
1299
1300 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1301
1302 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1303 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1304
1305 android_dlextinfo extinfo;
1306 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1307 extinfo.library_namespace = ns1;
1308
1309 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1310 ASSERT_TRUE(handle == nullptr);
1311 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1312}
1313
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001314TEST(dlext, ns_isolated) {
1315 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001316 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001317
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001318 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001319 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001320 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1321
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001322 android_set_application_target_sdk_version(42U); // something > 23
1323
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001324 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001325
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001326 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001327 android_create_namespace("private",
1328 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001329 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001330 ANDROID_NAMESPACE_TYPE_REGULAR,
1331 nullptr,
1332 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001333 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001334 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001335
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001336 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001337 android_create_namespace("private_isolated1",
1338 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001339 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001340 ANDROID_NAMESPACE_TYPE_ISOLATED,
1341 nullptr,
1342 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001343 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001344 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001345
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001346 android_namespace_t* ns_isolated2 =
1347 android_create_namespace("private_isolated2",
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001348 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001349 nullptr,
1350 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001351 GetTestlibRoot().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001352 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001353 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001354 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001355
1356 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1357 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1358
1359 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001360 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001361
1362 // Load lib_private_external_path to default namespace
1363 // (it should remain invisible for the isolated namespaces after this)
1364 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1365 ASSERT_TRUE(handle != nullptr) << dlerror();
1366
1367 android_dlextinfo extinfo;
1368 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1369 extinfo.library_namespace = ns_not_isolated;
1370
1371 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1372 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1373
1374 extinfo.library_namespace = ns_isolated;
1375
1376 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1377 ASSERT_TRUE(handle2 == nullptr);
Josh Gao16269572019-10-29 13:41:00 -07001378 const char* error = dlerror();
1379 ASSERT_MATCH(error,
1380 R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )"
1381 R"(\S+libnstest_root_not_isolated.so in namespace private_isolated1)");
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001382
1383 // Check dlopen by absolute path
1384 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1385 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001386 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001387 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001388 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001389
1390 extinfo.library_namespace = ns_isolated2;
1391
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001392 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001393 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001394 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1395 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001396
1397 // Check dlopen by absolute path
1398 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001399 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1400 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001401
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
1406 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1407
1408 fn_t ns_get_private_extern_string =
1409 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1410 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1411
1412 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1413
1414 fn_t ns_get_public_extern_string =
1415 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1416 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1417
1418 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1419
1420 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1421 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1422
1423 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1424
1425 dlclose(handle1);
1426}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001427
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001428TEST(dlext, ns_shared) {
1429 static const char* root_lib = "libnstest_root_not_isolated.so";
1430 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001431
1432 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001433
Jiyong Park917d34a2017-08-31 14:07:13 +09001434 // create a parent namespace to use instead of the default namespace. This is
1435 // to make this test be independent from the configuration of the default
1436 // namespace.
1437 android_namespace_t* ns_parent =
1438 android_create_namespace("parent",
1439 nullptr,
1440 nullptr,
1441 ANDROID_NAMESPACE_TYPE_REGULAR,
1442 nullptr,
1443 nullptr);
1444 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1445 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1446
1447 android_dlextinfo extinfo;
1448 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1449 extinfo.library_namespace = ns_parent;
1450
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001451 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Jiyong Park917d34a2017-08-31 14:07:13 +09001452 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001453 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1454
1455 android_set_application_target_sdk_version(42U); // something > 23
1456
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001457 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001458
Jiyong Park917d34a2017-08-31 14:07:13 +09001459 // preload this library to the parent namespace to check if it
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001460 // is shared later on.
1461 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001462 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001463 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1464
Jiyong Park917d34a2017-08-31 14:07:13 +09001465 // create two child namespaces of 'ns_parent'. One with regular, the other
1466 // with isolated & shared.
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001467 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001468 android_create_namespace("private",
1469 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001470 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001471 ANDROID_NAMESPACE_TYPE_REGULAR,
1472 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001473 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001474 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001475 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1476 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001477
1478 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001479 android_create_namespace("private_isolated_shared",
1480 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001481 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001482 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001483 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001484 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001485 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001486 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1487 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001488
Jiyong Park917d34a2017-08-31 14:07:13 +09001489 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001490 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1491
1492 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001493 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001494
Jiyong Park917d34a2017-08-31 14:07:13 +09001495 // Load lib_private_external_path to the parent namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001496 // (it should remain invisible for the isolated namespaces after this)
Jiyong Park917d34a2017-08-31 14:07:13 +09001497 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001498 ASSERT_TRUE(handle != nullptr) << dlerror();
1499
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001500 extinfo.library_namespace = ns_not_isolated;
1501
1502 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1503 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1504
1505 extinfo.library_namespace = ns_isolated_shared;
1506
1507 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1508 ASSERT_TRUE(handle2 == nullptr);
Josh Gao16269572019-10-29 13:41:00 -07001509 ASSERT_MATCH(dlerror(),
1510 R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )"
1511 R"(\S+libnstest_root_not_isolated.so in namespace private_isolated_shared)");
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001512
1513 // Check dlopen by absolute path
1514 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1515 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001516 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001517 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001518 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001519
1520 // load libnstest_root.so to shared namespace in order to check that everything is different
1521 // except shared libnstest_dlopened.so
1522
1523 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1524
1525 typedef const char* (*fn_t)();
1526 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1527 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1528 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1529 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1530
1531 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1532 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1533 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1534
1535 fn_t ns_get_private_extern_string =
1536 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1537 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1538 fn_t ns_get_private_extern_string_shared =
1539 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1540 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1541
1542 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1543 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1544 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1545
1546 fn_t ns_get_public_extern_string =
1547 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1548 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1549 fn_t ns_get_public_extern_string_shared =
1550 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1551 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1552
1553 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1554 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1555 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1556
1557 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1558 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1559 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1560 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1561 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1562 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1563
1564 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1565 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1566 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1567 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1568 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1569
1570 dlclose(handle1);
1571 dlclose(handle2);
1572}
1573
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001574TEST(dlext, ns_shared_links_and_paths) {
1575 // Create parent namespace (isolated, not shared)
1576 android_namespace_t* ns_isolated =
1577 android_create_namespace("private_isolated",
1578 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001579 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001580 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001581 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001582 nullptr);
1583 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1584 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1585
1586 // Create shared namespace with ns_isolated parent
1587 android_namespace_t* ns_shared =
1588 android_create_namespace("private_shared",
1589 nullptr,
1590 nullptr,
1591 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1592 nullptr,
1593 ns_isolated);
1594 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1595
1596 // 1. Load a library in ns_shared to check that it has inherited
1597 // search path and the link to the default namespace.
1598 android_dlextinfo extinfo;
1599 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1600 extinfo.library_namespace = ns_shared;
1601
1602 {
1603 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1604 ASSERT_TRUE(handle != nullptr) << dlerror();
1605 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1606 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1607 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1608
1609 dlclose(handle);
1610 }
1611 // 2. Load another test library by absolute path to check that
1612 // it has inherited permitted_when_isolated_path
1613 {
1614 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001615 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001616 RTLD_NOW,
1617 &extinfo);
1618
1619 ASSERT_TRUE(handle != nullptr) << dlerror();
1620 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1621 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1622 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1623
1624 dlclose(handle);
1625 }
1626
1627 // 3. Check that it is still isolated.
1628 {
1629 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001630 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001631 RTLD_NOW,
1632 &extinfo);
1633
1634 ASSERT_TRUE(handle == nullptr);
1635 }
1636}
1637
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001638TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001639 android_set_application_target_sdk_version(42U); // something > 23
1640
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001641 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001642
1643 // preload this library to the default namespace to check if it
1644 // is shared later on.
1645 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001646 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001647 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1648
1649 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001650 android_create_namespace("private_isolated_shared",
1651 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001652 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001653 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001654 nullptr,
1655 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001656 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001657 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001658
1659 // Check if "libnstest_dlopened.so" is loaded (and the same)
1660 android_dlextinfo extinfo;
1661 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1662 extinfo.library_namespace = ns_isolated_shared;
1663
1664 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1665 ASSERT_TRUE(handle != nullptr) << dlerror();
1666 ASSERT_TRUE(handle == handle_dlopened);
1667 dlclose(handle);
1668 dlclose(handle_dlopened);
1669
1670 // And now check that the library cannot be found by soname (and is no longer loaded)
1671 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1672 ASSERT_TRUE(handle == nullptr)
1673 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1674
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001675 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001676 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1677 ASSERT_TRUE(handle == nullptr)
1678 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1679
1680 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1681 ASSERT_TRUE(handle == nullptr)
1682 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1683
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001684 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001685 RTLD_NOW | RTLD_NOLOAD);
1686 ASSERT_TRUE(handle == nullptr)
1687 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1688
1689 // Now lets see if the soinfo area gets reused in the wrong way:
1690 // load a library to default namespace.
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001691 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001692 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1693 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1694
1695 // try to find it in shared namespace
1696 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1697 ASSERT_TRUE(handle == nullptr)
1698 << "Error: " << g_public_lib << " is accessible in shared namespace";
1699}
1700
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001701TEST(dlext, ns_isolated_rtld_global) {
1702 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001703 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001704
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001705 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001706
1707 android_namespace_t* ns1 =
1708 android_create_namespace("isolated1",
1709 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001710 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001711 ANDROID_NAMESPACE_TYPE_ISOLATED,
1712 lib_public_path.c_str(),
1713 nullptr);
1714 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001715 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001716
1717 android_namespace_t* ns2 =
1718 android_create_namespace("isolated2",
1719 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001720 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001721 ANDROID_NAMESPACE_TYPE_ISOLATED,
1722 lib_public_path.c_str(),
1723 nullptr);
1724 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001725 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001726
1727 android_dlextinfo extinfo;
1728 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1729 extinfo.library_namespace = ns1;
1730
1731 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1732 RTLD_GLOBAL,
1733 &extinfo);
1734
1735 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1736
1737 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001738 android_create_namespace("isolated1_child",
1739 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001740 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001741 ANDROID_NAMESPACE_TYPE_ISOLATED,
1742 nullptr,
1743 ns1);
1744
1745 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1746 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001747
1748 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1749 // attempt to use ns2 should result in dlerror()
1750
1751 // Check ns1_child first.
1752 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1753 extinfo.library_namespace = ns1_child;
1754
1755 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1756 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1757
1758 // now ns1
1759 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1760 extinfo.library_namespace = ns1;
1761
1762 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1763 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1764
1765 // and ns2 should fail
1766 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1767 extinfo.library_namespace = ns2;
1768
1769 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1770 ASSERT_TRUE(handle1 == nullptr);
Josh Gao16269572019-10-29 13:41:00 -07001771 ASSERT_MATCH(
1772 dlerror(),
1773 R"(dlopen failed: library "libnstest_public.so" not found: needed by \S+libnstest_root.so)"
1774 R"( in namespace isolated2)");
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001775}
1776
dimitry8db36a52017-10-23 15:10:10 +02001777TEST(dlext, ns_inaccessible_error_message) {
1778 // We set up 2 namespaces (a and b) and link a->b with a shared library
1779 // libtestshared.so. Then try to dlopen different library with the same
1780 // name from in namespace a. Note that library should not be accessible
1781 // in either namespace but since it's soname is in the list of shared libs
1782 // the linker will attempt to find it in linked namespace.
1783 //
1784 // Check the error message and make sure it mentions correct namespace name.
1785 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1786
1787 android_namespace_t* ns_a =
1788 android_create_namespace("ns_a",
1789 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001790 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001791 ANDROID_NAMESPACE_TYPE_ISOLATED,
1792 nullptr,
1793 nullptr);
1794 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1795 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1796
1797 android_namespace_t* ns_b =
1798 android_create_namespace("ns_b",
1799 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001800 GetTestlibRoot().c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001801 ANDROID_NAMESPACE_TYPE_ISOLATED,
1802 nullptr,
1803 nullptr);
1804 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1805 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1806
1807 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1808
1809 android_dlextinfo extinfo;
1810 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1811 extinfo.library_namespace = ns_a;
1812
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001813 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
dimitry8db36a52017-10-23 15:10:10 +02001814
1815 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1816 ASSERT_TRUE(handle == nullptr);
1817 std::string expected_dlerror =
1818 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1819 " is not accessible for the namespace \"ns_a\"",
1820 library_path.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001821 android::base::GetExecutablePath().c_str());
dimitry8db36a52017-10-23 15:10:10 +02001822 ASSERT_EQ(expected_dlerror, dlerror());
1823}
1824
dimitry321476a2018-01-29 15:32:37 +01001825extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1826 android_namespace_t* namespace_to);
1827
Logan Chien9ee45912018-01-18 12:05:09 +08001828TEST(dlext, ns_link_namespaces_invalid_arguments) {
1829 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1830
1831 android_namespace_t* ns =
1832 android_create_namespace("private",
1833 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001834 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001835 ANDROID_NAMESPACE_TYPE_REGULAR,
1836 nullptr,
1837 nullptr);
1838 ASSERT_TRUE(ns != nullptr) << dlerror();
1839
1840 // Test android_link_namespaces()
1841 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1842 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1843 dlerror());
1844
1845 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1846 ASSERT_STREQ("android_link_namespaces failed: "
1847 "error linking namespaces \"private\"->\"(default)\": "
1848 "the list of shared libraries is empty.", dlerror());
1849
1850 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1851 ASSERT_STREQ("android_link_namespaces failed: "
1852 "error linking namespaces \"private\"->\"(default)\": "
1853 "the list of shared libraries is empty.", dlerror());
1854
dimitry321476a2018-01-29 15:32:37 +01001855 // Test __loader_android_link_namespaces_all_libs()
1856 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001857 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1858 "error linking namespaces: namespace_from is null.", dlerror());
1859
dimitry321476a2018-01-29 15:32:37 +01001860 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
Logan Chien9ee45912018-01-18 12:05:09 +08001861 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1862 "error linking namespaces: namespace_from is null.", dlerror());
1863
dimitry321476a2018-01-29 15:32:37 +01001864 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001865 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1866 "error linking namespaces: namespace_to is null.", dlerror());
1867}
1868
1869TEST(dlext, ns_allow_all_shared_libs) {
1870 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1871
1872 android_namespace_t* ns_a =
1873 android_create_namespace("ns_a",
1874 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001875 (GetTestlibRoot() + "/ns_a").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001876 ANDROID_NAMESPACE_TYPE_ISOLATED,
1877 nullptr,
1878 nullptr);
1879 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1880 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1881
1882 android_namespace_t* ns_b =
1883 android_create_namespace("ns_b",
1884 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001885 (GetTestlibRoot() + "/ns_b").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001886 ANDROID_NAMESPACE_TYPE_ISOLATED,
1887 nullptr,
1888 nullptr);
1889 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1890 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1891
1892 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
dimitry321476a2018-01-29 15:32:37 +01001893 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
Logan Chien9ee45912018-01-18 12:05:09 +08001894
1895 // Load libs with android_dlopen_ext() from namespace b
1896 android_dlextinfo extinfo;
1897 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1898 extinfo.library_namespace = ns_b;
1899
1900 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1901 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1902
1903 void* ns_b_handle1_internal =
1904 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1905 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1906
1907 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1908 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1909
1910 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1911 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1912
1913 // Load libs with android_dlopen_ext() from namespace a
1914 extinfo.library_namespace = ns_a;
1915
1916 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1917 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1918
1919 void* ns_a_handle1_internal =
1920 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1921 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1922
1923 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1924 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1925
1926 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1927 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1928
1929 // Compare the dlopen handle
1930 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1931 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1932 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1933
1934 // Close libs
1935 dlclose(ns_b_handle1);
1936 dlclose(ns_b_handle2);
1937 dlclose(ns_b_handle3);
1938
1939 dlclose(ns_a_handle1);
1940 dlclose(ns_a_handle1_internal);
1941 dlclose(ns_a_handle2);
1942 dlclose(ns_a_handle3);
1943}
1944
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001945TEST(dlext, ns_anonymous) {
1946 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001947 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001948
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001949 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001950 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1951
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001952 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1953
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001954 ASSERT_TRUE(
1955 android_init_anonymous_namespace(shared_libs.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001956 (GetTestlibRoot() + "/private_namespace_libs").c_str())
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001957 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001958
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001959 android_namespace_t* ns =
1960 android_create_namespace("private",
1961 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001962 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001963 ANDROID_NAMESPACE_TYPE_REGULAR,
1964 nullptr,
1965 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001966
1967 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001968 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001969
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001970 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001971
1972 android_dlextinfo extinfo;
1973 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1974 extinfo.library_namespace = ns;
1975
1976 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1977 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1978 ASSERT_TRUE(handle != nullptr) << dlerror();
1979
1980 uintptr_t ns_get_dlopened_string_addr =
1981 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1982 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1983 typedef const char* (*fn_t)();
1984 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1985
1986 std::vector<map_record> maps;
1987 Maps::parse_maps(&maps);
1988
1989 uintptr_t addr_start = 0;
1990 uintptr_t addr_end = 0;
dimitry8eaf28d2017-10-11 10:04:14 +02001991 bool has_executable_segment = false;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001992 std::vector<map_record> maps_to_copy;
1993
1994 for (const auto& rec : maps) {
1995 if (rec.pathname == private_library_absolute_path) {
1996 if (addr_start == 0) {
1997 addr_start = rec.addr_start;
1998 }
1999 addr_end = rec.addr_end;
dimitry8eaf28d2017-10-11 10:04:14 +02002000 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002001
2002 maps_to_copy.push_back(rec);
2003 }
2004 }
2005
2006 // some sanity checks..
2007 ASSERT_TRUE(addr_start > 0);
2008 ASSERT_TRUE(addr_end > 0);
dimitry3b0a5b72018-06-06 11:11:25 +02002009 ASSERT_TRUE(maps_to_copy.size() > 0);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002010 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
2011 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
2012
dimitry8eaf28d2017-10-11 10:04:14 +02002013 if (!has_executable_segment) {
2014 // For some natively bridged environments this code might be missing
2015 // the executable flag. This is because the guest code is not supposed
2016 // to be executed directly and making it non-executable is more secure.
2017 // If this is the case we assume that the first segment is the one that
2018 // has this flag.
2019 ASSERT_TRUE((maps_to_copy[0].perms & PROT_WRITE) == 0);
2020 maps_to_copy[0].perms |= PROT_EXEC;
2021 }
2022
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002023 // copy
2024 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
2025 PROT_NONE, MAP_ANON | MAP_PRIVATE,
2026 -1, 0));
2027 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
2028
2029 for (const auto& rec : maps_to_copy) {
2030 uintptr_t offset = rec.addr_start - addr_start;
2031 size_t size = rec.addr_end - rec.addr_start;
2032 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
2033 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
2034 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
2035 ASSERT_TRUE(map != MAP_FAILED);
2036 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
2037 mprotect(map, size, rec.perms);
2038 }
2039
2040 // call the function copy
2041 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
2042 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
2043 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2044 ns_get_dlopened_string_anon());
2045
2046 // They should belong to different namespaces (private and anonymous)
2047 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2048 ns_get_dlopened_string_private());
2049
2050 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
2051}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002052
2053TEST(dlext, dlopen_handle_value_platform) {
2054 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2055 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
2056 << "dlopen should return odd value for the handle";
2057 dlclose(handle);
2058}
2059
2060TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08002061 android_set_application_target_sdk_version(__ANDROID_API_M__);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002062 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2063 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
2064 << "dlopen should return valid pointer";
2065 dlclose(handle);
2066}