blob: 67ebf37dfc6f80125523cc5593e3ee4011e49773 [file] [log] [blame]
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <dlfcn.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080020#include <elf.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000021#include <errno.h>
22#include <fcntl.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080023#include <inttypes.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000024#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070027
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000028#include <android/dlext.h>
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -070029#include <android-base/file.h>
Zhenhua WANG81aad002017-04-25 11:07:19 +080030#include <android-base/strings.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070031
32#include <linux/memfd.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000033#include <sys/mman.h>
Elliott Hughesd7c52622017-06-20 14:26:56 -070034#include <sys/syscall.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010035#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070036#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000037#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000038
Sandeep Patil4e02cc12019-01-21 14:22:05 -080039#include <meminfo/procmeminfo.h>
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040040#include <procinfo/process_map.h>
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -080041#include <ziparchive/zip_archive.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010042
Dimitry Ivanov927877c2016-09-21 11:17:13 -070043#include "gtest_globals.h"
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -080044#include "utils.h"
Dimitry Ivanov41fd2952016-05-09 17:37:39 -070045#include "dlext_private.h"
Dimitry Ivanov708589f2016-09-19 10:50:28 -070046#include "dlfcn_symlink_support.h"
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000047
48#define ASSERT_DL_NOTNULL(ptr) \
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070049 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000050
51#define ASSERT_DL_ZERO(i) \
52 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
53
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000054#define ASSERT_NOERROR(i) \
55 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
56
Yabin Cui16f7f8d2014-11-04 11:08:05 -080057#define ASSERT_SUBSTR(needle, haystack) \
58 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
59
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000060
61typedef int (*fn)(void);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070062constexpr const char* kLibName = "libdlext_test.so";
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040063constexpr const char* kLibNameRecursive = "libdlext_test_recursive.so";
Dimitry Ivanov927877c2016-09-21 11:17:13 -070064constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
65constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
66constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070067
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000068class DlExtTest : public ::testing::Test {
69protected:
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
Victor Chang6cb719f2019-02-06 17:19:10 +0000234TEST(dlfcn, dlopen_from_nullptr_android_api_level) {
235 // Regression test for http://b/123972211. Testing dlopen(nullptr) when target sdk is P
236 android_set_application_target_sdk_version(__ANDROID_API_P__);
237 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);
366 EXPECT_GE(reinterpret_cast<void*>(taxicab_number), start);
367 EXPECT_LT(reinterpret_cast<void*>(taxicab_number), reinterpret_cast<char*>(start) + kLibSize);
368 EXPECT_EQ(1729U, *taxicab_number);
369}
370
371TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
Yi Kong1e7a1502019-03-14 16:25:45 -0700372 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400373 ASSERT_TRUE(start != MAP_FAILED);
374 android_dlextinfo extinfo;
375 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
376 extinfo.reserved_addr = start;
Yi Kong1e7a1502019-03-14 16:25:45 -0700377 extinfo.reserved_size = PAGE_SIZE;
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400378 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
379 EXPECT_EQ(nullptr, handle_);
380}
381
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000382TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700383 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000384 ASSERT_TRUE(start != MAP_FAILED);
385 android_dlextinfo extinfo;
386 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
387 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700388 extinfo.reserved_size = kLibSize;
389 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000390 ASSERT_DL_NOTNULL(handle_);
391 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
392 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700393 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000394 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700395 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000396 EXPECT_EQ(4, f());
397}
398
399TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800400 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000401 ASSERT_TRUE(start != MAP_FAILED);
402 android_dlextinfo extinfo;
403 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
404 extinfo.reserved_addr = start;
405 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700406 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000407 ASSERT_DL_NOTNULL(handle_);
408 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
409 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700410 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
411 (reinterpret_cast<void*>(f) >=
412 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000413 EXPECT_EQ(4, f());
414}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000415
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100416class DlExtRelroSharingTest : public DlExtTest {
417protected:
Yi Kong358603a2019-03-29 14:25:16 -0700418 void SetUp() override {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100419 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700420 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100421 ASSERT_TRUE(start != MAP_FAILED);
422 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
423 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700424 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100425 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000426 }
427
Yi Kong358603a2019-03-29 14:25:16 -0700428 void TearDown() override {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100429 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100430 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000431
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400432 void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
Elliott Hughes5cec3772018-01-19 15:45:23 -0800433 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100434 ASSERT_NOERROR(relro_fd);
435
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400436 if (recursive) {
437 extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
438 }
439
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100440 pid_t pid = fork();
441 if (pid == 0) {
442 // child process
443 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
444 extinfo_.relro_fd = relro_fd;
445 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700446 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100447 fprintf(stderr, "in child: %s\n", dlerror());
448 exit(1);
449 }
Torne (Richard Coles)fa9f7f22019-04-02 17:04:42 -0400450 fn f = reinterpret_cast<fn>(dlsym(handle, "getRandomNumber"));
451 ASSERT_DL_NOTNULL(f);
452 EXPECT_EQ(4, f());
453
454 if (recursive) {
455 fn f = reinterpret_cast<fn>(dlsym(handle, "getBiggerRandomNumber"));
456 ASSERT_DL_NOTNULL(f);
457 EXPECT_EQ(8, f());
458 }
459
460 uint32_t* taxicab_number =
461 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
462 ASSERT_DL_NOTNULL(taxicab_number);
463 EXPECT_EQ(1729U, *taxicab_number);
464 exit(testing::Test::HasFailure());
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100465 }
466
467 // continuing in parent
468 ASSERT_NOERROR(close(relro_fd));
469 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800470 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100471
472 // reopen file for reading so it can be used
Elliott Hughes5cec3772018-01-19 15:45:23 -0800473 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100474 ASSERT_NOERROR(relro_fd);
475 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
476 extinfo_.relro_fd = relro_fd;
477 }
478
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400479 void TryUsingRelro(const char* lib, bool recursive) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100480 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
481 ASSERT_DL_NOTNULL(handle_);
482 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
483 ASSERT_DL_NOTNULL(f);
484 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700485
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400486 if (recursive) {
487 fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
488 ASSERT_DL_NOTNULL(f);
489 EXPECT_EQ(8, f());
490 }
491
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800492 uint32_t* taxicab_number =
493 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700494 ASSERT_DL_NOTNULL(taxicab_number);
495 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100496 }
497
Zhenhua WANG81aad002017-04-25 11:07:19 +0800498 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
499 size_t* pss_out);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100500
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400501 std::string FindMappingName(void* ptr);
502
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100503 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100504};
505
506TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800507 TemporaryFile tf; // Use tf to get an unique filename.
508 ASSERT_NOERROR(close(tf.fd));
509
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400510 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
511 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
512 void* relro_data = dlsym(handle_, "lots_of_relro");
513 ASSERT_DL_NOTNULL(relro_data);
514 EXPECT_EQ(tf.path, FindMappingName(relro_data));
515
516 // Use destructor of tf to close and unlink the file.
517 tf.fd = extinfo_.relro_fd;
518}
519
520TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
521 TemporaryFile tf; // Use tf to get an unique filename.
522 ASSERT_NOERROR(close(tf.fd));
523
524 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
525 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
526 void* relro_data = dlsym(handle_, "lots_of_relro");
527 ASSERT_DL_NOTNULL(relro_data);
528 EXPECT_EQ(tf.path, FindMappingName(relro_data));
529 void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
530 ASSERT_DL_NOTNULL(recursive_relro_data);
531 EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
532
Yabin Cui294d1e22014-12-07 20:43:37 -0800533
534 // Use destructor of tf to close and unlink the file.
535 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100536}
537
Torne (Richard Coles)5d103742019-04-11 12:25:06 -0400538TEST_F(DlExtRelroSharingTest, CheckRelroSizes) {
539 TemporaryFile tf1, tf2;
540 ASSERT_NOERROR(close(tf1.fd));
541 ASSERT_NOERROR(close(tf2.fd));
542
543 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf1.path, false));
544 struct stat no_recursive;
545 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &no_recursive));
546 tf1.fd = extinfo_.relro_fd;
547
548 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf2.path, true));
549 struct stat with_recursive;
550 ASSERT_NOERROR(fstat(extinfo_.relro_fd, &with_recursive));
551 tf2.fd = extinfo_.relro_fd;
552
553 // RELRO file should end up bigger when we use the recursive flag, since it
554 // includes data for more than one library.
555 ASSERT_GT(with_recursive.st_size, no_recursive.st_size);
556}
557
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100558TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800559 TemporaryFile tf; // // Use tf to get an unique filename.
560 ASSERT_NOERROR(close(tf.fd));
561
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400562 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
563 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800564
565 // Use destructor of tf to close and unlink the file.
566 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100567}
568
569TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400570 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000571}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100572
573TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800574 if (geteuid() != 0) GTEST_SKIP() << "This test must be run as root";
Dan Albert69fb9f32014-09-03 11:30:21 -0700575
Yabin Cui294d1e22014-12-07 20:43:37 -0800576 TemporaryFile tf; // Use tf to get an unique filename.
577 ASSERT_NOERROR(close(tf.fd));
578
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400579 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800580
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100581 int pipefd[2];
582 ASSERT_NOERROR(pipe(pipefd));
583
584 size_t without_sharing, with_sharing;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -0800585 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
586 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
Zhenhua WANG81aad002017-04-25 11:07:19 +0800587 ASSERT_LT(with_sharing, without_sharing);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100588
Zhenhua WANG81aad002017-04-25 11:07:19 +0800589 // We expect the sharing to save at least 50% of the library's total PSS.
590 // In practice it saves 80%+ for this library in the test.
591 size_t pss_saved = without_sharing - with_sharing;
592 size_t expected_min_saved = without_sharing / 2;
593
594 EXPECT_LT(expected_min_saved, pss_saved);
Yabin Cui294d1e22014-12-07 20:43:37 -0800595
596 // Use destructor of tf to close and unlink the file.
597 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100598}
599
Zhenhua WANG81aad002017-04-25 11:07:19 +0800600void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
601 size_t* total_pss) {
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800602 android::meminfo::ProcMemInfo proc_mem(pid);
603 const std::vector<android::meminfo::Vma>& maps = proc_mem.Maps();
604 ASSERT_GT(maps.size(), 0UL);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100605
Zhenhua WANG81aad002017-04-25 11:07:19 +0800606 // Calculate total PSS of the library.
607 *total_pss = 0;
608 bool saw_relro_file = false;
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800609 for (auto& vma : maps) {
610 if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
611 if (vma.name == relro_file) {
612 saw_relro_file = true;
613 }
Zhenhua WANG81aad002017-04-25 11:07:19 +0800614
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800615 *total_pss += vma.usage.pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800616 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100617 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100618
Zhenhua WANG81aad002017-04-25 11:07:19 +0800619 if (shared_relro) ASSERT_TRUE(saw_relro_file);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100620}
621
Zhenhua WANG81aad002017-04-25 11:07:19 +0800622void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
623 bool share_relro, size_t* pss_out) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100624 const int CHILDREN = 20;
625
626 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800627 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100628 int childpipe[CHILDREN];
629 for (int i=0; i<CHILDREN; ++i) {
630 char read_buf;
631 int child_done_pipe[2], parent_done_pipe[2];
632 ASSERT_NOERROR(pipe(child_done_pipe));
633 ASSERT_NOERROR(pipe(parent_done_pipe));
634
635 pid_t child = fork();
636 if (child == 0) {
637 // close the 'wrong' ends of the pipes in the child
638 close(child_done_pipe[0]);
639 close(parent_done_pipe[1]);
640
641 // open the library
642 void* handle;
643 if (share_relro) {
644 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
645 } else {
646 handle = dlopen(lib, RTLD_NOW);
647 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700648 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100649 fprintf(stderr, "in child: %s\n", dlerror());
650 exit(1);
651 }
652
653 // close write end of child_done_pipe to signal the parent that we're done.
654 close(child_done_pipe[1]);
655
656 // wait for the parent to close parent_done_pipe, then exit
657 read(parent_done_pipe[0], &read_buf, 1);
658 exit(0);
659 }
660
661 ASSERT_NOERROR(child);
662
663 // close the 'wrong' ends of the pipes in the parent
664 close(child_done_pipe[1]);
665 close(parent_done_pipe[0]);
666
667 // wait for the child to be done
668 read(child_done_pipe[0], &read_buf, 1);
669 close(child_done_pipe[0]);
670
671 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800672 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100673 childpipe[i] = parent_done_pipe[1];
674 }
675
Zhenhua WANG81aad002017-04-25 11:07:19 +0800676 // Sum the PSS of tested library of all the children
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100677 size_t total_pss = 0;
678 for (int i=0; i<CHILDREN; ++i) {
679 size_t child_pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800680 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100681 total_pss += child_pss;
682 }
683 *pss_out = total_pss;
684
685 // Close pipes and wait for children to exit
686 for (int i=0; i<CHILDREN; ++i) {
687 ASSERT_NOERROR(close(childpipe[i]));
688 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800689 for (int i = 0; i < CHILDREN; ++i) {
690 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100691 }
692}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700693
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400694std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
695 uint64_t addr = reinterpret_cast<uint64_t>(ptr);
696 std::string found_name = "<not found>";
697
698 EXPECT_TRUE(android::procinfo::ReadMapFile(
699 "/proc/self/maps",
700 [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
701 if (addr >= start && addr < end) {
702 found_name = name;
703 }
704 }));
705
706 return found_name;
707}
708
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700709// Testing namespaces
710static const char* g_public_lib = "libnstest_public.so";
711
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800712// These are libs shared with default namespace
713static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
714
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700715TEST(dlext, ns_smoke) {
716 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800717 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700718
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800719 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
720 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
721 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
722 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700723
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700724 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800725 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700726 ASSERT_TRUE(handle_public != nullptr) << dlerror();
727
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800728 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700729
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800730 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700731 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800732 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800733 ASSERT_TRUE(handle_public == nullptr);
734 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
735 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
736
737 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700738
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800739 // create "public namespace", share limited set of public libraries with
740
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800741 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800742 android_create_namespace("private",
743 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700744 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800745 ANDROID_NAMESPACE_TYPE_REGULAR,
746 nullptr,
747 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700748 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800749 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700750
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800751 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800752 android_create_namespace("private_isolated",
753 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700754 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800755 ANDROID_NAMESPACE_TYPE_ISOLATED,
756 nullptr,
757 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700758 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800759 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700760
761 // This should not have affect search path for default namespace:
762 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
763 void* handle = dlopen(g_public_lib, RTLD_NOW);
764 ASSERT_TRUE(handle != nullptr) << dlerror();
765 dlclose(handle);
766
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700767 // dlopen for a public library using an absolute path should work
768 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700769 android_dlextinfo extinfo;
770 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700771 extinfo.library_namespace = ns2;
772 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
773 ASSERT_TRUE(handle != nullptr) << dlerror();
774 ASSERT_TRUE(handle == handle_public);
775
776 dlclose(handle);
777
778 // 1.1 even if it wasn't loaded before
779 dlclose(handle_public);
780
781 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
782 ASSERT_TRUE(handle_public == nullptr);
783 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
784 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
785
786 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
787 ASSERT_TRUE(handle != nullptr) << dlerror();
788
789 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
790 ASSERT_TRUE(handle == handle_public);
791
792 dlclose(handle);
793
794 // 2. And for regular namespaces (make sure it does not load second copy of the library)
795 extinfo.library_namespace = ns1;
796 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
797 ASSERT_TRUE(handle != nullptr) << dlerror();
798 ASSERT_TRUE(handle == handle_public);
799
800 dlclose(handle);
801
802 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
803 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
804 dlclose(handle_public);
805
806 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
807 ASSERT_TRUE(handle_public == nullptr);
808 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
809 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
810
811 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
812 ASSERT_TRUE(handle != nullptr) << dlerror();
813
814 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
815
816 ASSERT_TRUE(handle != handle_public);
817
818 dlclose(handle);
819
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700820 extinfo.library_namespace = ns1;
821
822 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
823 ASSERT_TRUE(handle1 != nullptr) << dlerror();
824
825 extinfo.library_namespace = ns2;
826 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
827 ASSERT_TRUE(handle2 != nullptr) << dlerror();
828
829 ASSERT_TRUE(handle1 != handle2);
830
831 typedef const char* (*fn_t)();
832
833 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
834 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
835 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
836 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
837
838 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
839 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
840
841 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
842
843 fn_t ns_get_private_extern_string1 =
844 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
845 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
846 fn_t ns_get_private_extern_string2 =
847 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
848 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
849
850 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
851 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
852
853 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
854
855 fn_t ns_get_public_extern_string1 =
856 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
857 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
858 fn_t ns_get_public_extern_string2 =
859 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
860 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
861
862 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
863 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
864
865 // and now check that dlopen() does the right thing in terms of preserving namespace
866 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
867 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
868 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
869 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
870
871 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
872 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
873
874 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
875
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800876 // Check that symbols from non-shared libraries a shared library depends on are not visible
877 // from original namespace.
878
879 fn_t ns_get_internal_extern_string =
880 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
881 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
882 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
883 "ns_get_internal_extern_string() expected to return null but returns \"" <<
884 ns_get_internal_extern_string() << "\"";
885
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700886 dlclose(handle1);
887
888 // Check if handle2 is still alive (and well)
889 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
890 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
891 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
892 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
893
894 dlclose(handle2);
895}
896
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700897TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700898 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700899
900 int tmpfd = TEMP_FAILURE_RETRY(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700901 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700902
903 // Ignore kernels without O_TMPFILE flag support
904 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
905 return;
906 }
907
908 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
909
910 android_namespace_t* ns =
911 android_create_namespace("testing-o_tmpfile",
912 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700913 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700914 ANDROID_NAMESPACE_TYPE_ISOLATED,
915 nullptr,
916 nullptr);
917
918 ASSERT_DL_NOTNULL(ns);
919
920 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
921
922 std::string content;
923 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
924 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
925
926 android_dlextinfo extinfo;
927 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
928 extinfo.library_fd = tmpfd;
929 extinfo.library_namespace = ns;
930
931 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
932
933 ASSERT_DL_NOTNULL(handle);
934
935 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
936 ASSERT_DL_NOTNULL(taxicab_number);
937 EXPECT_EQ(1729U, *taxicab_number);
938 dlclose(handle);
939}
940
941TEST(dlext, dlopen_ext_use_memfd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700942 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700943
944 // create memfd
945 int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
946 if (memfd == -1 && errno == ENOSYS) {
947 return;
948 }
949
950 ASSERT_TRUE(memfd != -1) << strerror(errno);
951
952 // Check st.f_type is TMPFS_MAGIC for memfd
953 struct statfs st;
954 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
955 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
956
957 android_namespace_t* ns =
958 android_create_namespace("testing-memfd",
959 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700960 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700961 ANDROID_NAMESPACE_TYPE_ISOLATED,
962 nullptr,
963 nullptr);
964
965 ASSERT_DL_NOTNULL(ns);
966
967 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
968
969 // read file into memfd backed one.
970 std::string content;
971 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
972 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
973
974 android_dlextinfo extinfo;
975 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
976 extinfo.library_fd = memfd;
977 extinfo.library_namespace = ns;
978
979 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
980
981 ASSERT_DL_NOTNULL(handle);
982
983 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
984 ASSERT_DL_NOTNULL(taxicab_number);
985 EXPECT_EQ(1729U, *taxicab_number);
986 dlclose(handle);
987}
988
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800989TEST(dlext, ns_symbol_visibilty_one_namespace) {
990 static const char* root_lib = "libnstest_root.so";
991 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
992
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700993 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
994 GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800995
996 android_namespace_t* ns =
997 android_create_namespace("one",
998 nullptr,
999 ns_search_path.c_str(),
1000 ANDROID_NAMESPACE_TYPE_ISOLATED,
1001 nullptr,
1002 nullptr);
1003
1004 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1005
1006 android_dlextinfo extinfo;
1007 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1008 extinfo.library_namespace = ns;
1009
1010 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1011 ASSERT_TRUE(handle != nullptr) << dlerror();
1012
1013 typedef const char* (*fn_t)();
1014
1015 // Check that relocation worked correctly
1016 fn_t ns_get_internal_extern_string =
1017 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1018 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1019 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
1020
1021 fn_t internal_extern_string_fn =
1022 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1023 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
1024 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
1025}
1026
1027TEST(dlext, ns_symbol_visibilty_between_namespaces) {
1028 static const char* root_lib = "libnstest_root.so";
1029 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1030
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001031 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1032 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001033
1034 android_namespace_t* ns_public =
1035 android_create_namespace("public",
1036 nullptr,
1037 public_ns_search_path.c_str(),
1038 ANDROID_NAMESPACE_TYPE_ISOLATED,
1039 nullptr,
1040 nullptr);
1041
1042 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1043
1044 android_namespace_t* ns_private =
1045 android_create_namespace("private",
1046 nullptr,
1047 private_ns_search_path.c_str(),
1048 ANDROID_NAMESPACE_TYPE_ISOLATED,
1049 nullptr,
1050 nullptr);
1051
1052 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1053 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1054
1055 android_dlextinfo extinfo;
1056 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1057 extinfo.library_namespace = ns_private;
1058
1059 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1060 ASSERT_TRUE(handle != nullptr) << dlerror();
1061
1062 typedef const char* (*fn_t)();
1063
1064 // Check that relocation worked correctly
1065 fn_t ns_get_internal_extern_string =
1066 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1067 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1068 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
1069 "ns_get_internal_extern_string() expected to return null but returns \"" <<
1070 ns_get_internal_extern_string() << "\"";
1071
1072 fn_t internal_extern_string_fn =
1073 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1074 ASSERT_TRUE(internal_extern_string_fn == nullptr);
1075 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
1076}
1077
1078TEST(dlext, ns_unload_between_namespaces) {
1079 static const char* root_lib = "libnstest_root.so";
1080 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1081
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001082 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1083 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001084
1085 android_namespace_t* ns_public =
1086 android_create_namespace("public",
1087 nullptr,
1088 public_ns_search_path.c_str(),
1089 ANDROID_NAMESPACE_TYPE_ISOLATED,
1090 nullptr,
1091 nullptr);
1092
1093 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1094
1095 android_namespace_t* ns_private =
1096 android_create_namespace("private",
1097 nullptr,
1098 private_ns_search_path.c_str(),
1099 ANDROID_NAMESPACE_TYPE_ISOLATED,
1100 nullptr,
1101 nullptr);
1102
1103 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1104 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1105
1106 android_dlextinfo extinfo;
1107 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1108 extinfo.library_namespace = ns_private;
1109
1110 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1111 ASSERT_TRUE(handle != nullptr) << dlerror();
1112
1113 dlclose(handle);
1114 // Check that root_lib was unloaded
1115 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1116 ASSERT_TRUE(handle == nullptr);
1117 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1118 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1119
1120 // Check that shared library was unloaded in public ns
1121 extinfo.library_namespace = ns_public;
1122 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1123 ASSERT_TRUE(handle == nullptr);
1124 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1125 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1126}
1127
dimitry965d06d2017-11-28 16:03:07 +01001128TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1129 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1130
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001131 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1132 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001133
1134 android_namespace_t* ns_public =
1135 android_create_namespace("public",
1136 nullptr,
1137 public_ns_search_path.c_str(),
1138 ANDROID_NAMESPACE_TYPE_ISOLATED,
1139 nullptr,
1140 nullptr);
1141
1142 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1143
1144 android_namespace_t* ns_private =
1145 android_create_namespace("private",
1146 nullptr,
1147 private_ns_search_path.c_str(),
1148 ANDROID_NAMESPACE_TYPE_ISOLATED,
1149 nullptr,
1150 nullptr);
1151
1152 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1153 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1154
1155 android_dlextinfo extinfo;
1156 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1157 extinfo.library_namespace = ns_private;
1158
1159 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1160 RTLD_NOW,
1161 &extinfo);
1162 ASSERT_TRUE(handle == nullptr);
1163 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1164 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1165 dlerror());
1166}
1167
1168TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1169 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1170
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001171 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1172 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001173
1174 android_namespace_t* ns_public =
1175 android_create_namespace("public",
1176 nullptr,
1177 public_ns_search_path.c_str(),
1178 ANDROID_NAMESPACE_TYPE_ISOLATED,
1179 nullptr,
1180 nullptr);
1181
1182 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1183
1184 android_namespace_t* ns_private =
1185 android_create_namespace("private",
1186 nullptr,
1187 private_ns_search_path.c_str(),
1188 ANDROID_NAMESPACE_TYPE_ISOLATED,
1189 nullptr,
1190 nullptr);
1191
1192 ASSERT_TRUE(android_link_namespaces(ns_private,
1193 ns_public,
1194 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1195 ) << dlerror();
1196 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1197
1198 android_dlextinfo extinfo;
1199 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1200 extinfo.library_namespace = ns_private;
1201
1202 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1203 ASSERT_TRUE(handle == nullptr);
1204 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1205 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1206 dlerror());
1207}
1208
Jiyong Park37b91af2017-05-05 22:07:05 +09001209TEST(dlext, ns_greylist_enabled) {
Dimitry Ivanov18623142017-02-21 13:41:08 -08001210 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1211
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001212 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov18623142017-02-21 13:41:08 -08001213
1214 android_namespace_t* ns =
1215 android_create_namespace("namespace",
1216 nullptr,
1217 ns_search_path.c_str(),
Jiyong Park37b91af2017-05-05 22:07:05 +09001218 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
Dimitry Ivanov18623142017-02-21 13:41:08 -08001219 nullptr,
1220 nullptr);
1221
1222 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1223
1224 android_dlextinfo extinfo;
1225 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1226 extinfo.library_namespace = ns;
1227
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001228 // An app targeting M can open libnativehelper.so because it's on the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001229 android_set_application_target_sdk_version(__ANDROID_API_M__);
1230 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1231 ASSERT_TRUE(handle != nullptr) << dlerror();
1232
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001233 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1234 void* dlsym_ptr = dlsym(handle, "dlsym");
1235 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1236 ASSERT_EQ(&dlsym, dlsym_ptr);
1237
Dimitry Ivanov18623142017-02-21 13:41:08 -08001238 dlclose(handle);
1239
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001240 // An app targeting N no longer has the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001241 android_set_application_target_sdk_version(__ANDROID_API_N__);
1242 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1243 ASSERT_TRUE(handle == nullptr);
1244 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1245}
1246
Jiyong Park37b91af2017-05-05 22:07:05 +09001247TEST(dlext, ns_greylist_disabled_by_default) {
1248 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1249
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001250 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Jiyong Park37b91af2017-05-05 22:07:05 +09001251
1252 android_namespace_t* ns =
1253 android_create_namespace("namespace",
1254 nullptr,
1255 ns_search_path.c_str(),
1256 ANDROID_NAMESPACE_TYPE_ISOLATED,
1257 nullptr,
1258 nullptr);
1259
1260 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1261
1262 android_dlextinfo extinfo;
1263 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1264 extinfo.library_namespace = ns;
1265
1266 android_set_application_target_sdk_version(__ANDROID_API_M__);
1267 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1268 ASSERT_TRUE(handle == nullptr);
1269 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1270}
1271
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001272TEST(dlext, ns_cyclic_namespaces) {
1273 // Test that ns1->ns2->ns1 link does not break the loader
1274 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1275 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1276
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001277 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001278
1279 android_namespace_t* ns1 =
1280 android_create_namespace("ns1",
1281 nullptr,
1282 ns_search_path.c_str(),
1283 ANDROID_NAMESPACE_TYPE_ISOLATED,
1284 nullptr,
1285 nullptr);
1286
1287 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1288
1289 android_namespace_t* ns2 =
1290 android_create_namespace("ns1",
1291 nullptr,
1292 ns_search_path.c_str(),
1293 ANDROID_NAMESPACE_TYPE_ISOLATED,
1294 nullptr,
1295 nullptr);
1296
1297 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1298
1299 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1300 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1301
1302 android_dlextinfo extinfo;
1303 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1304 extinfo.library_namespace = ns1;
1305
1306 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1307 ASSERT_TRUE(handle == nullptr);
1308 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1309}
1310
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001311TEST(dlext, ns_isolated) {
1312 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001313 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001314
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001315 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001316 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001317 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1318
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001319 android_set_application_target_sdk_version(42U); // something > 23
1320
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001321 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001322
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001323 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001324 android_create_namespace("private",
1325 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001326 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001327 ANDROID_NAMESPACE_TYPE_REGULAR,
1328 nullptr,
1329 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001330 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001331 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001332
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001333 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001334 android_create_namespace("private_isolated1",
1335 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001336 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001337 ANDROID_NAMESPACE_TYPE_ISOLATED,
1338 nullptr,
1339 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001340 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001341 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001342
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001343 android_namespace_t* ns_isolated2 =
1344 android_create_namespace("private_isolated2",
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001345 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001346 nullptr,
1347 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001348 GetTestlibRoot().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001349 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001350 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001351 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001352
1353 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1354 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1355
1356 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001357 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001358
1359 // Load lib_private_external_path to default namespace
1360 // (it should remain invisible for the isolated namespaces after this)
1361 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1362 ASSERT_TRUE(handle != nullptr) << dlerror();
1363
1364 android_dlextinfo extinfo;
1365 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1366 extinfo.library_namespace = ns_not_isolated;
1367
1368 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1369 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1370
1371 extinfo.library_namespace = ns_isolated;
1372
1373 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1374 ASSERT_TRUE(handle2 == nullptr);
1375 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1376
1377 // Check dlopen by absolute path
1378 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1379 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001380 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001381 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001382 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001383
1384 extinfo.library_namespace = ns_isolated2;
1385
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001386 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001387 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001388 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1389 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001390
1391 // Check dlopen by absolute path
1392 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001393 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1394 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001395
1396 typedef const char* (*fn_t)();
1397 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1398 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1399
1400 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1401
1402 fn_t ns_get_private_extern_string =
1403 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1404 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1405
1406 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1407
1408 fn_t ns_get_public_extern_string =
1409 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1410 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1411
1412 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1413
1414 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1415 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1416
1417 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1418
1419 dlclose(handle1);
1420}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001421
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001422TEST(dlext, ns_shared) {
1423 static const char* root_lib = "libnstest_root_not_isolated.so";
1424 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001425
1426 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001427
Jiyong Park917d34a2017-08-31 14:07:13 +09001428 // create a parent namespace to use instead of the default namespace. This is
1429 // to make this test be independent from the configuration of the default
1430 // namespace.
1431 android_namespace_t* ns_parent =
1432 android_create_namespace("parent",
1433 nullptr,
1434 nullptr,
1435 ANDROID_NAMESPACE_TYPE_REGULAR,
1436 nullptr,
1437 nullptr);
1438 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1439 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1440
1441 android_dlextinfo extinfo;
1442 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1443 extinfo.library_namespace = ns_parent;
1444
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001445 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Jiyong Park917d34a2017-08-31 14:07:13 +09001446 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001447 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1448
1449 android_set_application_target_sdk_version(42U); // something > 23
1450
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001451 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001452
Jiyong Park917d34a2017-08-31 14:07:13 +09001453 // preload this library to the parent namespace to check if it
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001454 // is shared later on.
1455 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001456 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001457 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1458
Jiyong Park917d34a2017-08-31 14:07:13 +09001459 // create two child namespaces of 'ns_parent'. One with regular, the other
1460 // with isolated & shared.
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001461 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001462 android_create_namespace("private",
1463 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001464 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001465 ANDROID_NAMESPACE_TYPE_REGULAR,
1466 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001467 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001468 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001469 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1470 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001471
1472 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001473 android_create_namespace("private_isolated_shared",
1474 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001475 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001476 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001477 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001478 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001479 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001480 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1481 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001482
Jiyong Park917d34a2017-08-31 14:07:13 +09001483 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001484 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1485
1486 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001487 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001488
Jiyong Park917d34a2017-08-31 14:07:13 +09001489 // Load lib_private_external_path to the parent namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001490 // (it should remain invisible for the isolated namespaces after this)
Jiyong Park917d34a2017-08-31 14:07:13 +09001491 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001492 ASSERT_TRUE(handle != nullptr) << dlerror();
1493
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001494 extinfo.library_namespace = ns_not_isolated;
1495
1496 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1497 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1498
1499 extinfo.library_namespace = ns_isolated_shared;
1500
1501 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1502 ASSERT_TRUE(handle2 == nullptr);
1503 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1504
1505 // Check dlopen by absolute path
1506 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1507 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001508 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001509 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001510 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001511
1512 // load libnstest_root.so to shared namespace in order to check that everything is different
1513 // except shared libnstest_dlopened.so
1514
1515 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1516
1517 typedef const char* (*fn_t)();
1518 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1519 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1520 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1521 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1522
1523 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1524 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1525 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1526
1527 fn_t ns_get_private_extern_string =
1528 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1529 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1530 fn_t ns_get_private_extern_string_shared =
1531 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1532 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1533
1534 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1535 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1536 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1537
1538 fn_t ns_get_public_extern_string =
1539 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1540 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1541 fn_t ns_get_public_extern_string_shared =
1542 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1543 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1544
1545 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1546 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1547 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1548
1549 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1550 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1551 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1552 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1553 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1554 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1555
1556 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1557 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1558 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1559 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1560 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1561
1562 dlclose(handle1);
1563 dlclose(handle2);
1564}
1565
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001566TEST(dlext, ns_shared_links_and_paths) {
1567 // Create parent namespace (isolated, not shared)
1568 android_namespace_t* ns_isolated =
1569 android_create_namespace("private_isolated",
1570 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001571 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001572 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001573 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001574 nullptr);
1575 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1576 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1577
1578 // Create shared namespace with ns_isolated parent
1579 android_namespace_t* ns_shared =
1580 android_create_namespace("private_shared",
1581 nullptr,
1582 nullptr,
1583 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1584 nullptr,
1585 ns_isolated);
1586 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1587
1588 // 1. Load a library in ns_shared to check that it has inherited
1589 // search path and the link to the default namespace.
1590 android_dlextinfo extinfo;
1591 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1592 extinfo.library_namespace = ns_shared;
1593
1594 {
1595 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1596 ASSERT_TRUE(handle != nullptr) << dlerror();
1597 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1598 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1599 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1600
1601 dlclose(handle);
1602 }
1603 // 2. Load another test library by absolute path to check that
1604 // it has inherited permitted_when_isolated_path
1605 {
1606 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001607 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001608 RTLD_NOW,
1609 &extinfo);
1610
1611 ASSERT_TRUE(handle != nullptr) << dlerror();
1612 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1613 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1614 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1615
1616 dlclose(handle);
1617 }
1618
1619 // 3. Check that it is still isolated.
1620 {
1621 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001622 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001623 RTLD_NOW,
1624 &extinfo);
1625
1626 ASSERT_TRUE(handle == nullptr);
1627 }
1628}
1629
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001630TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001631 android_set_application_target_sdk_version(42U); // something > 23
1632
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001633 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001634
1635 // preload this library to the default namespace to check if it
1636 // is shared later on.
1637 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001638 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001639 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1640
1641 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001642 android_create_namespace("private_isolated_shared",
1643 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001644 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001645 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001646 nullptr,
1647 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001648 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001649 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001650
1651 // Check if "libnstest_dlopened.so" is loaded (and the same)
1652 android_dlextinfo extinfo;
1653 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1654 extinfo.library_namespace = ns_isolated_shared;
1655
1656 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1657 ASSERT_TRUE(handle != nullptr) << dlerror();
1658 ASSERT_TRUE(handle == handle_dlopened);
1659 dlclose(handle);
1660 dlclose(handle_dlopened);
1661
1662 // And now check that the library cannot be found by soname (and is no longer loaded)
1663 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1664 ASSERT_TRUE(handle == nullptr)
1665 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1666
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001667 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001668 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1669 ASSERT_TRUE(handle == nullptr)
1670 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1671
1672 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1673 ASSERT_TRUE(handle == nullptr)
1674 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1675
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001676 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001677 RTLD_NOW | RTLD_NOLOAD);
1678 ASSERT_TRUE(handle == nullptr)
1679 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1680
1681 // Now lets see if the soinfo area gets reused in the wrong way:
1682 // load a library to default namespace.
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001683 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001684 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1685 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1686
1687 // try to find it in shared namespace
1688 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1689 ASSERT_TRUE(handle == nullptr)
1690 << "Error: " << g_public_lib << " is accessible in shared namespace";
1691}
1692
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001693TEST(dlext, ns_isolated_rtld_global) {
1694 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001695 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001696
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001697 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001698
1699 android_namespace_t* ns1 =
1700 android_create_namespace("isolated1",
1701 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001702 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001703 ANDROID_NAMESPACE_TYPE_ISOLATED,
1704 lib_public_path.c_str(),
1705 nullptr);
1706 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001707 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001708
1709 android_namespace_t* ns2 =
1710 android_create_namespace("isolated2",
1711 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001712 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001713 ANDROID_NAMESPACE_TYPE_ISOLATED,
1714 lib_public_path.c_str(),
1715 nullptr);
1716 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001717 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001718
1719 android_dlextinfo extinfo;
1720 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1721 extinfo.library_namespace = ns1;
1722
1723 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1724 RTLD_GLOBAL,
1725 &extinfo);
1726
1727 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1728
1729 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001730 android_create_namespace("isolated1_child",
1731 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001732 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001733 ANDROID_NAMESPACE_TYPE_ISOLATED,
1734 nullptr,
1735 ns1);
1736
1737 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1738 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001739
1740 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1741 // attempt to use ns2 should result in dlerror()
1742
1743 // Check ns1_child first.
1744 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1745 extinfo.library_namespace = ns1_child;
1746
1747 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1748 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1749
1750 // now ns1
1751 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1752 extinfo.library_namespace = ns1;
1753
1754 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1755 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1756
1757 // and ns2 should fail
1758 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1759 extinfo.library_namespace = ns2;
1760
1761 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1762 ASSERT_TRUE(handle1 == nullptr);
1763 ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
1764}
1765
dimitry8db36a52017-10-23 15:10:10 +02001766TEST(dlext, ns_inaccessible_error_message) {
1767 // We set up 2 namespaces (a and b) and link a->b with a shared library
1768 // libtestshared.so. Then try to dlopen different library with the same
1769 // name from in namespace a. Note that library should not be accessible
1770 // in either namespace but since it's soname is in the list of shared libs
1771 // the linker will attempt to find it in linked namespace.
1772 //
1773 // Check the error message and make sure it mentions correct namespace name.
1774 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1775
1776 android_namespace_t* ns_a =
1777 android_create_namespace("ns_a",
1778 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001779 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001780 ANDROID_NAMESPACE_TYPE_ISOLATED,
1781 nullptr,
1782 nullptr);
1783 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1784 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1785
1786 android_namespace_t* ns_b =
1787 android_create_namespace("ns_b",
1788 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001789 GetTestlibRoot().c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001790 ANDROID_NAMESPACE_TYPE_ISOLATED,
1791 nullptr,
1792 nullptr);
1793 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1794 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1795
1796 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1797
1798 android_dlextinfo extinfo;
1799 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1800 extinfo.library_namespace = ns_a;
1801
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001802 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
dimitry8db36a52017-10-23 15:10:10 +02001803
1804 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1805 ASSERT_TRUE(handle == nullptr);
1806 std::string expected_dlerror =
1807 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1808 " is not accessible for the namespace \"ns_a\"",
1809 library_path.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001810 android::base::GetExecutablePath().c_str());
dimitry8db36a52017-10-23 15:10:10 +02001811 ASSERT_EQ(expected_dlerror, dlerror());
1812}
1813
dimitry321476a2018-01-29 15:32:37 +01001814extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1815 android_namespace_t* namespace_to);
1816
Logan Chien9ee45912018-01-18 12:05:09 +08001817TEST(dlext, ns_link_namespaces_invalid_arguments) {
1818 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1819
1820 android_namespace_t* ns =
1821 android_create_namespace("private",
1822 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001823 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001824 ANDROID_NAMESPACE_TYPE_REGULAR,
1825 nullptr,
1826 nullptr);
1827 ASSERT_TRUE(ns != nullptr) << dlerror();
1828
1829 // Test android_link_namespaces()
1830 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1831 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1832 dlerror());
1833
1834 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1835 ASSERT_STREQ("android_link_namespaces failed: "
1836 "error linking namespaces \"private\"->\"(default)\": "
1837 "the list of shared libraries is empty.", dlerror());
1838
1839 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1840 ASSERT_STREQ("android_link_namespaces failed: "
1841 "error linking namespaces \"private\"->\"(default)\": "
1842 "the list of shared libraries is empty.", dlerror());
1843
dimitry321476a2018-01-29 15:32:37 +01001844 // Test __loader_android_link_namespaces_all_libs()
1845 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001846 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1847 "error linking namespaces: namespace_from is null.", dlerror());
1848
dimitry321476a2018-01-29 15:32:37 +01001849 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
Logan Chien9ee45912018-01-18 12:05:09 +08001850 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1851 "error linking namespaces: namespace_from is null.", dlerror());
1852
dimitry321476a2018-01-29 15:32:37 +01001853 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001854 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1855 "error linking namespaces: namespace_to is null.", dlerror());
1856}
1857
1858TEST(dlext, ns_allow_all_shared_libs) {
1859 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1860
1861 android_namespace_t* ns_a =
1862 android_create_namespace("ns_a",
1863 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001864 (GetTestlibRoot() + "/ns_a").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001865 ANDROID_NAMESPACE_TYPE_ISOLATED,
1866 nullptr,
1867 nullptr);
1868 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1869 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1870
1871 android_namespace_t* ns_b =
1872 android_create_namespace("ns_b",
1873 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001874 (GetTestlibRoot() + "/ns_b").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001875 ANDROID_NAMESPACE_TYPE_ISOLATED,
1876 nullptr,
1877 nullptr);
1878 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1879 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1880
1881 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
dimitry321476a2018-01-29 15:32:37 +01001882 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
Logan Chien9ee45912018-01-18 12:05:09 +08001883
1884 // Load libs with android_dlopen_ext() from namespace b
1885 android_dlextinfo extinfo;
1886 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1887 extinfo.library_namespace = ns_b;
1888
1889 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1890 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1891
1892 void* ns_b_handle1_internal =
1893 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1894 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1895
1896 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1897 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1898
1899 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1900 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1901
1902 // Load libs with android_dlopen_ext() from namespace a
1903 extinfo.library_namespace = ns_a;
1904
1905 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1906 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1907
1908 void* ns_a_handle1_internal =
1909 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1910 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1911
1912 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1913 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1914
1915 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1916 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1917
1918 // Compare the dlopen handle
1919 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1920 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1921 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1922
1923 // Close libs
1924 dlclose(ns_b_handle1);
1925 dlclose(ns_b_handle2);
1926 dlclose(ns_b_handle3);
1927
1928 dlclose(ns_a_handle1);
1929 dlclose(ns_a_handle1_internal);
1930 dlclose(ns_a_handle2);
1931 dlclose(ns_a_handle3);
1932}
1933
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001934TEST(dlext, ns_anonymous) {
1935 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001936 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001937
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001938 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001939 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1940
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001941 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1942
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001943 ASSERT_TRUE(
1944 android_init_anonymous_namespace(shared_libs.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001945 (GetTestlibRoot() + "/private_namespace_libs").c_str())
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001946 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001947
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001948 android_namespace_t* ns =
1949 android_create_namespace("private",
1950 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001951 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001952 ANDROID_NAMESPACE_TYPE_REGULAR,
1953 nullptr,
1954 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001955
1956 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001957 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001958
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001959 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001960
1961 android_dlextinfo extinfo;
1962 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1963 extinfo.library_namespace = ns;
1964
1965 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1966 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1967 ASSERT_TRUE(handle != nullptr) << dlerror();
1968
1969 uintptr_t ns_get_dlopened_string_addr =
1970 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1971 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1972 typedef const char* (*fn_t)();
1973 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1974
1975 std::vector<map_record> maps;
1976 Maps::parse_maps(&maps);
1977
1978 uintptr_t addr_start = 0;
1979 uintptr_t addr_end = 0;
dimitry8eaf28d2017-10-11 10:04:14 +02001980 bool has_executable_segment = false;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001981 std::vector<map_record> maps_to_copy;
1982
1983 for (const auto& rec : maps) {
1984 if (rec.pathname == private_library_absolute_path) {
1985 if (addr_start == 0) {
1986 addr_start = rec.addr_start;
1987 }
1988 addr_end = rec.addr_end;
dimitry8eaf28d2017-10-11 10:04:14 +02001989 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001990
1991 maps_to_copy.push_back(rec);
1992 }
1993 }
1994
1995 // some sanity checks..
1996 ASSERT_TRUE(addr_start > 0);
1997 ASSERT_TRUE(addr_end > 0);
dimitry3b0a5b72018-06-06 11:11:25 +02001998 ASSERT_TRUE(maps_to_copy.size() > 0);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001999 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
2000 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
2001
dimitry8eaf28d2017-10-11 10:04:14 +02002002 if (!has_executable_segment) {
2003 // For some natively bridged environments this code might be missing
2004 // the executable flag. This is because the guest code is not supposed
2005 // to be executed directly and making it non-executable is more secure.
2006 // If this is the case we assume that the first segment is the one that
2007 // has this flag.
2008 ASSERT_TRUE((maps_to_copy[0].perms & PROT_WRITE) == 0);
2009 maps_to_copy[0].perms |= PROT_EXEC;
2010 }
2011
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002012 // copy
2013 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
2014 PROT_NONE, MAP_ANON | MAP_PRIVATE,
2015 -1, 0));
2016 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
2017
2018 for (const auto& rec : maps_to_copy) {
2019 uintptr_t offset = rec.addr_start - addr_start;
2020 size_t size = rec.addr_end - rec.addr_start;
2021 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
2022 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
2023 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
2024 ASSERT_TRUE(map != MAP_FAILED);
2025 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
2026 mprotect(map, size, rec.perms);
2027 }
2028
2029 // call the function copy
2030 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
2031 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
2032 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2033 ns_get_dlopened_string_anon());
2034
2035 // They should belong to different namespaces (private and anonymous)
2036 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2037 ns_get_dlopened_string_private());
2038
2039 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
2040}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002041
2042TEST(dlext, dlopen_handle_value_platform) {
2043 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2044 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
2045 << "dlopen should return odd value for the handle";
2046 dlclose(handle);
2047}
2048
2049TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08002050 android_set_application_target_sdk_version(__ANDROID_API_M__);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002051 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2052 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
2053 << "dlopen should return valid pointer";
2054 dlclose(handle);
2055}