blob: f5e0c9c421736fac1e3e1325582fbaba1c0472f8 [file] [log] [blame]
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <dlfcn.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080020#include <elf.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000021#include <errno.h>
22#include <fcntl.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080023#include <inttypes.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000024#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070027
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000028#include <android/dlext.h>
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -070029#include <android-base/file.h>
Zhenhua WANG81aad002017-04-25 11:07:19 +080030#include <android-base/strings.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070031
32#include <linux/memfd.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000033#include <sys/mman.h>
Elliott Hughesd7c52622017-06-20 14:26:56 -070034#include <sys/syscall.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010035#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070036#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000037#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000038
Sandeep Patil4e02cc12019-01-21 14:22:05 -080039#include <meminfo/procmeminfo.h>
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040040#include <procinfo/process_map.h>
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -080041#include <ziparchive/zip_archive.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010042
Dimitry Ivanov927877c2016-09-21 11:17:13 -070043#include "gtest_globals.h"
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -080044#include "utils.h"
Dimitry Ivanov41fd2952016-05-09 17:37:39 -070045#include "dlext_private.h"
Dimitry Ivanov708589f2016-09-19 10:50:28 -070046#include "dlfcn_symlink_support.h"
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000047
48#define ASSERT_DL_NOTNULL(ptr) \
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070049 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000050
51#define ASSERT_DL_ZERO(i) \
52 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
53
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000054#define ASSERT_NOERROR(i) \
55 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
56
Yabin Cui16f7f8d2014-11-04 11:08:05 -080057#define ASSERT_SUBSTR(needle, haystack) \
58 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
59
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000060
61typedef int (*fn)(void);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070062constexpr const char* kLibName = "libdlext_test.so";
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040063constexpr const char* kLibNameRecursive = "libdlext_test_recursive.so";
Dimitry Ivanov927877c2016-09-21 11:17:13 -070064constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
65constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
66constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070067
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000068class DlExtTest : public ::testing::Test {
69protected:
70 virtual void SetUp() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070071 handle_ = nullptr;
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000072 // verify that we don't have the library loaded already
Dimitry Ivanov927877c2016-09-21 11:17:13 -070073 void* h = dlopen(kLibName, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070074 ASSERT_TRUE(h == nullptr);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070075 h = dlopen(kLibNameNoRelro, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070076 ASSERT_TRUE(h == nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000077 // call dlerror() to swallow the error, and check it was the one we wanted
Dimitry Ivanov927877c2016-09-21 11:17:13 -070078 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 +000079 }
80
81 virtual void TearDown() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070082 if (handle_ != nullptr) {
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000083 ASSERT_DL_ZERO(dlclose(handle_));
84 }
85 }
86
87 void* handle_;
88};
89
90TEST_F(DlExtTest, ExtInfoNull) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -070091 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000092 ASSERT_DL_NOTNULL(handle_);
93 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
94 ASSERT_DL_NOTNULL(f);
95 EXPECT_EQ(4, f());
96}
97
98TEST_F(DlExtTest, ExtInfoNoFlags) {
99 android_dlextinfo extinfo;
100 extinfo.flags = 0;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700101 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000102 ASSERT_DL_NOTNULL(handle_);
103 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
104 ASSERT_DL_NOTNULL(f);
105 EXPECT_EQ(4, f());
106}
107
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700108TEST_F(DlExtTest, ExtInfoUseFd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700109 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_fd/libdlext_test_fd.so";
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700110
111 android_dlextinfo extinfo;
112 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700113 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700114 ASSERT_TRUE(extinfo.library_fd != -1);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700115 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700116 ASSERT_DL_NOTNULL(handle_);
117 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
118 ASSERT_DL_NOTNULL(f);
119 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700120
121 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
122 ASSERT_DL_NOTNULL(taxicab_number);
123 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700124}
125
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700126TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700127 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700128
129 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700130 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700131 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800132
133 // Find the offset of the shared library in the zip.
134 ZipArchiveHandle handle;
135 ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
136 ZipEntry zip_entry;
137 ZipString zip_name;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700138 zip_name.name = reinterpret_cast<const uint8_t*>(kLibZipSimpleZip);
139 zip_name.name_length = strlen(kLibZipSimpleZip);
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800140 ASSERT_EQ(0, FindEntry(handle, zip_name, &zip_entry));
141 extinfo.library_fd_offset = zip_entry.offset;
142 CloseArchive(handle);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700143
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700144 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700145 ASSERT_DL_NOTNULL(handle_);
146
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700147 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
148 ASSERT_DL_NOTNULL(taxicab_number);
149 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700150}
151
152TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700153 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700154
155 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700156 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700157 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700158 extinfo.library_fd_offset = 17;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700159
160 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
161 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700162 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
163
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800164 // Test an address above 2^44, for http://b/18178121 .
165 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700166 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700167 ASSERT_TRUE(handle_ == nullptr);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800168 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
169
170 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
171 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
172 ASSERT_TRUE(handle_ == nullptr);
173 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
174
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700175 extinfo.library_fd_offset = 0;
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700176 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800177 ASSERT_TRUE(handle_ == nullptr);
Elliott Hughesa8971512018-06-27 14:39:06 -0700178 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700179
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -0800180 // Check if dlsym works after unsuccessful dlopen().
181 // Supply non-exiting one to make linker visit every soinfo.
182 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
183 ASSERT_TRUE(sym == nullptr);
184
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700185 close(extinfo.library_fd);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700186}
187
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800188TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700189 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700190 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800191 // This offset will not be used, so it doesn't matter.
192 extinfo.library_fd_offset = 0;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700193
194 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
195 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700196 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 -0700197}
198
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700199TEST(dlext, android_dlopen_ext_force_load_smoke) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700200 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
201 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700202 // 1. Open actual file
203 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
204 ASSERT_DL_NOTNULL(handle);
205 // 2. Open link with force_load flag set
206 android_dlextinfo extinfo;
207 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700208 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700209 ASSERT_DL_NOTNULL(handle2);
210 ASSERT_TRUE(handle != handle2);
211
212 dlclose(handle2);
213 dlclose(handle);
214}
215
216TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700217 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
218 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700219 // Check if soname lookup still returns already loaded library
220 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700221 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700222 ASSERT_DL_NOTNULL(handle);
223
224 android_dlextinfo extinfo;
225 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
226
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700227 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700228 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
229
230 ASSERT_DL_NOTNULL(handle2);
231 ASSERT_TRUE(handle == handle2);
232
233 dlclose(handle2);
234 dlclose(handle);
235}
236
Victor Chang6cb719f2019-02-06 17:19:10 +0000237TEST(dlfcn, dlopen_from_nullptr_android_api_level) {
238 // Regression test for http://b/123972211. Testing dlopen(nullptr) when target sdk is P
239 android_set_application_target_sdk_version(__ANDROID_API_P__);
240 ASSERT_TRUE(dlopen(nullptr, RTLD_NOW) != nullptr);
241}
242
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700243TEST(dlfcn, dlopen_from_zip_absolute_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700244 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700245 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700246
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700247 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700248 ASSERT_TRUE(handle != nullptr) << dlerror();
249
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700250 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
251 ASSERT_DL_NOTNULL(taxicab_number);
252 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700253
254 dlclose(handle);
255}
256
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700257TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700258 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700259 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700260
261 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
262
263 ASSERT_TRUE(handle != nullptr) << dlerror();
264
265 typedef void *(* dlopen_b_fn)();
266 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
267 ASSERT_TRUE(fn != nullptr) << dlerror();
268
269 void *p = fn();
270 ASSERT_TRUE(p != nullptr) << dlerror();
271
272 dlclose(p);
273 dlclose(handle);
274}
275
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700276TEST(dlfcn, dlopen_from_zip_ld_library_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700277 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700278 const std::string lib_path = GetTestlibRoot() + lib_zip_path + "!/libdir";
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700279
280 typedef void (*fn_t)(const char*);
281 fn_t android_update_LD_LIBRARY_PATH =
282 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
283
284 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
285
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700286 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700287 ASSERT_TRUE(handle == nullptr);
288
289 android_update_LD_LIBRARY_PATH(lib_path.c_str());
290
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700291 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700292 ASSERT_TRUE(handle != nullptr) << dlerror();
293
294 int (*fn)(void);
295 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
296 ASSERT_TRUE(fn != nullptr);
297 EXPECT_EQ(4, fn());
298
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800299 uint32_t* taxicab_number =
300 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700301 ASSERT_DL_NOTNULL(taxicab_number);
302 EXPECT_EQ(1729U, *taxicab_number);
303
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700304 dlclose(handle);
305}
306
307
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000308TEST_F(DlExtTest, Reserved) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700309 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000310 ASSERT_TRUE(start != MAP_FAILED);
311 android_dlextinfo extinfo;
312 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
313 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700314 extinfo.reserved_size = kLibSize;
315 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000316 ASSERT_DL_NOTNULL(handle_);
317 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
318 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700319 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000320 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700321 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000322 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800323
324 // Check that after dlclose reserved address space is unmapped (and can be reused)
325 dlclose(handle_);
326 handle_ = nullptr;
327
328 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
329 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000330}
331
332TEST_F(DlExtTest, ReservedTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800333 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000334 ASSERT_TRUE(start != MAP_FAILED);
335 android_dlextinfo extinfo;
336 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
337 extinfo.reserved_addr = start;
338 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700339 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700340 EXPECT_EQ(nullptr, handle_);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000341}
342
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400343TEST_F(DlExtTest, ReservedRecursive) {
344 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
345 ASSERT_TRUE(start != MAP_FAILED);
346 android_dlextinfo extinfo;
347 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
348 extinfo.reserved_addr = start;
349 extinfo.reserved_size = kLibSize;
350 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
351 ASSERT_DL_NOTNULL(handle_);
352
353 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
354 ASSERT_DL_NOTNULL(f);
355 EXPECT_GE(reinterpret_cast<void*>(f), start);
356 EXPECT_LT(reinterpret_cast<void*>(f),
357 reinterpret_cast<char*>(start) + kLibSize);
358 EXPECT_EQ(4, f());
359
360 f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
361 ASSERT_DL_NOTNULL(f);
362 EXPECT_GE(reinterpret_cast<void*>(f), start);
363 EXPECT_LT(reinterpret_cast<void*>(f),
364 reinterpret_cast<char*>(start) + kLibSize);
365 EXPECT_EQ(8, f());
366
367 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
368 ASSERT_DL_NOTNULL(taxicab_number);
369 EXPECT_GE(reinterpret_cast<void*>(taxicab_number), start);
370 EXPECT_LT(reinterpret_cast<void*>(taxicab_number), reinterpret_cast<char*>(start) + kLibSize);
371 EXPECT_EQ(1729U, *taxicab_number);
372}
373
374TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
Yi Kong1e7a1502019-03-14 16:25:45 -0700375 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400376 ASSERT_TRUE(start != MAP_FAILED);
377 android_dlextinfo extinfo;
378 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
379 extinfo.reserved_addr = start;
Yi Kong1e7a1502019-03-14 16:25:45 -0700380 extinfo.reserved_size = PAGE_SIZE;
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400381 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
382 EXPECT_EQ(nullptr, handle_);
383}
384
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000385TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700386 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000387 ASSERT_TRUE(start != MAP_FAILED);
388 android_dlextinfo extinfo;
389 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
390 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700391 extinfo.reserved_size = kLibSize;
392 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000393 ASSERT_DL_NOTNULL(handle_);
394 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
395 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700396 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000397 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700398 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000399 EXPECT_EQ(4, f());
400}
401
402TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800403 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000404 ASSERT_TRUE(start != MAP_FAILED);
405 android_dlextinfo extinfo;
406 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
407 extinfo.reserved_addr = start;
408 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700409 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000410 ASSERT_DL_NOTNULL(handle_);
411 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
412 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700413 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
414 (reinterpret_cast<void*>(f) >=
415 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000416 EXPECT_EQ(4, f());
417}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000418
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100419class DlExtRelroSharingTest : public DlExtTest {
420protected:
421 virtual void SetUp() {
422 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700423 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100424 ASSERT_TRUE(start != MAP_FAILED);
425 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
426 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700427 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100428 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000429 }
430
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100431 virtual void TearDown() {
432 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100433 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000434
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400435 void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
Elliott Hughes5cec3772018-01-19 15:45:23 -0800436 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100437 ASSERT_NOERROR(relro_fd);
438
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400439 if (recursive) {
440 extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
441 }
442
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100443 pid_t pid = fork();
444 if (pid == 0) {
445 // child process
446 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
447 extinfo_.relro_fd = relro_fd;
448 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700449 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100450 fprintf(stderr, "in child: %s\n", dlerror());
451 exit(1);
452 }
453 exit(0);
454 }
455
456 // continuing in parent
457 ASSERT_NOERROR(close(relro_fd));
458 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800459 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100460
461 // reopen file for reading so it can be used
Elliott Hughes5cec3772018-01-19 15:45:23 -0800462 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100463 ASSERT_NOERROR(relro_fd);
464 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
465 extinfo_.relro_fd = relro_fd;
466 }
467
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400468 void TryUsingRelro(const char* lib, bool recursive) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100469 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
470 ASSERT_DL_NOTNULL(handle_);
471 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
472 ASSERT_DL_NOTNULL(f);
473 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700474
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400475 if (recursive) {
476 fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
477 ASSERT_DL_NOTNULL(f);
478 EXPECT_EQ(8, f());
479 }
480
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800481 uint32_t* taxicab_number =
482 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700483 ASSERT_DL_NOTNULL(taxicab_number);
484 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100485 }
486
Zhenhua WANG81aad002017-04-25 11:07:19 +0800487 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
488 size_t* pss_out);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100489
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400490 std::string FindMappingName(void* ptr);
491
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100492 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100493};
494
495TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800496 TemporaryFile tf; // Use tf to get an unique filename.
497 ASSERT_NOERROR(close(tf.fd));
498
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400499 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
500 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
501 void* relro_data = dlsym(handle_, "lots_of_relro");
502 ASSERT_DL_NOTNULL(relro_data);
503 EXPECT_EQ(tf.path, FindMappingName(relro_data));
504
505 // Use destructor of tf to close and unlink the file.
506 tf.fd = extinfo_.relro_fd;
507}
508
509TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
510 TemporaryFile tf; // Use tf to get an unique filename.
511 ASSERT_NOERROR(close(tf.fd));
512
513 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
514 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
515 void* relro_data = dlsym(handle_, "lots_of_relro");
516 ASSERT_DL_NOTNULL(relro_data);
517 EXPECT_EQ(tf.path, FindMappingName(relro_data));
518 void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
519 ASSERT_DL_NOTNULL(recursive_relro_data);
520 EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
521
Yabin Cui294d1e22014-12-07 20:43:37 -0800522
523 // Use destructor of tf to close and unlink the file.
524 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100525}
526
527TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800528 TemporaryFile tf; // // Use tf to get an unique filename.
529 ASSERT_NOERROR(close(tf.fd));
530
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400531 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
532 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800533
534 // Use destructor of tf to close and unlink the file.
535 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100536}
537
538TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400539 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000540}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100541
542TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Dan Albert69fb9f32014-09-03 11:30:21 -0700543 if (geteuid() != 0) {
544 GTEST_LOG_(INFO) << "This test must be run as root.\n";
545 return;
546 }
547
Yabin Cui294d1e22014-12-07 20:43:37 -0800548 TemporaryFile tf; // Use tf to get an unique filename.
549 ASSERT_NOERROR(close(tf.fd));
550
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400551 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800552
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100553 int pipefd[2];
554 ASSERT_NOERROR(pipe(pipefd));
555
556 size_t without_sharing, with_sharing;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -0800557 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
558 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
Zhenhua WANG81aad002017-04-25 11:07:19 +0800559 ASSERT_LT(with_sharing, without_sharing);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100560
Zhenhua WANG81aad002017-04-25 11:07:19 +0800561 // We expect the sharing to save at least 50% of the library's total PSS.
562 // In practice it saves 80%+ for this library in the test.
563 size_t pss_saved = without_sharing - with_sharing;
564 size_t expected_min_saved = without_sharing / 2;
565
566 EXPECT_LT(expected_min_saved, pss_saved);
Yabin Cui294d1e22014-12-07 20:43:37 -0800567
568 // Use destructor of tf to close and unlink the file.
569 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100570}
571
Zhenhua WANG81aad002017-04-25 11:07:19 +0800572void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
573 size_t* total_pss) {
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800574 android::meminfo::ProcMemInfo proc_mem(pid);
575 const std::vector<android::meminfo::Vma>& maps = proc_mem.Maps();
576 ASSERT_GT(maps.size(), 0UL);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100577
Zhenhua WANG81aad002017-04-25 11:07:19 +0800578 // Calculate total PSS of the library.
579 *total_pss = 0;
580 bool saw_relro_file = false;
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800581 for (auto& vma : maps) {
582 if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
583 if (vma.name == relro_file) {
584 saw_relro_file = true;
585 }
Zhenhua WANG81aad002017-04-25 11:07:19 +0800586
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800587 *total_pss += vma.usage.pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800588 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100589 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100590
Zhenhua WANG81aad002017-04-25 11:07:19 +0800591 if (shared_relro) ASSERT_TRUE(saw_relro_file);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100592}
593
Zhenhua WANG81aad002017-04-25 11:07:19 +0800594void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
595 bool share_relro, size_t* pss_out) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100596 const int CHILDREN = 20;
597
598 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800599 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100600 int childpipe[CHILDREN];
601 for (int i=0; i<CHILDREN; ++i) {
602 char read_buf;
603 int child_done_pipe[2], parent_done_pipe[2];
604 ASSERT_NOERROR(pipe(child_done_pipe));
605 ASSERT_NOERROR(pipe(parent_done_pipe));
606
607 pid_t child = fork();
608 if (child == 0) {
609 // close the 'wrong' ends of the pipes in the child
610 close(child_done_pipe[0]);
611 close(parent_done_pipe[1]);
612
613 // open the library
614 void* handle;
615 if (share_relro) {
616 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
617 } else {
618 handle = dlopen(lib, RTLD_NOW);
619 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700620 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100621 fprintf(stderr, "in child: %s\n", dlerror());
622 exit(1);
623 }
624
625 // close write end of child_done_pipe to signal the parent that we're done.
626 close(child_done_pipe[1]);
627
628 // wait for the parent to close parent_done_pipe, then exit
629 read(parent_done_pipe[0], &read_buf, 1);
630 exit(0);
631 }
632
633 ASSERT_NOERROR(child);
634
635 // close the 'wrong' ends of the pipes in the parent
636 close(child_done_pipe[1]);
637 close(parent_done_pipe[0]);
638
639 // wait for the child to be done
640 read(child_done_pipe[0], &read_buf, 1);
641 close(child_done_pipe[0]);
642
643 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800644 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100645 childpipe[i] = parent_done_pipe[1];
646 }
647
Zhenhua WANG81aad002017-04-25 11:07:19 +0800648 // Sum the PSS of tested library of all the children
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100649 size_t total_pss = 0;
650 for (int i=0; i<CHILDREN; ++i) {
651 size_t child_pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800652 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100653 total_pss += child_pss;
654 }
655 *pss_out = total_pss;
656
657 // Close pipes and wait for children to exit
658 for (int i=0; i<CHILDREN; ++i) {
659 ASSERT_NOERROR(close(childpipe[i]));
660 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800661 for (int i = 0; i < CHILDREN; ++i) {
662 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100663 }
664}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700665
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400666std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
667 uint64_t addr = reinterpret_cast<uint64_t>(ptr);
668 std::string found_name = "<not found>";
669
670 EXPECT_TRUE(android::procinfo::ReadMapFile(
671 "/proc/self/maps",
672 [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
673 if (addr >= start && addr < end) {
674 found_name = name;
675 }
676 }));
677
678 return found_name;
679}
680
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700681// Testing namespaces
682static const char* g_public_lib = "libnstest_public.so";
683
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800684// These are libs shared with default namespace
685static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
686
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700687TEST(dlext, ns_smoke) {
688 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800689 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700690
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800691 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
692 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
693 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
694 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700695
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700696 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800697 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700698 ASSERT_TRUE(handle_public != nullptr) << dlerror();
699
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800700 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700701
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800702 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700703 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800704 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800705 ASSERT_TRUE(handle_public == nullptr);
706 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
707 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
708
709 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700710
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800711 // create "public namespace", share limited set of public libraries with
712
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800713 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800714 android_create_namespace("private",
715 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700716 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800717 ANDROID_NAMESPACE_TYPE_REGULAR,
718 nullptr,
719 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700720 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800721 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700722
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800723 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800724 android_create_namespace("private_isolated",
725 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700726 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800727 ANDROID_NAMESPACE_TYPE_ISOLATED,
728 nullptr,
729 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700730 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800731 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700732
733 // This should not have affect search path for default namespace:
734 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
735 void* handle = dlopen(g_public_lib, RTLD_NOW);
736 ASSERT_TRUE(handle != nullptr) << dlerror();
737 dlclose(handle);
738
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700739 // dlopen for a public library using an absolute path should work
740 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700741 android_dlextinfo extinfo;
742 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700743 extinfo.library_namespace = ns2;
744 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
745 ASSERT_TRUE(handle != nullptr) << dlerror();
746 ASSERT_TRUE(handle == handle_public);
747
748 dlclose(handle);
749
750 // 1.1 even if it wasn't loaded before
751 dlclose(handle_public);
752
753 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
754 ASSERT_TRUE(handle_public == nullptr);
755 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
756 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
757
758 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
759 ASSERT_TRUE(handle != nullptr) << dlerror();
760
761 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
762 ASSERT_TRUE(handle == handle_public);
763
764 dlclose(handle);
765
766 // 2. And for regular namespaces (make sure it does not load second copy of the library)
767 extinfo.library_namespace = ns1;
768 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
769 ASSERT_TRUE(handle != nullptr) << dlerror();
770 ASSERT_TRUE(handle == handle_public);
771
772 dlclose(handle);
773
774 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
775 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
776 dlclose(handle_public);
777
778 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
779 ASSERT_TRUE(handle_public == nullptr);
780 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
781 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
782
783 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
784 ASSERT_TRUE(handle != nullptr) << dlerror();
785
786 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
787
788 ASSERT_TRUE(handle != handle_public);
789
790 dlclose(handle);
791
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700792 extinfo.library_namespace = ns1;
793
794 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
795 ASSERT_TRUE(handle1 != nullptr) << dlerror();
796
797 extinfo.library_namespace = ns2;
798 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
799 ASSERT_TRUE(handle2 != nullptr) << dlerror();
800
801 ASSERT_TRUE(handle1 != handle2);
802
803 typedef const char* (*fn_t)();
804
805 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
806 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
807 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
808 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
809
810 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
811 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
812
813 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
814
815 fn_t ns_get_private_extern_string1 =
816 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
817 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
818 fn_t ns_get_private_extern_string2 =
819 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
820 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
821
822 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
823 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
824
825 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
826
827 fn_t ns_get_public_extern_string1 =
828 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
829 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
830 fn_t ns_get_public_extern_string2 =
831 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
832 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
833
834 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
835 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
836
837 // and now check that dlopen() does the right thing in terms of preserving namespace
838 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
839 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
840 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
841 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
842
843 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
844 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
845
846 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
847
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800848 // Check that symbols from non-shared libraries a shared library depends on are not visible
849 // from original namespace.
850
851 fn_t ns_get_internal_extern_string =
852 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
853 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
854 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
855 "ns_get_internal_extern_string() expected to return null but returns \"" <<
856 ns_get_internal_extern_string() << "\"";
857
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700858 dlclose(handle1);
859
860 // Check if handle2 is still alive (and well)
861 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
862 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
863 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
864 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
865
866 dlclose(handle2);
867}
868
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700869TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700870 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700871
872 int tmpfd = TEMP_FAILURE_RETRY(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700873 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700874
875 // Ignore kernels without O_TMPFILE flag support
876 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
877 return;
878 }
879
880 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
881
882 android_namespace_t* ns =
883 android_create_namespace("testing-o_tmpfile",
884 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700885 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700886 ANDROID_NAMESPACE_TYPE_ISOLATED,
887 nullptr,
888 nullptr);
889
890 ASSERT_DL_NOTNULL(ns);
891
892 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
893
894 std::string content;
895 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
896 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
897
898 android_dlextinfo extinfo;
899 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
900 extinfo.library_fd = tmpfd;
901 extinfo.library_namespace = ns;
902
903 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
904
905 ASSERT_DL_NOTNULL(handle);
906
907 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
908 ASSERT_DL_NOTNULL(taxicab_number);
909 EXPECT_EQ(1729U, *taxicab_number);
910 dlclose(handle);
911}
912
913TEST(dlext, dlopen_ext_use_memfd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700914 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700915
916 // create memfd
917 int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
918 if (memfd == -1 && errno == ENOSYS) {
919 return;
920 }
921
922 ASSERT_TRUE(memfd != -1) << strerror(errno);
923
924 // Check st.f_type is TMPFS_MAGIC for memfd
925 struct statfs st;
926 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
927 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
928
929 android_namespace_t* ns =
930 android_create_namespace("testing-memfd",
931 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700932 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700933 ANDROID_NAMESPACE_TYPE_ISOLATED,
934 nullptr,
935 nullptr);
936
937 ASSERT_DL_NOTNULL(ns);
938
939 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
940
941 // read file into memfd backed one.
942 std::string content;
943 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
944 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
945
946 android_dlextinfo extinfo;
947 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
948 extinfo.library_fd = memfd;
949 extinfo.library_namespace = ns;
950
951 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
952
953 ASSERT_DL_NOTNULL(handle);
954
955 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
956 ASSERT_DL_NOTNULL(taxicab_number);
957 EXPECT_EQ(1729U, *taxicab_number);
958 dlclose(handle);
959}
960
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800961TEST(dlext, ns_symbol_visibilty_one_namespace) {
962 static const char* root_lib = "libnstest_root.so";
963 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
964
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700965 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
966 GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800967
968 android_namespace_t* ns =
969 android_create_namespace("one",
970 nullptr,
971 ns_search_path.c_str(),
972 ANDROID_NAMESPACE_TYPE_ISOLATED,
973 nullptr,
974 nullptr);
975
976 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
977
978 android_dlextinfo extinfo;
979 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
980 extinfo.library_namespace = ns;
981
982 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
983 ASSERT_TRUE(handle != nullptr) << dlerror();
984
985 typedef const char* (*fn_t)();
986
987 // Check that relocation worked correctly
988 fn_t ns_get_internal_extern_string =
989 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
990 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
991 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
992
993 fn_t internal_extern_string_fn =
994 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
995 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
996 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
997}
998
999TEST(dlext, ns_symbol_visibilty_between_namespaces) {
1000 static const char* root_lib = "libnstest_root.so";
1001 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1002
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001003 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1004 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001005
1006 android_namespace_t* ns_public =
1007 android_create_namespace("public",
1008 nullptr,
1009 public_ns_search_path.c_str(),
1010 ANDROID_NAMESPACE_TYPE_ISOLATED,
1011 nullptr,
1012 nullptr);
1013
1014 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1015
1016 android_namespace_t* ns_private =
1017 android_create_namespace("private",
1018 nullptr,
1019 private_ns_search_path.c_str(),
1020 ANDROID_NAMESPACE_TYPE_ISOLATED,
1021 nullptr,
1022 nullptr);
1023
1024 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1025 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1026
1027 android_dlextinfo extinfo;
1028 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1029 extinfo.library_namespace = ns_private;
1030
1031 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1032 ASSERT_TRUE(handle != nullptr) << dlerror();
1033
1034 typedef const char* (*fn_t)();
1035
1036 // Check that relocation worked correctly
1037 fn_t ns_get_internal_extern_string =
1038 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1039 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1040 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
1041 "ns_get_internal_extern_string() expected to return null but returns \"" <<
1042 ns_get_internal_extern_string() << "\"";
1043
1044 fn_t internal_extern_string_fn =
1045 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1046 ASSERT_TRUE(internal_extern_string_fn == nullptr);
1047 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
1048}
1049
1050TEST(dlext, ns_unload_between_namespaces) {
1051 static const char* root_lib = "libnstest_root.so";
1052 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1053
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001054 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1055 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001056
1057 android_namespace_t* ns_public =
1058 android_create_namespace("public",
1059 nullptr,
1060 public_ns_search_path.c_str(),
1061 ANDROID_NAMESPACE_TYPE_ISOLATED,
1062 nullptr,
1063 nullptr);
1064
1065 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1066
1067 android_namespace_t* ns_private =
1068 android_create_namespace("private",
1069 nullptr,
1070 private_ns_search_path.c_str(),
1071 ANDROID_NAMESPACE_TYPE_ISOLATED,
1072 nullptr,
1073 nullptr);
1074
1075 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1076 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1077
1078 android_dlextinfo extinfo;
1079 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1080 extinfo.library_namespace = ns_private;
1081
1082 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1083 ASSERT_TRUE(handle != nullptr) << dlerror();
1084
1085 dlclose(handle);
1086 // Check that root_lib was unloaded
1087 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1088 ASSERT_TRUE(handle == nullptr);
1089 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1090 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1091
1092 // Check that shared library was unloaded in public ns
1093 extinfo.library_namespace = ns_public;
1094 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1095 ASSERT_TRUE(handle == nullptr);
1096 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1097 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1098}
1099
dimitry965d06d2017-11-28 16:03:07 +01001100TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1101 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1102
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001103 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1104 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001105
1106 android_namespace_t* ns_public =
1107 android_create_namespace("public",
1108 nullptr,
1109 public_ns_search_path.c_str(),
1110 ANDROID_NAMESPACE_TYPE_ISOLATED,
1111 nullptr,
1112 nullptr);
1113
1114 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1115
1116 android_namespace_t* ns_private =
1117 android_create_namespace("private",
1118 nullptr,
1119 private_ns_search_path.c_str(),
1120 ANDROID_NAMESPACE_TYPE_ISOLATED,
1121 nullptr,
1122 nullptr);
1123
1124 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1125 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1126
1127 android_dlextinfo extinfo;
1128 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1129 extinfo.library_namespace = ns_private;
1130
1131 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1132 RTLD_NOW,
1133 &extinfo);
1134 ASSERT_TRUE(handle == nullptr);
1135 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1136 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1137 dlerror());
1138}
1139
1140TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1141 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1142
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001143 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1144 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001145
1146 android_namespace_t* ns_public =
1147 android_create_namespace("public",
1148 nullptr,
1149 public_ns_search_path.c_str(),
1150 ANDROID_NAMESPACE_TYPE_ISOLATED,
1151 nullptr,
1152 nullptr);
1153
1154 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1155
1156 android_namespace_t* ns_private =
1157 android_create_namespace("private",
1158 nullptr,
1159 private_ns_search_path.c_str(),
1160 ANDROID_NAMESPACE_TYPE_ISOLATED,
1161 nullptr,
1162 nullptr);
1163
1164 ASSERT_TRUE(android_link_namespaces(ns_private,
1165 ns_public,
1166 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1167 ) << dlerror();
1168 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1169
1170 android_dlextinfo extinfo;
1171 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1172 extinfo.library_namespace = ns_private;
1173
1174 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1175 ASSERT_TRUE(handle == nullptr);
1176 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1177 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1178 dlerror());
1179}
1180
Jiyong Park37b91af2017-05-05 22:07:05 +09001181TEST(dlext, ns_greylist_enabled) {
Dimitry Ivanov18623142017-02-21 13:41:08 -08001182 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1183
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001184 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov18623142017-02-21 13:41:08 -08001185
1186 android_namespace_t* ns =
1187 android_create_namespace("namespace",
1188 nullptr,
1189 ns_search_path.c_str(),
Jiyong Park37b91af2017-05-05 22:07:05 +09001190 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
Dimitry Ivanov18623142017-02-21 13:41:08 -08001191 nullptr,
1192 nullptr);
1193
1194 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1195
1196 android_dlextinfo extinfo;
1197 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1198 extinfo.library_namespace = ns;
1199
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001200 // An app targeting M can open libnativehelper.so because it's on the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001201 android_set_application_target_sdk_version(__ANDROID_API_M__);
1202 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1203 ASSERT_TRUE(handle != nullptr) << dlerror();
1204
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001205 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1206 void* dlsym_ptr = dlsym(handle, "dlsym");
1207 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1208 ASSERT_EQ(&dlsym, dlsym_ptr);
1209
Dimitry Ivanov18623142017-02-21 13:41:08 -08001210 dlclose(handle);
1211
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001212 // An app targeting N no longer has the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001213 android_set_application_target_sdk_version(__ANDROID_API_N__);
1214 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1215 ASSERT_TRUE(handle == nullptr);
1216 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1217}
1218
Jiyong Park37b91af2017-05-05 22:07:05 +09001219TEST(dlext, ns_greylist_disabled_by_default) {
1220 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1221
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001222 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Jiyong Park37b91af2017-05-05 22:07:05 +09001223
1224 android_namespace_t* ns =
1225 android_create_namespace("namespace",
1226 nullptr,
1227 ns_search_path.c_str(),
1228 ANDROID_NAMESPACE_TYPE_ISOLATED,
1229 nullptr,
1230 nullptr);
1231
1232 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1233
1234 android_dlextinfo extinfo;
1235 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1236 extinfo.library_namespace = ns;
1237
1238 android_set_application_target_sdk_version(__ANDROID_API_M__);
1239 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1240 ASSERT_TRUE(handle == nullptr);
1241 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1242}
1243
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001244TEST(dlext, ns_cyclic_namespaces) {
1245 // Test that ns1->ns2->ns1 link does not break the loader
1246 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1247 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1248
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001249 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001250
1251 android_namespace_t* ns1 =
1252 android_create_namespace("ns1",
1253 nullptr,
1254 ns_search_path.c_str(),
1255 ANDROID_NAMESPACE_TYPE_ISOLATED,
1256 nullptr,
1257 nullptr);
1258
1259 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1260
1261 android_namespace_t* ns2 =
1262 android_create_namespace("ns1",
1263 nullptr,
1264 ns_search_path.c_str(),
1265 ANDROID_NAMESPACE_TYPE_ISOLATED,
1266 nullptr,
1267 nullptr);
1268
1269 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1270
1271 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1272 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1273
1274 android_dlextinfo extinfo;
1275 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1276 extinfo.library_namespace = ns1;
1277
1278 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1279 ASSERT_TRUE(handle == nullptr);
1280 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1281}
1282
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001283TEST(dlext, ns_isolated) {
1284 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001285 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001286
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001287 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001288 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001289 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1290
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001291 android_set_application_target_sdk_version(42U); // something > 23
1292
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001293 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001294
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001295 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001296 android_create_namespace("private",
1297 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001298 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001299 ANDROID_NAMESPACE_TYPE_REGULAR,
1300 nullptr,
1301 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001302 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001303 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001304
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001305 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001306 android_create_namespace("private_isolated1",
1307 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001308 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001309 ANDROID_NAMESPACE_TYPE_ISOLATED,
1310 nullptr,
1311 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001312 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001313 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001314
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001315 android_namespace_t* ns_isolated2 =
1316 android_create_namespace("private_isolated2",
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001317 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001318 nullptr,
1319 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001320 GetTestlibRoot().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001321 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001322 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001323 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001324
1325 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1326 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1327
1328 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001329 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001330
1331 // Load lib_private_external_path to default namespace
1332 // (it should remain invisible for the isolated namespaces after this)
1333 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1334 ASSERT_TRUE(handle != nullptr) << dlerror();
1335
1336 android_dlextinfo extinfo;
1337 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1338 extinfo.library_namespace = ns_not_isolated;
1339
1340 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1341 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1342
1343 extinfo.library_namespace = ns_isolated;
1344
1345 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1346 ASSERT_TRUE(handle2 == nullptr);
1347 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1348
1349 // Check dlopen by absolute path
1350 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1351 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001352 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001353 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001354 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001355
1356 extinfo.library_namespace = ns_isolated2;
1357
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001358 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001359 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001360 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1361 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001362
1363 // Check dlopen by absolute path
1364 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001365 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1366 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001367
1368 typedef const char* (*fn_t)();
1369 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1370 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1371
1372 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1373
1374 fn_t ns_get_private_extern_string =
1375 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1376 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1377
1378 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1379
1380 fn_t ns_get_public_extern_string =
1381 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1382 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1383
1384 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1385
1386 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1387 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1388
1389 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1390
1391 dlclose(handle1);
1392}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001393
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001394TEST(dlext, ns_shared) {
1395 static const char* root_lib = "libnstest_root_not_isolated.so";
1396 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001397
1398 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001399
Jiyong Park917d34a2017-08-31 14:07:13 +09001400 // create a parent namespace to use instead of the default namespace. This is
1401 // to make this test be independent from the configuration of the default
1402 // namespace.
1403 android_namespace_t* ns_parent =
1404 android_create_namespace("parent",
1405 nullptr,
1406 nullptr,
1407 ANDROID_NAMESPACE_TYPE_REGULAR,
1408 nullptr,
1409 nullptr);
1410 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1411 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1412
1413 android_dlextinfo extinfo;
1414 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1415 extinfo.library_namespace = ns_parent;
1416
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001417 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Jiyong Park917d34a2017-08-31 14:07:13 +09001418 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001419 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1420
1421 android_set_application_target_sdk_version(42U); // something > 23
1422
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001423 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001424
Jiyong Park917d34a2017-08-31 14:07:13 +09001425 // preload this library to the parent namespace to check if it
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001426 // is shared later on.
1427 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001428 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001429 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1430
Jiyong Park917d34a2017-08-31 14:07:13 +09001431 // create two child namespaces of 'ns_parent'. One with regular, the other
1432 // with isolated & shared.
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001433 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001434 android_create_namespace("private",
1435 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001436 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001437 ANDROID_NAMESPACE_TYPE_REGULAR,
1438 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001439 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001440 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001441 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1442 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001443
1444 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001445 android_create_namespace("private_isolated_shared",
1446 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001447 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001448 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001449 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001450 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001451 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001452 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1453 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001454
Jiyong Park917d34a2017-08-31 14:07:13 +09001455 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001456 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1457
1458 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001459 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001460
Jiyong Park917d34a2017-08-31 14:07:13 +09001461 // Load lib_private_external_path to the parent namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001462 // (it should remain invisible for the isolated namespaces after this)
Jiyong Park917d34a2017-08-31 14:07:13 +09001463 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001464 ASSERT_TRUE(handle != nullptr) << dlerror();
1465
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001466 extinfo.library_namespace = ns_not_isolated;
1467
1468 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1469 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1470
1471 extinfo.library_namespace = ns_isolated_shared;
1472
1473 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1474 ASSERT_TRUE(handle2 == nullptr);
1475 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1476
1477 // Check dlopen by absolute path
1478 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1479 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001480 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001481 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001482 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001483
1484 // load libnstest_root.so to shared namespace in order to check that everything is different
1485 // except shared libnstest_dlopened.so
1486
1487 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1488
1489 typedef const char* (*fn_t)();
1490 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1491 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1492 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1493 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1494
1495 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1496 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1497 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1498
1499 fn_t ns_get_private_extern_string =
1500 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1501 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1502 fn_t ns_get_private_extern_string_shared =
1503 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1504 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1505
1506 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1507 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1508 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1509
1510 fn_t ns_get_public_extern_string =
1511 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1512 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1513 fn_t ns_get_public_extern_string_shared =
1514 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1515 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1516
1517 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1518 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1519 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1520
1521 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1522 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1523 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1524 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1525 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1526 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1527
1528 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1529 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1530 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1531 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1532 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1533
1534 dlclose(handle1);
1535 dlclose(handle2);
1536}
1537
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001538TEST(dlext, ns_shared_links_and_paths) {
1539 // Create parent namespace (isolated, not shared)
1540 android_namespace_t* ns_isolated =
1541 android_create_namespace("private_isolated",
1542 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001543 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001544 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001545 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001546 nullptr);
1547 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1548 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1549
1550 // Create shared namespace with ns_isolated parent
1551 android_namespace_t* ns_shared =
1552 android_create_namespace("private_shared",
1553 nullptr,
1554 nullptr,
1555 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1556 nullptr,
1557 ns_isolated);
1558 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1559
1560 // 1. Load a library in ns_shared to check that it has inherited
1561 // search path and the link to the default namespace.
1562 android_dlextinfo extinfo;
1563 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1564 extinfo.library_namespace = ns_shared;
1565
1566 {
1567 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1568 ASSERT_TRUE(handle != nullptr) << dlerror();
1569 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1570 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1571 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1572
1573 dlclose(handle);
1574 }
1575 // 2. Load another test library by absolute path to check that
1576 // it has inherited permitted_when_isolated_path
1577 {
1578 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001579 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001580 RTLD_NOW,
1581 &extinfo);
1582
1583 ASSERT_TRUE(handle != nullptr) << dlerror();
1584 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1585 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1586 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1587
1588 dlclose(handle);
1589 }
1590
1591 // 3. Check that it is still isolated.
1592 {
1593 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001594 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001595 RTLD_NOW,
1596 &extinfo);
1597
1598 ASSERT_TRUE(handle == nullptr);
1599 }
1600}
1601
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001602TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001603 android_set_application_target_sdk_version(42U); // something > 23
1604
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001605 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001606
1607 // preload this library to the default namespace to check if it
1608 // is shared later on.
1609 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001610 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001611 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1612
1613 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001614 android_create_namespace("private_isolated_shared",
1615 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001616 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001617 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001618 nullptr,
1619 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001620 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001621 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001622
1623 // Check if "libnstest_dlopened.so" is loaded (and the same)
1624 android_dlextinfo extinfo;
1625 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1626 extinfo.library_namespace = ns_isolated_shared;
1627
1628 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1629 ASSERT_TRUE(handle != nullptr) << dlerror();
1630 ASSERT_TRUE(handle == handle_dlopened);
1631 dlclose(handle);
1632 dlclose(handle_dlopened);
1633
1634 // And now check that the library cannot be found by soname (and is no longer loaded)
1635 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1636 ASSERT_TRUE(handle == nullptr)
1637 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1638
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001639 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001640 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1641 ASSERT_TRUE(handle == nullptr)
1642 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1643
1644 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1645 ASSERT_TRUE(handle == nullptr)
1646 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1647
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001648 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001649 RTLD_NOW | RTLD_NOLOAD);
1650 ASSERT_TRUE(handle == nullptr)
1651 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1652
1653 // Now lets see if the soinfo area gets reused in the wrong way:
1654 // load a library to default namespace.
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001655 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001656 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1657 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1658
1659 // try to find it in shared namespace
1660 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1661 ASSERT_TRUE(handle == nullptr)
1662 << "Error: " << g_public_lib << " is accessible in shared namespace";
1663}
1664
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001665TEST(dlext, ns_isolated_rtld_global) {
1666 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001667 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001668
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001669 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001670
1671 android_namespace_t* ns1 =
1672 android_create_namespace("isolated1",
1673 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001674 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001675 ANDROID_NAMESPACE_TYPE_ISOLATED,
1676 lib_public_path.c_str(),
1677 nullptr);
1678 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001679 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001680
1681 android_namespace_t* ns2 =
1682 android_create_namespace("isolated2",
1683 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001684 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001685 ANDROID_NAMESPACE_TYPE_ISOLATED,
1686 lib_public_path.c_str(),
1687 nullptr);
1688 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001689 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001690
1691 android_dlextinfo extinfo;
1692 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1693 extinfo.library_namespace = ns1;
1694
1695 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1696 RTLD_GLOBAL,
1697 &extinfo);
1698
1699 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1700
1701 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001702 android_create_namespace("isolated1_child",
1703 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001704 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001705 ANDROID_NAMESPACE_TYPE_ISOLATED,
1706 nullptr,
1707 ns1);
1708
1709 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1710 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001711
1712 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1713 // attempt to use ns2 should result in dlerror()
1714
1715 // Check ns1_child first.
1716 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1717 extinfo.library_namespace = ns1_child;
1718
1719 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1720 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1721
1722 // now ns1
1723 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1724 extinfo.library_namespace = ns1;
1725
1726 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1727 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1728
1729 // and ns2 should fail
1730 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1731 extinfo.library_namespace = ns2;
1732
1733 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1734 ASSERT_TRUE(handle1 == nullptr);
1735 ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
1736}
1737
dimitry8db36a52017-10-23 15:10:10 +02001738TEST(dlext, ns_inaccessible_error_message) {
1739 // We set up 2 namespaces (a and b) and link a->b with a shared library
1740 // libtestshared.so. Then try to dlopen different library with the same
1741 // name from in namespace a. Note that library should not be accessible
1742 // in either namespace but since it's soname is in the list of shared libs
1743 // the linker will attempt to find it in linked namespace.
1744 //
1745 // Check the error message and make sure it mentions correct namespace name.
1746 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1747
1748 android_namespace_t* ns_a =
1749 android_create_namespace("ns_a",
1750 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001751 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001752 ANDROID_NAMESPACE_TYPE_ISOLATED,
1753 nullptr,
1754 nullptr);
1755 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1756 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1757
1758 android_namespace_t* ns_b =
1759 android_create_namespace("ns_b",
1760 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001761 GetTestlibRoot().c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001762 ANDROID_NAMESPACE_TYPE_ISOLATED,
1763 nullptr,
1764 nullptr);
1765 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1766 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1767
1768 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1769
1770 android_dlextinfo extinfo;
1771 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1772 extinfo.library_namespace = ns_a;
1773
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001774 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
dimitry8db36a52017-10-23 15:10:10 +02001775
1776 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1777 ASSERT_TRUE(handle == nullptr);
1778 std::string expected_dlerror =
1779 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1780 " is not accessible for the namespace \"ns_a\"",
1781 library_path.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001782 android::base::GetExecutablePath().c_str());
dimitry8db36a52017-10-23 15:10:10 +02001783 ASSERT_EQ(expected_dlerror, dlerror());
1784}
1785
dimitry321476a2018-01-29 15:32:37 +01001786extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1787 android_namespace_t* namespace_to);
1788
Logan Chien9ee45912018-01-18 12:05:09 +08001789TEST(dlext, ns_link_namespaces_invalid_arguments) {
1790 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1791
1792 android_namespace_t* ns =
1793 android_create_namespace("private",
1794 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001795 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001796 ANDROID_NAMESPACE_TYPE_REGULAR,
1797 nullptr,
1798 nullptr);
1799 ASSERT_TRUE(ns != nullptr) << dlerror();
1800
1801 // Test android_link_namespaces()
1802 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1803 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1804 dlerror());
1805
1806 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1807 ASSERT_STREQ("android_link_namespaces failed: "
1808 "error linking namespaces \"private\"->\"(default)\": "
1809 "the list of shared libraries is empty.", dlerror());
1810
1811 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1812 ASSERT_STREQ("android_link_namespaces failed: "
1813 "error linking namespaces \"private\"->\"(default)\": "
1814 "the list of shared libraries is empty.", dlerror());
1815
dimitry321476a2018-01-29 15:32:37 +01001816 // Test __loader_android_link_namespaces_all_libs()
1817 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001818 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1819 "error linking namespaces: namespace_from is null.", dlerror());
1820
dimitry321476a2018-01-29 15:32:37 +01001821 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
Logan Chien9ee45912018-01-18 12:05:09 +08001822 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1823 "error linking namespaces: namespace_from is null.", dlerror());
1824
dimitry321476a2018-01-29 15:32:37 +01001825 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001826 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1827 "error linking namespaces: namespace_to is null.", dlerror());
1828}
1829
1830TEST(dlext, ns_allow_all_shared_libs) {
1831 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1832
1833 android_namespace_t* ns_a =
1834 android_create_namespace("ns_a",
1835 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001836 (GetTestlibRoot() + "/ns_a").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001837 ANDROID_NAMESPACE_TYPE_ISOLATED,
1838 nullptr,
1839 nullptr);
1840 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1841 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1842
1843 android_namespace_t* ns_b =
1844 android_create_namespace("ns_b",
1845 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001846 (GetTestlibRoot() + "/ns_b").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001847 ANDROID_NAMESPACE_TYPE_ISOLATED,
1848 nullptr,
1849 nullptr);
1850 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1851 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1852
1853 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
dimitry321476a2018-01-29 15:32:37 +01001854 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
Logan Chien9ee45912018-01-18 12:05:09 +08001855
1856 // Load libs with android_dlopen_ext() from namespace b
1857 android_dlextinfo extinfo;
1858 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1859 extinfo.library_namespace = ns_b;
1860
1861 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1862 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1863
1864 void* ns_b_handle1_internal =
1865 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1866 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1867
1868 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1869 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1870
1871 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1872 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1873
1874 // Load libs with android_dlopen_ext() from namespace a
1875 extinfo.library_namespace = ns_a;
1876
1877 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1878 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1879
1880 void* ns_a_handle1_internal =
1881 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1882 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1883
1884 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1885 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1886
1887 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1888 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1889
1890 // Compare the dlopen handle
1891 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1892 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1893 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1894
1895 // Close libs
1896 dlclose(ns_b_handle1);
1897 dlclose(ns_b_handle2);
1898 dlclose(ns_b_handle3);
1899
1900 dlclose(ns_a_handle1);
1901 dlclose(ns_a_handle1_internal);
1902 dlclose(ns_a_handle2);
1903 dlclose(ns_a_handle3);
1904}
1905
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001906TEST(dlext, ns_anonymous) {
1907 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001908 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001909
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001910 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001911 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1912
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001913 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1914
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001915 ASSERT_TRUE(
1916 android_init_anonymous_namespace(shared_libs.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001917 (GetTestlibRoot() + "/private_namespace_libs").c_str())
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001918 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001919
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001920 android_namespace_t* ns =
1921 android_create_namespace("private",
1922 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001923 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001924 ANDROID_NAMESPACE_TYPE_REGULAR,
1925 nullptr,
1926 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001927
1928 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001929 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001930
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001931 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001932
1933 android_dlextinfo extinfo;
1934 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1935 extinfo.library_namespace = ns;
1936
1937 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1938 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1939 ASSERT_TRUE(handle != nullptr) << dlerror();
1940
1941 uintptr_t ns_get_dlopened_string_addr =
1942 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1943 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1944 typedef const char* (*fn_t)();
1945 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1946
1947 std::vector<map_record> maps;
1948 Maps::parse_maps(&maps);
1949
1950 uintptr_t addr_start = 0;
1951 uintptr_t addr_end = 0;
dimitry8eaf28d2017-10-11 10:04:14 +02001952 bool has_executable_segment = false;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001953 std::vector<map_record> maps_to_copy;
1954
1955 for (const auto& rec : maps) {
1956 if (rec.pathname == private_library_absolute_path) {
1957 if (addr_start == 0) {
1958 addr_start = rec.addr_start;
1959 }
1960 addr_end = rec.addr_end;
dimitry8eaf28d2017-10-11 10:04:14 +02001961 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001962
1963 maps_to_copy.push_back(rec);
1964 }
1965 }
1966
1967 // some sanity checks..
1968 ASSERT_TRUE(addr_start > 0);
1969 ASSERT_TRUE(addr_end > 0);
dimitry3b0a5b72018-06-06 11:11:25 +02001970 ASSERT_TRUE(maps_to_copy.size() > 0);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001971 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
1972 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
1973
dimitry8eaf28d2017-10-11 10:04:14 +02001974 if (!has_executable_segment) {
1975 // For some natively bridged environments this code might be missing
1976 // the executable flag. This is because the guest code is not supposed
1977 // to be executed directly and making it non-executable is more secure.
1978 // If this is the case we assume that the first segment is the one that
1979 // has this flag.
1980 ASSERT_TRUE((maps_to_copy[0].perms & PROT_WRITE) == 0);
1981 maps_to_copy[0].perms |= PROT_EXEC;
1982 }
1983
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001984 // copy
1985 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
1986 PROT_NONE, MAP_ANON | MAP_PRIVATE,
1987 -1, 0));
1988 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
1989
1990 for (const auto& rec : maps_to_copy) {
1991 uintptr_t offset = rec.addr_start - addr_start;
1992 size_t size = rec.addr_end - rec.addr_start;
1993 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
1994 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
1995 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
1996 ASSERT_TRUE(map != MAP_FAILED);
1997 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
1998 mprotect(map, size, rec.perms);
1999 }
2000
2001 // call the function copy
2002 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
2003 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
2004 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2005 ns_get_dlopened_string_anon());
2006
2007 // They should belong to different namespaces (private and anonymous)
2008 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2009 ns_get_dlopened_string_private());
2010
2011 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
2012}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002013
2014TEST(dlext, dlopen_handle_value_platform) {
2015 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2016 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
2017 << "dlopen should return odd value for the handle";
2018 dlclose(handle);
2019}
2020
2021TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08002022 android_set_application_target_sdk_version(__ANDROID_API_M__);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002023 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2024 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
2025 << "dlopen should return valid pointer";
2026 dlclose(handle);
2027}