blob: 293c17b4141bcc9324afd96df2cdb7036049886e [file] [log] [blame]
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <dlfcn.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080020#include <elf.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000021#include <errno.h>
22#include <fcntl.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080023#include <inttypes.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000024#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070027
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000028#include <android/dlext.h>
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -070029#include <android-base/file.h>
Zhenhua WANG81aad002017-04-25 11:07:19 +080030#include <android-base/strings.h>
Josh Gao16269572019-10-29 13:41:00 -070031#include <android-base/test_utils.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070032
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000033#include <sys/mman.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010034#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070035#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000036#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000037
Sandeep Patil4e02cc12019-01-21 14:22:05 -080038#include <meminfo/procmeminfo.h>
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040039#include <procinfo/process_map.h>
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -080040#include <ziparchive/zip_archive.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010041
Ryan Prichard22fa3dd2020-01-31 14:47:48 -080042#include "core_shared_libs.h"
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:
Yi Kong358603a2019-03-29 14:25:16 -070070 void SetUp() override {
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
Yi Kong358603a2019-03-29 14:25:16 -070081 void TearDown() override {
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;
Elliott Hughesb51bb502019-05-03 22:45:41 -0700137 ASSERT_EQ(0, FindEntry(handle, kLibZipSimpleZip, &zip_entry));
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800138 extinfo.library_fd_offset = zip_entry.offset;
139 CloseArchive(handle);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700140
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700141 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700142 ASSERT_DL_NOTNULL(handle_);
143
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700144 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
145 ASSERT_DL_NOTNULL(taxicab_number);
146 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700147}
148
149TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700150 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700151
152 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700153 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700154 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700155 extinfo.library_fd_offset = 17;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700156
157 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
158 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700159 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
160
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800161 // Test an address above 2^44, for http://b/18178121 .
162 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700163 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700164 ASSERT_TRUE(handle_ == nullptr);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800165 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
166
167 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
168 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
169 ASSERT_TRUE(handle_ == nullptr);
170 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
171
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700172 extinfo.library_fd_offset = 0;
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700173 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800174 ASSERT_TRUE(handle_ == nullptr);
Elliott Hughesa8971512018-06-27 14:39:06 -0700175 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700176
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -0800177 // Check if dlsym works after unsuccessful dlopen().
178 // Supply non-exiting one to make linker visit every soinfo.
179 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
180 ASSERT_TRUE(sym == nullptr);
181
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700182 close(extinfo.library_fd);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700183}
184
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800185TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700186 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700187 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800188 // This offset will not be used, so it doesn't matter.
189 extinfo.library_fd_offset = 0;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700190
191 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
192 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700193 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 -0700194}
195
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700196TEST(dlext, android_dlopen_ext_force_load_smoke) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700197 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
198 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700199 // 1. Open actual file
200 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
201 ASSERT_DL_NOTNULL(handle);
202 // 2. Open link with force_load flag set
203 android_dlextinfo extinfo;
204 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700205 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700206 ASSERT_DL_NOTNULL(handle2);
207 ASSERT_TRUE(handle != handle2);
208
209 dlclose(handle2);
210 dlclose(handle);
211}
212
213TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700214 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
215 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700216 // Check if soname lookup still returns already loaded library
217 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700218 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700219 ASSERT_DL_NOTNULL(handle);
220
221 android_dlextinfo extinfo;
222 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
223
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700224 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700225 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
226
227 ASSERT_DL_NOTNULL(handle2);
228 ASSERT_TRUE(handle == handle2);
229
230 dlclose(handle2);
231 dlclose(handle);
232}
233
Elliott Hughes95c6cd72019-12-20 13:26:14 -0800234TEST(dlfcn, dlopen_from_nullptr_android_api_level_28) {
Victor Chang6cb719f2019-02-06 17:19:10 +0000235 // Regression test for http://b/123972211. Testing dlopen(nullptr) when target sdk is P
Elliott Hughes95c6cd72019-12-20 13:26:14 -0800236 android_set_application_target_sdk_version(28);
Victor Chang6cb719f2019-02-06 17:19:10 +0000237 ASSERT_TRUE(dlopen(nullptr, RTLD_NOW) != nullptr);
238}
239
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700240TEST(dlfcn, dlopen_from_zip_absolute_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700241 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700242 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700243
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700244 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700245 ASSERT_TRUE(handle != nullptr) << dlerror();
246
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700247 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
248 ASSERT_DL_NOTNULL(taxicab_number);
249 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700250
251 dlclose(handle);
252}
253
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700254TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700255 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700256 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700257
258 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
259
260 ASSERT_TRUE(handle != nullptr) << dlerror();
261
262 typedef void *(* dlopen_b_fn)();
263 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
264 ASSERT_TRUE(fn != nullptr) << dlerror();
265
266 void *p = fn();
267 ASSERT_TRUE(p != nullptr) << dlerror();
268
269 dlclose(p);
270 dlclose(handle);
271}
272
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700273TEST(dlfcn, dlopen_from_zip_ld_library_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700274 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700275 const std::string lib_path = GetTestlibRoot() + lib_zip_path + "!/libdir";
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700276
277 typedef void (*fn_t)(const char*);
278 fn_t android_update_LD_LIBRARY_PATH =
279 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
280
281 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
282
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700283 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700284 ASSERT_TRUE(handle == nullptr);
285
286 android_update_LD_LIBRARY_PATH(lib_path.c_str());
287
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700288 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700289 ASSERT_TRUE(handle != nullptr) << dlerror();
290
291 int (*fn)(void);
292 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
293 ASSERT_TRUE(fn != nullptr);
294 EXPECT_EQ(4, fn());
295
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800296 uint32_t* taxicab_number =
297 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700298 ASSERT_DL_NOTNULL(taxicab_number);
299 EXPECT_EQ(1729U, *taxicab_number);
300
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700301 dlclose(handle);
302}
303
304
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000305TEST_F(DlExtTest, Reserved) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700306 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000307 ASSERT_TRUE(start != MAP_FAILED);
308 android_dlextinfo extinfo;
309 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
310 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700311 extinfo.reserved_size = kLibSize;
312 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000313 ASSERT_DL_NOTNULL(handle_);
314 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
315 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700316 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000317 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700318 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000319 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800320
321 // Check that after dlclose reserved address space is unmapped (and can be reused)
322 dlclose(handle_);
323 handle_ = nullptr;
324
325 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
326 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000327}
328
329TEST_F(DlExtTest, ReservedTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800330 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000331 ASSERT_TRUE(start != MAP_FAILED);
332 android_dlextinfo extinfo;
333 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
334 extinfo.reserved_addr = start;
335 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700336 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700337 EXPECT_EQ(nullptr, handle_);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000338}
339
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400340TEST_F(DlExtTest, ReservedRecursive) {
341 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
342 ASSERT_TRUE(start != MAP_FAILED);
343 android_dlextinfo extinfo;
344 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
345 extinfo.reserved_addr = start;
346 extinfo.reserved_size = kLibSize;
347 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
348 ASSERT_DL_NOTNULL(handle_);
349
350 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
351 ASSERT_DL_NOTNULL(f);
352 EXPECT_GE(reinterpret_cast<void*>(f), start);
353 EXPECT_LT(reinterpret_cast<void*>(f),
354 reinterpret_cast<char*>(start) + kLibSize);
355 EXPECT_EQ(4, f());
356
357 f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
358 ASSERT_DL_NOTNULL(f);
359 EXPECT_GE(reinterpret_cast<void*>(f), start);
360 EXPECT_LT(reinterpret_cast<void*>(f),
361 reinterpret_cast<char*>(start) + kLibSize);
362 EXPECT_EQ(8, f());
363
364 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
365 ASSERT_DL_NOTNULL(taxicab_number);
Peter Collingbourne191ecdc2019-08-07 19:06:00 -0700366 // Untag the pointer so that it can be compared with start, which will be untagged.
367 void* addr = reinterpret_cast<void*>(untag_address(taxicab_number));
368 EXPECT_GE(addr, start);
369 EXPECT_LT(addr, reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400370 EXPECT_EQ(1729U, *taxicab_number);
371}
372
373TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
Yi Kong1e7a1502019-03-14 16:25:45 -0700374 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400375 ASSERT_TRUE(start != MAP_FAILED);
376 android_dlextinfo extinfo;
377 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
378 extinfo.reserved_addr = start;
Yi Kong1e7a1502019-03-14 16:25:45 -0700379 extinfo.reserved_size = PAGE_SIZE;
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400380 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
381 EXPECT_EQ(nullptr, handle_);
382}
383
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000384TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700385 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000386 ASSERT_TRUE(start != MAP_FAILED);
387 android_dlextinfo extinfo;
388 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
389 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700390 extinfo.reserved_size = kLibSize;
391 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000392 ASSERT_DL_NOTNULL(handle_);
393 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
394 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700395 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000396 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700397 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000398 EXPECT_EQ(4, f());
399}
400
401TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800402 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000403 ASSERT_TRUE(start != MAP_FAILED);
404 android_dlextinfo extinfo;
405 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
406 extinfo.reserved_addr = start;
407 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700408 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000409 ASSERT_DL_NOTNULL(handle_);
410 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
411 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700412 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
413 (reinterpret_cast<void*>(f) >=
414 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000415 EXPECT_EQ(4, f());
416}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000417
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100418class DlExtRelroSharingTest : public DlExtTest {
419protected:
Yi Kong358603a2019-03-29 14:25:16 -0700420 void SetUp() override {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100421 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700422 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100423 ASSERT_TRUE(start != MAP_FAILED);
424 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
425 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700426 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100427 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000428 }
429
Yi Kong358603a2019-03-29 14:25:16 -0700430 void TearDown() override {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100431 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100432 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000433
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400434 void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
Elliott Hughes5cec3772018-01-19 15:45:23 -0800435 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100436 ASSERT_NOERROR(relro_fd);
437
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400438 if (recursive) {
439 extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
440 }
441
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100442 pid_t pid = fork();
443 if (pid == 0) {
444 // child process
445 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
446 extinfo_.relro_fd = relro_fd;
447 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700448 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100449 fprintf(stderr, "in child: %s\n", dlerror());
450 exit(1);
451 }
Torne (Richard Coles)fa9f7f22019-04-02 17:04:42 -0400452 fn f = reinterpret_cast<fn>(dlsym(handle, "getRandomNumber"));
453 ASSERT_DL_NOTNULL(f);
454 EXPECT_EQ(4, f());
455
456 if (recursive) {
457 fn f = reinterpret_cast<fn>(dlsym(handle, "getBiggerRandomNumber"));
458 ASSERT_DL_NOTNULL(f);
459 EXPECT_EQ(8, f());
460 }
461
462 uint32_t* taxicab_number =
463 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
464 ASSERT_DL_NOTNULL(taxicab_number);
465 EXPECT_EQ(1729U, *taxicab_number);
466 exit(testing::Test::HasFailure());
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100467 }
468
469 // continuing in parent
470 ASSERT_NOERROR(close(relro_fd));
471 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800472 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100473
474 // reopen file for reading so it can be used
Elliott Hughes5cec3772018-01-19 15:45:23 -0800475 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100476 ASSERT_NOERROR(relro_fd);
477 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
478 extinfo_.relro_fd = relro_fd;
479 }
480
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400481 void TryUsingRelro(const char* lib, bool recursive) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100482 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
483 ASSERT_DL_NOTNULL(handle_);
484 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
485 ASSERT_DL_NOTNULL(f);
486 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700487
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400488 if (recursive) {
489 fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
490 ASSERT_DL_NOTNULL(f);
491 EXPECT_EQ(8, f());
492 }
493
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800494 uint32_t* taxicab_number =
495 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700496 ASSERT_DL_NOTNULL(taxicab_number);
497 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100498 }
499
Zhenhua WANG81aad002017-04-25 11:07:19 +0800500 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
501 size_t* pss_out);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100502
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400503 std::string FindMappingName(void* ptr);
504
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100505 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100506};
507
508TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800509 TemporaryFile tf; // Use tf to get an unique filename.
510 ASSERT_NOERROR(close(tf.fd));
511
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400512 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
513 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
514 void* relro_data = dlsym(handle_, "lots_of_relro");
515 ASSERT_DL_NOTNULL(relro_data);
516 EXPECT_EQ(tf.path, FindMappingName(relro_data));
517
518 // Use destructor of tf to close and unlink the file.
519 tf.fd = extinfo_.relro_fd;
520}
521
522TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
523 TemporaryFile tf; // Use tf to get an unique filename.
524 ASSERT_NOERROR(close(tf.fd));
525
526 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
527 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
528 void* relro_data = dlsym(handle_, "lots_of_relro");
529 ASSERT_DL_NOTNULL(relro_data);
530 EXPECT_EQ(tf.path, FindMappingName(relro_data));
531 void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
532 ASSERT_DL_NOTNULL(recursive_relro_data);
533 EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
534
Yabin Cui294d1e22014-12-07 20:43:37 -0800535
536 // Use destructor of tf to close and unlink the file.
537 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100538}
539
Torne (Richard Coles)5d103742019-04-11 12:25:06 -0400540TEST_F(DlExtRelroSharingTest, CheckRelroSizes) {
541 TemporaryFile tf1, tf2;
542 ASSERT_NOERROR(close(tf1.fd));
543 ASSERT_NOERROR(close(tf2.fd));
544
545 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf1.path, false));
546 struct stat no_recursive;
547 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &no_recursive));
548 tf1.fd = extinfo_.relro_fd;
549
550 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf2.path, true));
551 struct stat with_recursive;
552 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &with_recursive));
553 tf2.fd = extinfo_.relro_fd;
554
555 // RELRO file should end up bigger when we use the recursive flag, since it
556 // includes data for more than one library.
557 ASSERT_GT(with_recursive.st_size, no_recursive.st_size);
558}
559
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100560TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800561 TemporaryFile tf; // // Use tf to get an unique filename.
562 ASSERT_NOERROR(close(tf.fd));
563
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400564 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
565 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800566
567 // Use destructor of tf to close and unlink the file.
568 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100569}
570
571TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400572 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000573}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100574
575TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800576 if (geteuid() != 0) GTEST_SKIP() << "This test must be run as root";
Dan Albert69fb9f32014-09-03 11:30:21 -0700577
Yabin Cui294d1e22014-12-07 20:43:37 -0800578 TemporaryFile tf; // Use tf to get an unique filename.
579 ASSERT_NOERROR(close(tf.fd));
580
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400581 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800582
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100583 int pipefd[2];
584 ASSERT_NOERROR(pipe(pipefd));
585
586 size_t without_sharing, with_sharing;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -0800587 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
588 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
Zhenhua WANG81aad002017-04-25 11:07:19 +0800589 ASSERT_LT(with_sharing, without_sharing);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100590
Zhenhua WANG81aad002017-04-25 11:07:19 +0800591 // We expect the sharing to save at least 50% of the library's total PSS.
592 // In practice it saves 80%+ for this library in the test.
593 size_t pss_saved = without_sharing - with_sharing;
594 size_t expected_min_saved = without_sharing / 2;
595
596 EXPECT_LT(expected_min_saved, pss_saved);
Yabin Cui294d1e22014-12-07 20:43:37 -0800597
598 // Use destructor of tf to close and unlink the file.
599 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100600}
601
Zhenhua WANG81aad002017-04-25 11:07:19 +0800602void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
603 size_t* total_pss) {
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800604 android::meminfo::ProcMemInfo proc_mem(pid);
Christopher Ferris89b658c2019-10-10 13:27:54 -0700605 const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats();
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800606 ASSERT_GT(maps.size(), 0UL);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100607
Zhenhua WANG81aad002017-04-25 11:07:19 +0800608 // Calculate total PSS of the library.
609 *total_pss = 0;
610 bool saw_relro_file = false;
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800611 for (auto& vma : maps) {
612 if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
613 if (vma.name == relro_file) {
614 saw_relro_file = true;
615 }
Zhenhua WANG81aad002017-04-25 11:07:19 +0800616
Christopher Ferris89b658c2019-10-10 13:27:54 -0700617 android::meminfo::Vma update_vma(vma);
618 ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma));
619 *total_pss += update_vma.usage.pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800620 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100621 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100622
Zhenhua WANG81aad002017-04-25 11:07:19 +0800623 if (shared_relro) ASSERT_TRUE(saw_relro_file);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100624}
625
Zhenhua WANG81aad002017-04-25 11:07:19 +0800626void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
627 bool share_relro, size_t* pss_out) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100628 const int CHILDREN = 20;
629
630 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800631 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100632 int childpipe[CHILDREN];
633 for (int i=0; i<CHILDREN; ++i) {
634 char read_buf;
635 int child_done_pipe[2], parent_done_pipe[2];
636 ASSERT_NOERROR(pipe(child_done_pipe));
637 ASSERT_NOERROR(pipe(parent_done_pipe));
638
639 pid_t child = fork();
640 if (child == 0) {
641 // close the 'wrong' ends of the pipes in the child
642 close(child_done_pipe[0]);
643 close(parent_done_pipe[1]);
644
645 // open the library
646 void* handle;
647 if (share_relro) {
648 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
649 } else {
650 handle = dlopen(lib, RTLD_NOW);
651 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700652 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100653 fprintf(stderr, "in child: %s\n", dlerror());
654 exit(1);
655 }
656
657 // close write end of child_done_pipe to signal the parent that we're done.
658 close(child_done_pipe[1]);
659
660 // wait for the parent to close parent_done_pipe, then exit
661 read(parent_done_pipe[0], &read_buf, 1);
662 exit(0);
663 }
664
665 ASSERT_NOERROR(child);
666
667 // close the 'wrong' ends of the pipes in the parent
668 close(child_done_pipe[1]);
669 close(parent_done_pipe[0]);
670
671 // wait for the child to be done
672 read(child_done_pipe[0], &read_buf, 1);
673 close(child_done_pipe[0]);
674
675 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800676 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100677 childpipe[i] = parent_done_pipe[1];
678 }
679
Zhenhua WANG81aad002017-04-25 11:07:19 +0800680 // Sum the PSS of tested library of all the children
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100681 size_t total_pss = 0;
682 for (int i=0; i<CHILDREN; ++i) {
683 size_t child_pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800684 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100685 total_pss += child_pss;
686 }
687 *pss_out = total_pss;
688
689 // Close pipes and wait for children to exit
690 for (int i=0; i<CHILDREN; ++i) {
691 ASSERT_NOERROR(close(childpipe[i]));
692 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800693 for (int i = 0; i < CHILDREN; ++i) {
694 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100695 }
696}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700697
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400698std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
699 uint64_t addr = reinterpret_cast<uint64_t>(ptr);
700 std::string found_name = "<not found>";
701
702 EXPECT_TRUE(android::procinfo::ReadMapFile(
703 "/proc/self/maps",
704 [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
705 if (addr >= start && addr < end) {
706 found_name = name;
707 }
708 }));
709
710 return found_name;
711}
712
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700713// Testing namespaces
714static const char* g_public_lib = "libnstest_public.so";
715
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800716// These are libs shared with default namespace
Ryan Prichard22fa3dd2020-01-31 14:47:48 -0800717static const std::string g_core_shared_libs = kCoreSharedLibs;
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800718
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700719TEST(dlext, ns_smoke) {
720 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800721 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700722
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800723 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
724 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
725 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
726 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700727
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700728 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800729 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700730 ASSERT_TRUE(handle_public != nullptr) << dlerror();
731
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800732 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700733
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800734 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700735 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800736 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800737 ASSERT_TRUE(handle_public == nullptr);
738 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
739 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
740
741 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700742
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800743 // create "public namespace", share limited set of public libraries with
744
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800745 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800746 android_create_namespace("private",
747 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700748 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800749 ANDROID_NAMESPACE_TYPE_REGULAR,
750 nullptr,
751 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700752 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800753 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700754
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800755 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800756 android_create_namespace("private_isolated",
757 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700758 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800759 ANDROID_NAMESPACE_TYPE_ISOLATED,
760 nullptr,
761 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700762 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800763 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700764
765 // This should not have affect search path for default namespace:
766 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
767 void* handle = dlopen(g_public_lib, RTLD_NOW);
768 ASSERT_TRUE(handle != nullptr) << dlerror();
769 dlclose(handle);
770
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700771 // dlopen for a public library using an absolute path should work
772 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700773 android_dlextinfo extinfo;
774 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700775 extinfo.library_namespace = ns2;
776 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
777 ASSERT_TRUE(handle != nullptr) << dlerror();
778 ASSERT_TRUE(handle == handle_public);
779
780 dlclose(handle);
781
782 // 1.1 even if it wasn't loaded before
783 dlclose(handle_public);
784
785 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
786 ASSERT_TRUE(handle_public == nullptr);
787 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
788 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
789
790 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
791 ASSERT_TRUE(handle != nullptr) << dlerror();
792
793 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
794 ASSERT_TRUE(handle == handle_public);
795
796 dlclose(handle);
797
798 // 2. And for regular namespaces (make sure it does not load second copy of the library)
799 extinfo.library_namespace = ns1;
800 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
801 ASSERT_TRUE(handle != nullptr) << dlerror();
802 ASSERT_TRUE(handle == handle_public);
803
804 dlclose(handle);
805
806 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
807 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
808 dlclose(handle_public);
809
810 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
811 ASSERT_TRUE(handle_public == nullptr);
812 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
813 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
814
815 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
816 ASSERT_TRUE(handle != nullptr) << dlerror();
817
818 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
819
820 ASSERT_TRUE(handle != handle_public);
821
822 dlclose(handle);
823
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700824 extinfo.library_namespace = ns1;
825
826 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
827 ASSERT_TRUE(handle1 != nullptr) << dlerror();
828
829 extinfo.library_namespace = ns2;
830 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
831 ASSERT_TRUE(handle2 != nullptr) << dlerror();
832
833 ASSERT_TRUE(handle1 != handle2);
834
835 typedef const char* (*fn_t)();
836
837 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
838 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
839 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
840 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
841
842 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
843 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
844
845 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
846
847 fn_t ns_get_private_extern_string1 =
848 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
849 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
850 fn_t ns_get_private_extern_string2 =
851 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
852 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
853
854 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
855 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
856
857 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
858
859 fn_t ns_get_public_extern_string1 =
860 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
861 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
862 fn_t ns_get_public_extern_string2 =
863 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
864 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
865
866 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
867 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
868
869 // and now check that dlopen() does the right thing in terms of preserving namespace
870 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
871 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
872 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
873 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
874
875 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
876 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
877
878 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
879
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800880 // Check that symbols from non-shared libraries a shared library depends on are not visible
881 // from original namespace.
882
883 fn_t ns_get_internal_extern_string =
884 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
885 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
886 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
887 "ns_get_internal_extern_string() expected to return null but returns \"" <<
888 ns_get_internal_extern_string() << "\"";
889
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700890 dlclose(handle1);
891
892 // Check if handle2 is still alive (and well)
893 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
894 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
895 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
896 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
897
898 dlclose(handle2);
899}
900
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700901TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700902 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700903
904 int tmpfd = TEMP_FAILURE_RETRY(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700905 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700906
907 // Ignore kernels without O_TMPFILE flag support
908 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
909 return;
910 }
911
912 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
913
914 android_namespace_t* ns =
915 android_create_namespace("testing-o_tmpfile",
916 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700917 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700918 ANDROID_NAMESPACE_TYPE_ISOLATED,
919 nullptr,
920 nullptr);
921
922 ASSERT_DL_NOTNULL(ns);
923
924 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
925
926 std::string content;
927 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
928 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
929
930 android_dlextinfo extinfo;
931 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
932 extinfo.library_fd = tmpfd;
933 extinfo.library_namespace = ns;
934
935 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
936
937 ASSERT_DL_NOTNULL(handle);
938
939 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
940 ASSERT_DL_NOTNULL(taxicab_number);
941 EXPECT_EQ(1729U, *taxicab_number);
942 dlclose(handle);
943}
944
945TEST(dlext, dlopen_ext_use_memfd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700946 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700947
948 // create memfd
Elliott Hughes3d24d2b2019-08-05 13:53:01 -0700949 int memfd = memfd_create("foobar", MFD_CLOEXEC);
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700950 if (memfd == -1 && errno == ENOSYS) {
951 return;
952 }
953
954 ASSERT_TRUE(memfd != -1) << strerror(errno);
955
956 // Check st.f_type is TMPFS_MAGIC for memfd
957 struct statfs st;
958 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
959 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
960
961 android_namespace_t* ns =
962 android_create_namespace("testing-memfd",
963 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700964 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700965 ANDROID_NAMESPACE_TYPE_ISOLATED,
966 nullptr,
967 nullptr);
968
969 ASSERT_DL_NOTNULL(ns);
970
971 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
972
973 // read file into memfd backed one.
974 std::string content;
975 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
976 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
977
978 android_dlextinfo extinfo;
979 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
980 extinfo.library_fd = memfd;
981 extinfo.library_namespace = ns;
982
983 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
984
985 ASSERT_DL_NOTNULL(handle);
986
987 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
988 ASSERT_DL_NOTNULL(taxicab_number);
989 EXPECT_EQ(1729U, *taxicab_number);
990 dlclose(handle);
991}
992
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800993TEST(dlext, ns_symbol_visibilty_one_namespace) {
994 static const char* root_lib = "libnstest_root.so";
995 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
996
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700997 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
998 GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800999
1000 android_namespace_t* ns =
1001 android_create_namespace("one",
1002 nullptr,
1003 ns_search_path.c_str(),
1004 ANDROID_NAMESPACE_TYPE_ISOLATED,
1005 nullptr,
1006 nullptr);
1007
1008 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1009
1010 android_dlextinfo extinfo;
1011 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1012 extinfo.library_namespace = ns;
1013
1014 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1015 ASSERT_TRUE(handle != nullptr) << dlerror();
1016
1017 typedef const char* (*fn_t)();
1018
1019 // Check that relocation worked correctly
1020 fn_t ns_get_internal_extern_string =
1021 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1022 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1023 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
1024
1025 fn_t internal_extern_string_fn =
1026 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1027 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
1028 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
1029}
1030
1031TEST(dlext, ns_symbol_visibilty_between_namespaces) {
1032 static const char* root_lib = "libnstest_root.so";
1033 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1034
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001035 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1036 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001037
1038 android_namespace_t* ns_public =
1039 android_create_namespace("public",
1040 nullptr,
1041 public_ns_search_path.c_str(),
1042 ANDROID_NAMESPACE_TYPE_ISOLATED,
1043 nullptr,
1044 nullptr);
1045
1046 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1047
1048 android_namespace_t* ns_private =
1049 android_create_namespace("private",
1050 nullptr,
1051 private_ns_search_path.c_str(),
1052 ANDROID_NAMESPACE_TYPE_ISOLATED,
1053 nullptr,
1054 nullptr);
1055
1056 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1057 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1058
1059 android_dlextinfo extinfo;
1060 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1061 extinfo.library_namespace = ns_private;
1062
1063 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1064 ASSERT_TRUE(handle != nullptr) << dlerror();
1065
1066 typedef const char* (*fn_t)();
1067
1068 // Check that relocation worked correctly
1069 fn_t ns_get_internal_extern_string =
1070 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1071 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1072 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
1073 "ns_get_internal_extern_string() expected to return null but returns \"" <<
1074 ns_get_internal_extern_string() << "\"";
1075
1076 fn_t internal_extern_string_fn =
1077 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1078 ASSERT_TRUE(internal_extern_string_fn == nullptr);
1079 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
1080}
1081
1082TEST(dlext, ns_unload_between_namespaces) {
1083 static const char* root_lib = "libnstest_root.so";
1084 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1085
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001086 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1087 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001088
1089 android_namespace_t* ns_public =
1090 android_create_namespace("public",
1091 nullptr,
1092 public_ns_search_path.c_str(),
1093 ANDROID_NAMESPACE_TYPE_ISOLATED,
1094 nullptr,
1095 nullptr);
1096
1097 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1098
1099 android_namespace_t* ns_private =
1100 android_create_namespace("private",
1101 nullptr,
1102 private_ns_search_path.c_str(),
1103 ANDROID_NAMESPACE_TYPE_ISOLATED,
1104 nullptr,
1105 nullptr);
1106
1107 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1108 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1109
1110 android_dlextinfo extinfo;
1111 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1112 extinfo.library_namespace = ns_private;
1113
1114 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1115 ASSERT_TRUE(handle != nullptr) << dlerror();
1116
1117 dlclose(handle);
1118 // Check that root_lib was unloaded
1119 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1120 ASSERT_TRUE(handle == nullptr);
1121 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1122 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1123
1124 // Check that shared library was unloaded in public ns
1125 extinfo.library_namespace = ns_public;
1126 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1127 ASSERT_TRUE(handle == nullptr);
1128 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1129 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1130}
1131
dimitry965d06d2017-11-28 16:03:07 +01001132TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1133 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1134
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001135 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1136 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001137
1138 android_namespace_t* ns_public =
1139 android_create_namespace("public",
1140 nullptr,
1141 public_ns_search_path.c_str(),
1142 ANDROID_NAMESPACE_TYPE_ISOLATED,
1143 nullptr,
1144 nullptr);
1145
1146 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1147
1148 android_namespace_t* ns_private =
1149 android_create_namespace("private",
1150 nullptr,
1151 private_ns_search_path.c_str(),
1152 ANDROID_NAMESPACE_TYPE_ISOLATED,
1153 nullptr,
1154 nullptr);
1155
1156 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1157 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1158
1159 android_dlextinfo extinfo;
1160 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1161 extinfo.library_namespace = ns_private;
1162
1163 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1164 RTLD_NOW,
1165 &extinfo);
1166 ASSERT_TRUE(handle == nullptr);
1167 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1168 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1169 dlerror());
1170}
1171
1172TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1173 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1174
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001175 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1176 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001177
1178 android_namespace_t* ns_public =
1179 android_create_namespace("public",
1180 nullptr,
1181 public_ns_search_path.c_str(),
1182 ANDROID_NAMESPACE_TYPE_ISOLATED,
1183 nullptr,
1184 nullptr);
1185
1186 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1187
1188 android_namespace_t* ns_private =
1189 android_create_namespace("private",
1190 nullptr,
1191 private_ns_search_path.c_str(),
1192 ANDROID_NAMESPACE_TYPE_ISOLATED,
1193 nullptr,
1194 nullptr);
1195
1196 ASSERT_TRUE(android_link_namespaces(ns_private,
1197 ns_public,
1198 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1199 ) << dlerror();
1200 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1201
1202 android_dlextinfo extinfo;
1203 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1204 extinfo.library_namespace = ns_private;
1205
1206 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1207 ASSERT_TRUE(handle == nullptr);
1208 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1209 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1210 dlerror());
1211}
1212
Jiyong Park37b91af2017-05-05 22:07:05 +09001213TEST(dlext, ns_greylist_enabled) {
Dimitry Ivanov18623142017-02-21 13:41:08 -08001214 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1215
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001216 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov18623142017-02-21 13:41:08 -08001217
1218 android_namespace_t* ns =
1219 android_create_namespace("namespace",
1220 nullptr,
1221 ns_search_path.c_str(),
Jiyong Park37b91af2017-05-05 22:07:05 +09001222 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
Dimitry Ivanov18623142017-02-21 13:41:08 -08001223 nullptr,
1224 nullptr);
1225
1226 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1227
1228 android_dlextinfo extinfo;
1229 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1230 extinfo.library_namespace = ns;
1231
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001232 // An app targeting M can open libnativehelper.so because it's on the greylist.
Elliott Hughes95c6cd72019-12-20 13:26:14 -08001233 android_set_application_target_sdk_version(23);
Dimitry Ivanov18623142017-02-21 13:41:08 -08001234 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1235 ASSERT_TRUE(handle != nullptr) << dlerror();
1236
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001237 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1238 void* dlsym_ptr = dlsym(handle, "dlsym");
1239 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1240 ASSERT_EQ(&dlsym, dlsym_ptr);
1241
Dimitry Ivanov18623142017-02-21 13:41:08 -08001242 dlclose(handle);
1243
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001244 // An app targeting N no longer has the greylist.
Elliott Hughes95c6cd72019-12-20 13:26:14 -08001245 android_set_application_target_sdk_version(24);
Dimitry Ivanov18623142017-02-21 13:41:08 -08001246 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1247 ASSERT_TRUE(handle == nullptr);
1248 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1249}
1250
Jiyong Park37b91af2017-05-05 22:07:05 +09001251TEST(dlext, ns_greylist_disabled_by_default) {
1252 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1253
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001254 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Jiyong Park37b91af2017-05-05 22:07:05 +09001255
1256 android_namespace_t* ns =
1257 android_create_namespace("namespace",
1258 nullptr,
1259 ns_search_path.c_str(),
1260 ANDROID_NAMESPACE_TYPE_ISOLATED,
1261 nullptr,
1262 nullptr);
1263
1264 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1265
1266 android_dlextinfo extinfo;
1267 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1268 extinfo.library_namespace = ns;
1269
Elliott Hughes95c6cd72019-12-20 13:26:14 -08001270 android_set_application_target_sdk_version(23);
Jiyong Park37b91af2017-05-05 22:07:05 +09001271 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1272 ASSERT_TRUE(handle == nullptr);
1273 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1274}
1275
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001276TEST(dlext, ns_cyclic_namespaces) {
1277 // Test that ns1->ns2->ns1 link does not break the loader
1278 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1279 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1280
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001281 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001282
1283 android_namespace_t* ns1 =
1284 android_create_namespace("ns1",
1285 nullptr,
1286 ns_search_path.c_str(),
1287 ANDROID_NAMESPACE_TYPE_ISOLATED,
1288 nullptr,
1289 nullptr);
1290
1291 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1292
1293 android_namespace_t* ns2 =
1294 android_create_namespace("ns1",
1295 nullptr,
1296 ns_search_path.c_str(),
1297 ANDROID_NAMESPACE_TYPE_ISOLATED,
1298 nullptr,
1299 nullptr);
1300
1301 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1302
1303 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1304 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1305
1306 android_dlextinfo extinfo;
1307 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1308 extinfo.library_namespace = ns1;
1309
1310 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1311 ASSERT_TRUE(handle == nullptr);
1312 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1313}
1314
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001315TEST(dlext, ns_isolated) {
1316 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001317 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001318
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001319 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001320 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001321 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1322
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001323 android_set_application_target_sdk_version(42U); // something > 23
1324
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001325 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001326
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001327 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001328 android_create_namespace("private",
1329 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001330 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001331 ANDROID_NAMESPACE_TYPE_REGULAR,
1332 nullptr,
1333 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001334 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001335 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001336
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001337 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001338 android_create_namespace("private_isolated1",
1339 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001340 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001341 ANDROID_NAMESPACE_TYPE_ISOLATED,
1342 nullptr,
1343 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001344 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001345 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001346
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001347 android_namespace_t* ns_isolated2 =
1348 android_create_namespace("private_isolated2",
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001349 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001350 nullptr,
1351 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001352 GetTestlibRoot().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001353 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001354 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001355 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001356
1357 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1358 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1359
1360 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001361 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001362
1363 // Load lib_private_external_path to default namespace
1364 // (it should remain invisible for the isolated namespaces after this)
1365 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1366 ASSERT_TRUE(handle != nullptr) << dlerror();
1367
1368 android_dlextinfo extinfo;
1369 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1370 extinfo.library_namespace = ns_not_isolated;
1371
1372 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1373 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1374
1375 extinfo.library_namespace = ns_isolated;
1376
1377 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1378 ASSERT_TRUE(handle2 == nullptr);
Josh Gao16269572019-10-29 13:41:00 -07001379 const char* error = dlerror();
1380 ASSERT_MATCH(error,
1381 R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )"
1382 R"(\S+libnstest_root_not_isolated.so in namespace private_isolated1)");
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001383
1384 // Check dlopen by absolute path
1385 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1386 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001387 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001388 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001389 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001390
1391 extinfo.library_namespace = ns_isolated2;
1392
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001393 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001394 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001395 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1396 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001397
1398 // Check dlopen by absolute path
1399 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001400 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1401 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001402
1403 typedef const char* (*fn_t)();
1404 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1405 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1406
1407 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1408
1409 fn_t ns_get_private_extern_string =
1410 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1411 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1412
1413 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1414
1415 fn_t ns_get_public_extern_string =
1416 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1417 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1418
1419 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1420
1421 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1422 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1423
1424 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1425
1426 dlclose(handle1);
1427}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001428
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001429TEST(dlext, ns_shared) {
1430 static const char* root_lib = "libnstest_root_not_isolated.so";
1431 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001432
1433 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001434
Jiyong Park917d34a2017-08-31 14:07:13 +09001435 // create a parent namespace to use instead of the default namespace. This is
1436 // to make this test be independent from the configuration of the default
1437 // namespace.
1438 android_namespace_t* ns_parent =
1439 android_create_namespace("parent",
1440 nullptr,
1441 nullptr,
1442 ANDROID_NAMESPACE_TYPE_REGULAR,
1443 nullptr,
1444 nullptr);
1445 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1446 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1447
1448 android_dlextinfo extinfo;
1449 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1450 extinfo.library_namespace = ns_parent;
1451
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001452 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Jiyong Park917d34a2017-08-31 14:07:13 +09001453 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001454 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1455
1456 android_set_application_target_sdk_version(42U); // something > 23
1457
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001458 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001459
Jiyong Park917d34a2017-08-31 14:07:13 +09001460 // preload this library to the parent namespace to check if it
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001461 // is shared later on.
1462 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001463 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001464 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1465
Jiyong Park917d34a2017-08-31 14:07:13 +09001466 // create two child namespaces of 'ns_parent'. One with regular, the other
1467 // with isolated & shared.
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001468 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001469 android_create_namespace("private",
1470 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001471 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001472 ANDROID_NAMESPACE_TYPE_REGULAR,
1473 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001474 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001475 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001476 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1477 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001478
1479 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001480 android_create_namespace("private_isolated_shared",
1481 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001482 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001483 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001484 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001485 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001486 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001487 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1488 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001489
Jiyong Park917d34a2017-08-31 14:07:13 +09001490 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001491 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1492
1493 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001494 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001495
Jiyong Park917d34a2017-08-31 14:07:13 +09001496 // Load lib_private_external_path to the parent namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001497 // (it should remain invisible for the isolated namespaces after this)
Jiyong Park917d34a2017-08-31 14:07:13 +09001498 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001499 ASSERT_TRUE(handle != nullptr) << dlerror();
1500
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001501 extinfo.library_namespace = ns_not_isolated;
1502
1503 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1504 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1505
1506 extinfo.library_namespace = ns_isolated_shared;
1507
1508 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1509 ASSERT_TRUE(handle2 == nullptr);
Josh Gao16269572019-10-29 13:41:00 -07001510 ASSERT_MATCH(dlerror(),
1511 R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )"
1512 R"(\S+libnstest_root_not_isolated.so in namespace private_isolated_shared)");
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001513
1514 // Check dlopen by absolute path
1515 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1516 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001517 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001518 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001519 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001520
1521 // load libnstest_root.so to shared namespace in order to check that everything is different
1522 // except shared libnstest_dlopened.so
1523
1524 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1525
1526 typedef const char* (*fn_t)();
1527 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1528 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1529 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1530 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1531
1532 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1533 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1534 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1535
1536 fn_t ns_get_private_extern_string =
1537 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1538 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1539 fn_t ns_get_private_extern_string_shared =
1540 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1541 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1542
1543 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1544 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1545 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1546
1547 fn_t ns_get_public_extern_string =
1548 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1549 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1550 fn_t ns_get_public_extern_string_shared =
1551 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1552 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1553
1554 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1555 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1556 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1557
1558 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1559 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1560 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1561 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1562 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1563 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1564
1565 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1566 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1567 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1568 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1569 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1570
1571 dlclose(handle1);
1572 dlclose(handle2);
1573}
1574
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001575TEST(dlext, ns_shared_links_and_paths) {
1576 // Create parent namespace (isolated, not shared)
1577 android_namespace_t* ns_isolated =
1578 android_create_namespace("private_isolated",
1579 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001580 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001581 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001582 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001583 nullptr);
1584 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1585 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1586
1587 // Create shared namespace with ns_isolated parent
1588 android_namespace_t* ns_shared =
1589 android_create_namespace("private_shared",
1590 nullptr,
1591 nullptr,
1592 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1593 nullptr,
1594 ns_isolated);
1595 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1596
1597 // 1. Load a library in ns_shared to check that it has inherited
1598 // search path and the link to the default namespace.
1599 android_dlextinfo extinfo;
1600 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1601 extinfo.library_namespace = ns_shared;
1602
1603 {
1604 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1605 ASSERT_TRUE(handle != nullptr) << dlerror();
1606 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1607 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1608 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1609
1610 dlclose(handle);
1611 }
1612 // 2. Load another test library by absolute path to check that
1613 // it has inherited permitted_when_isolated_path
1614 {
1615 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001616 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001617 RTLD_NOW,
1618 &extinfo);
1619
1620 ASSERT_TRUE(handle != nullptr) << dlerror();
1621 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1622 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1623 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1624
1625 dlclose(handle);
1626 }
1627
1628 // 3. Check that it is still isolated.
1629 {
1630 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001631 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001632 RTLD_NOW,
1633 &extinfo);
1634
1635 ASSERT_TRUE(handle == nullptr);
1636 }
1637}
1638
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001639TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001640 android_set_application_target_sdk_version(42U); // something > 23
1641
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001642 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001643
1644 // preload this library to the default namespace to check if it
1645 // is shared later on.
1646 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001647 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001648 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1649
1650 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001651 android_create_namespace("private_isolated_shared",
1652 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001653 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001654 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001655 nullptr,
1656 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001657 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001658 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001659
1660 // Check if "libnstest_dlopened.so" is loaded (and the same)
1661 android_dlextinfo extinfo;
1662 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1663 extinfo.library_namespace = ns_isolated_shared;
1664
1665 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1666 ASSERT_TRUE(handle != nullptr) << dlerror();
1667 ASSERT_TRUE(handle == handle_dlopened);
1668 dlclose(handle);
1669 dlclose(handle_dlopened);
1670
1671 // And now check that the library cannot be found by soname (and is no longer loaded)
1672 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1673 ASSERT_TRUE(handle == nullptr)
1674 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1675
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001676 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001677 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1678 ASSERT_TRUE(handle == nullptr)
1679 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1680
1681 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1682 ASSERT_TRUE(handle == nullptr)
1683 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1684
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001685 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001686 RTLD_NOW | RTLD_NOLOAD);
1687 ASSERT_TRUE(handle == nullptr)
1688 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1689
1690 // Now lets see if the soinfo area gets reused in the wrong way:
1691 // load a library to default namespace.
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001692 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001693 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1694 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1695
1696 // try to find it in shared namespace
1697 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1698 ASSERT_TRUE(handle == nullptr)
1699 << "Error: " << g_public_lib << " is accessible in shared namespace";
1700}
1701
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001702TEST(dlext, ns_isolated_rtld_global) {
1703 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001704 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001705
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001706 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001707
1708 android_namespace_t* ns1 =
1709 android_create_namespace("isolated1",
1710 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001711 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001712 ANDROID_NAMESPACE_TYPE_ISOLATED,
1713 lib_public_path.c_str(),
1714 nullptr);
1715 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001716 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001717
1718 android_namespace_t* ns2 =
1719 android_create_namespace("isolated2",
1720 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001721 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001722 ANDROID_NAMESPACE_TYPE_ISOLATED,
1723 lib_public_path.c_str(),
1724 nullptr);
1725 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001726 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001727
1728 android_dlextinfo extinfo;
1729 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1730 extinfo.library_namespace = ns1;
1731
1732 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1733 RTLD_GLOBAL,
1734 &extinfo);
1735
1736 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1737
1738 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001739 android_create_namespace("isolated1_child",
1740 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001741 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001742 ANDROID_NAMESPACE_TYPE_ISOLATED,
1743 nullptr,
1744 ns1);
1745
1746 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1747 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001748
1749 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1750 // attempt to use ns2 should result in dlerror()
1751
1752 // Check ns1_child first.
1753 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1754 extinfo.library_namespace = ns1_child;
1755
1756 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1757 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1758
1759 // now ns1
1760 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1761 extinfo.library_namespace = ns1;
1762
1763 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1764 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1765
1766 // and ns2 should fail
1767 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1768 extinfo.library_namespace = ns2;
1769
1770 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1771 ASSERT_TRUE(handle1 == nullptr);
Josh Gao16269572019-10-29 13:41:00 -07001772 ASSERT_MATCH(
1773 dlerror(),
1774 R"(dlopen failed: library "libnstest_public.so" not found: needed by \S+libnstest_root.so)"
1775 R"( in namespace isolated2)");
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001776}
1777
dimitry8db36a52017-10-23 15:10:10 +02001778TEST(dlext, ns_inaccessible_error_message) {
1779 // We set up 2 namespaces (a and b) and link a->b with a shared library
1780 // libtestshared.so. Then try to dlopen different library with the same
1781 // name from in namespace a. Note that library should not be accessible
1782 // in either namespace but since it's soname is in the list of shared libs
1783 // the linker will attempt to find it in linked namespace.
1784 //
1785 // Check the error message and make sure it mentions correct namespace name.
1786 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1787
1788 android_namespace_t* ns_a =
1789 android_create_namespace("ns_a",
1790 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001791 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001792 ANDROID_NAMESPACE_TYPE_ISOLATED,
1793 nullptr,
1794 nullptr);
1795 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1796 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1797
1798 android_namespace_t* ns_b =
1799 android_create_namespace("ns_b",
1800 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001801 GetTestlibRoot().c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001802 ANDROID_NAMESPACE_TYPE_ISOLATED,
1803 nullptr,
1804 nullptr);
1805 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1806 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1807
1808 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1809
1810 android_dlextinfo extinfo;
1811 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1812 extinfo.library_namespace = ns_a;
1813
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001814 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
dimitry8db36a52017-10-23 15:10:10 +02001815
1816 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1817 ASSERT_TRUE(handle == nullptr);
1818 std::string expected_dlerror =
1819 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1820 " is not accessible for the namespace \"ns_a\"",
1821 library_path.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001822 android::base::GetExecutablePath().c_str());
dimitry8db36a52017-10-23 15:10:10 +02001823 ASSERT_EQ(expected_dlerror, dlerror());
1824}
1825
dimitry321476a2018-01-29 15:32:37 +01001826extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1827 android_namespace_t* namespace_to);
1828
Logan Chien9ee45912018-01-18 12:05:09 +08001829TEST(dlext, ns_link_namespaces_invalid_arguments) {
1830 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1831
1832 android_namespace_t* ns =
1833 android_create_namespace("private",
1834 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001835 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001836 ANDROID_NAMESPACE_TYPE_REGULAR,
1837 nullptr,
1838 nullptr);
1839 ASSERT_TRUE(ns != nullptr) << dlerror();
1840
1841 // Test android_link_namespaces()
1842 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1843 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1844 dlerror());
1845
1846 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1847 ASSERT_STREQ("android_link_namespaces failed: "
1848 "error linking namespaces \"private\"->\"(default)\": "
1849 "the list of shared libraries is empty.", dlerror());
1850
1851 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1852 ASSERT_STREQ("android_link_namespaces failed: "
1853 "error linking namespaces \"private\"->\"(default)\": "
1854 "the list of shared libraries is empty.", dlerror());
1855
dimitry321476a2018-01-29 15:32:37 +01001856 // Test __loader_android_link_namespaces_all_libs()
1857 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001858 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1859 "error linking namespaces: namespace_from is null.", dlerror());
1860
dimitry321476a2018-01-29 15:32:37 +01001861 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
Logan Chien9ee45912018-01-18 12:05:09 +08001862 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1863 "error linking namespaces: namespace_from is null.", dlerror());
1864
dimitry321476a2018-01-29 15:32:37 +01001865 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001866 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1867 "error linking namespaces: namespace_to is null.", dlerror());
1868}
1869
1870TEST(dlext, ns_allow_all_shared_libs) {
1871 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1872
1873 android_namespace_t* ns_a =
1874 android_create_namespace("ns_a",
1875 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001876 (GetTestlibRoot() + "/ns_a").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001877 ANDROID_NAMESPACE_TYPE_ISOLATED,
1878 nullptr,
1879 nullptr);
1880 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1881 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1882
1883 android_namespace_t* ns_b =
1884 android_create_namespace("ns_b",
1885 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001886 (GetTestlibRoot() + "/ns_b").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001887 ANDROID_NAMESPACE_TYPE_ISOLATED,
1888 nullptr,
1889 nullptr);
1890 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1891 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1892
1893 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
dimitry321476a2018-01-29 15:32:37 +01001894 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
Logan Chien9ee45912018-01-18 12:05:09 +08001895
1896 // Load libs with android_dlopen_ext() from namespace b
1897 android_dlextinfo extinfo;
1898 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1899 extinfo.library_namespace = ns_b;
1900
1901 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1902 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1903
1904 void* ns_b_handle1_internal =
1905 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1906 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1907
1908 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1909 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1910
1911 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1912 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1913
1914 // Load libs with android_dlopen_ext() from namespace a
1915 extinfo.library_namespace = ns_a;
1916
1917 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1918 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1919
1920 void* ns_a_handle1_internal =
1921 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1922 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1923
1924 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1925 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1926
1927 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1928 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1929
1930 // Compare the dlopen handle
1931 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1932 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1933 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1934
1935 // Close libs
1936 dlclose(ns_b_handle1);
1937 dlclose(ns_b_handle2);
1938 dlclose(ns_b_handle3);
1939
1940 dlclose(ns_a_handle1);
1941 dlclose(ns_a_handle1_internal);
1942 dlclose(ns_a_handle2);
1943 dlclose(ns_a_handle3);
1944}
1945
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001946TEST(dlext, ns_anonymous) {
1947 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001948 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001949
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001950 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001951 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1952
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001953 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1954
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001955 ASSERT_TRUE(
1956 android_init_anonymous_namespace(shared_libs.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001957 (GetTestlibRoot() + "/private_namespace_libs").c_str())
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001958 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001959
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001960 android_namespace_t* ns =
1961 android_create_namespace("private",
1962 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001963 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001964 ANDROID_NAMESPACE_TYPE_REGULAR,
1965 nullptr,
1966 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001967
1968 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001969 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001970
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001971 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001972
1973 android_dlextinfo extinfo;
1974 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1975 extinfo.library_namespace = ns;
1976
1977 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1978 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1979 ASSERT_TRUE(handle != nullptr) << dlerror();
1980
1981 uintptr_t ns_get_dlopened_string_addr =
1982 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1983 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1984 typedef const char* (*fn_t)();
1985 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1986
1987 std::vector<map_record> maps;
1988 Maps::parse_maps(&maps);
1989
1990 uintptr_t addr_start = 0;
1991 uintptr_t addr_end = 0;
dimitry8eaf28d2017-10-11 10:04:14 +02001992 bool has_executable_segment = false;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001993 std::vector<map_record> maps_to_copy;
1994
1995 for (const auto& rec : maps) {
1996 if (rec.pathname == private_library_absolute_path) {
1997 if (addr_start == 0) {
1998 addr_start = rec.addr_start;
1999 }
2000 addr_end = rec.addr_end;
dimitry8eaf28d2017-10-11 10:04:14 +02002001 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002002
2003 maps_to_copy.push_back(rec);
2004 }
2005 }
2006
2007 // some sanity checks..
2008 ASSERT_TRUE(addr_start > 0);
2009 ASSERT_TRUE(addr_end > 0);
dimitry3b0a5b72018-06-06 11:11:25 +02002010 ASSERT_TRUE(maps_to_copy.size() > 0);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002011 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
2012 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
2013
dimitry8eaf28d2017-10-11 10:04:14 +02002014 if (!has_executable_segment) {
2015 // For some natively bridged environments this code might be missing
2016 // the executable flag. This is because the guest code is not supposed
2017 // to be executed directly and making it non-executable is more secure.
Evgeny Eltsinad865d72019-12-17 18:54:17 +01002018 // In this case we assume the segment with the function is executable.
2019 for (auto& rec : maps_to_copy) {
2020 if (ns_get_dlopened_string_addr >= rec.addr_start &&
2021 ns_get_dlopened_string_addr < rec.addr_end) {
2022 ASSERT_TRUE((rec.perms & PROT_WRITE) == 0);
2023 rec.perms |= PROT_EXEC;
2024 break;
2025 }
2026 }
dimitry8eaf28d2017-10-11 10:04:14 +02002027 }
2028
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002029 // copy
2030 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
2031 PROT_NONE, MAP_ANON | MAP_PRIVATE,
2032 -1, 0));
2033 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
2034
2035 for (const auto& rec : maps_to_copy) {
2036 uintptr_t offset = rec.addr_start - addr_start;
2037 size_t size = rec.addr_end - rec.addr_start;
2038 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
2039 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
2040 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
2041 ASSERT_TRUE(map != MAP_FAILED);
2042 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
2043 mprotect(map, size, rec.perms);
2044 }
2045
2046 // call the function copy
2047 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
2048 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
2049 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2050 ns_get_dlopened_string_anon());
2051
2052 // They should belong to different namespaces (private and anonymous)
2053 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2054 ns_get_dlopened_string_private());
2055
2056 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
2057}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002058
Ryan Prichard22fa3dd2020-01-31 14:47:48 -08002059TEST(dlext, ns_hidden_child) {
2060 ExecTestHelper eth;
2061
2062 std::string helper = GetTestlibRoot() + "/ns_hidden_child_helper/ns_hidden_child_helper";
2063 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
2064 std::string app_ns_dir = GetTestlibRoot() + "/ns_hidden_child_app";
2065 eth.SetArgs({ helper.c_str(), app_ns_dir.c_str(), nullptr });
2066
2067 // Add the main libns_hidden_child_*.so libraries to the search path of the default namespace.
2068 std::string env = "LD_LIBRARY_PATH=" + GetTestlibRoot();
2069 eth.SetEnv({ env.c_str(), nullptr });
2070
2071 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
2072 "public_function is non-null\n"
2073 "internal_function is null\n");
2074}
2075
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002076TEST(dlext, dlopen_handle_value_platform) {
2077 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2078 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
2079 << "dlopen should return odd value for the handle";
2080 dlclose(handle);
2081}
2082
2083TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes95c6cd72019-12-20 13:26:14 -08002084 android_set_application_target_sdk_version(23);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002085 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2086 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
2087 << "dlopen should return valid pointer";
2088 dlclose(handle);
2089}