blob: edeb4b19b54c507228b8c949a85b98bfc7cf304c [file] [log] [blame]
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <dlfcn.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080020#include <elf.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000021#include <errno.h>
22#include <fcntl.h>
Yabin Cui16f7f8d2014-11-04 11:08:05 -080023#include <inttypes.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000024#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070027
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000028#include <android/dlext.h>
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -070029#include <android-base/file.h>
Zhenhua WANG81aad002017-04-25 11:07:19 +080030#include <android-base/strings.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070031
32#include <linux/memfd.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000033#include <sys/mman.h>
Elliott Hughesd7c52622017-06-20 14:26:56 -070034#include <sys/syscall.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010035#include <sys/types.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070036#include <sys/vfs.h>
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000037#include <sys/wait.h>
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000038
Sandeep Patil4e02cc12019-01-21 14:22:05 -080039#include <meminfo/procmeminfo.h>
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040040#include <procinfo/process_map.h>
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -080041#include <ziparchive/zip_archive.h>
Torne (Richard Coles)26052612014-05-02 14:57:42 +010042
Dimitry Ivanov927877c2016-09-21 11:17:13 -070043#include "gtest_globals.h"
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -080044#include "utils.h"
Dimitry Ivanov41fd2952016-05-09 17:37:39 -070045#include "dlext_private.h"
Dimitry Ivanov708589f2016-09-19 10:50:28 -070046#include "dlfcn_symlink_support.h"
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000047
48#define ASSERT_DL_NOTNULL(ptr) \
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070049 ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000050
51#define ASSERT_DL_ZERO(i) \
52 ASSERT_EQ(0, i) << "dlerror: " << dlerror()
53
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +000054#define ASSERT_NOERROR(i) \
55 ASSERT_NE(-1, i) << "errno: " << strerror(errno)
56
Yabin Cui16f7f8d2014-11-04 11:08:05 -080057#define ASSERT_SUBSTR(needle, haystack) \
58 ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
59
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000060
61typedef int (*fn)(void);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070062constexpr const char* kLibName = "libdlext_test.so";
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -040063constexpr const char* kLibNameRecursive = "libdlext_test_recursive.so";
Dimitry Ivanov927877c2016-09-21 11:17:13 -070064constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
65constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
66constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070067
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000068class DlExtTest : public ::testing::Test {
69protected:
70 virtual void SetUp() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070071 handle_ = nullptr;
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000072 // verify that we don't have the library loaded already
Dimitry Ivanov927877c2016-09-21 11:17:13 -070073 void* h = dlopen(kLibName, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070074 ASSERT_TRUE(h == nullptr);
Dimitry Ivanov927877c2016-09-21 11:17:13 -070075 h = dlopen(kLibNameNoRelro, RTLD_NOW | RTLD_NOLOAD);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070076 ASSERT_TRUE(h == nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000077 // call dlerror() to swallow the error, and check it was the one we wanted
Dimitry Ivanov927877c2016-09-21 11:17:13 -070078 ASSERT_EQ(std::string("dlopen failed: library \"") + kLibNameNoRelro + "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000079 }
80
81 virtual void TearDown() {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -070082 if (handle_ != nullptr) {
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000083 ASSERT_DL_ZERO(dlclose(handle_));
84 }
85 }
86
87 void* handle_;
88};
89
90TEST_F(DlExtTest, ExtInfoNull) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -070091 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, nullptr);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +000092 ASSERT_DL_NOTNULL(handle_);
93 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
94 ASSERT_DL_NOTNULL(f);
95 EXPECT_EQ(4, f());
96}
97
98TEST_F(DlExtTest, ExtInfoNoFlags) {
99 android_dlextinfo extinfo;
100 extinfo.flags = 0;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700101 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000102 ASSERT_DL_NOTNULL(handle_);
103 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
104 ASSERT_DL_NOTNULL(f);
105 EXPECT_EQ(4, f());
106}
107
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700108TEST_F(DlExtTest, ExtInfoUseFd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700109 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_fd/libdlext_test_fd.so";
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700110
111 android_dlextinfo extinfo;
112 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700113 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700114 ASSERT_TRUE(extinfo.library_fd != -1);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700115 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700116 ASSERT_DL_NOTNULL(handle_);
117 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
118 ASSERT_DL_NOTNULL(f);
119 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700120
121 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
122 ASSERT_DL_NOTNULL(taxicab_number);
123 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov04dc91a2014-07-01 14:10:16 -0700124}
125
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700126TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700127 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700128
129 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700130 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700131 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800132
133 // Find the offset of the shared library in the zip.
134 ZipArchiveHandle handle;
135 ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
136 ZipEntry zip_entry;
137 ZipString zip_name;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700138 zip_name.name = reinterpret_cast<const uint8_t*>(kLibZipSimpleZip);
139 zip_name.name_length = strlen(kLibZipSimpleZip);
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800140 ASSERT_EQ(0, FindEntry(handle, zip_name, &zip_entry));
141 extinfo.library_fd_offset = zip_entry.offset;
142 CloseArchive(handle);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700143
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700144 handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700145 ASSERT_DL_NOTNULL(handle_);
146
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700147 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
148 ASSERT_DL_NOTNULL(taxicab_number);
149 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700150}
151
152TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700153 const std::string lib_path = GetTestlibRoot() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700154
155 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700156 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700157 extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700158 extinfo.library_fd_offset = 17;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700159
160 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
161 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700162 ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
163
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800164 // Test an address above 2^44, for http://b/18178121 .
165 extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700166 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700167 ASSERT_TRUE(handle_ == nullptr);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800168 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
169
170 extinfo.library_fd_offset = 0LL - PAGE_SIZE;
171 handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
172 ASSERT_TRUE(handle_ == nullptr);
173 ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
174
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700175 extinfo.library_fd_offset = 0;
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700176 handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
Yabin Cui16f7f8d2014-11-04 11:08:05 -0800177 ASSERT_TRUE(handle_ == nullptr);
Elliott Hughesa8971512018-06-27 14:39:06 -0700178 ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700179
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -0800180 // Check if dlsym works after unsuccessful dlopen().
181 // Supply non-exiting one to make linker visit every soinfo.
182 void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
183 ASSERT_TRUE(sym == nullptr);
184
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700185 close(extinfo.library_fd);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700186}
187
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800188TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700189 android_dlextinfo extinfo;
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700190 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
Christopher Ferrisc0ffcec2016-01-19 20:32:37 -0800191 // This offset will not be used, so it doesn't matter.
192 extinfo.library_fd_offset = 0;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700193
194 handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
195 ASSERT_TRUE(handle_ == nullptr);
Dmitriy Ivanova6c12792014-10-21 12:09:18 -0700196 ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700197}
198
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700199TEST(dlext, android_dlopen_ext_force_load_smoke) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700200 DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
201 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700202 // 1. Open actual file
203 void* handle = dlopen("libdlext_test.so", RTLD_NOW);
204 ASSERT_DL_NOTNULL(handle);
205 // 2. Open link with force_load flag set
206 android_dlextinfo extinfo;
207 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700208 void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700209 ASSERT_DL_NOTNULL(handle2);
210 ASSERT_TRUE(handle != handle2);
211
212 dlclose(handle2);
213 dlclose(handle);
214}
215
216TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700217 DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
218 const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700219 // Check if soname lookup still returns already loaded library
220 // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700221 void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700222 ASSERT_DL_NOTNULL(handle);
223
224 android_dlextinfo extinfo;
225 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
226
Dimitry Ivanov708589f2016-09-19 10:50:28 -0700227 // Note that 'libdlext_test.so' is dt_soname for the symlink_name
Dmitriy Ivanov9b821362015-04-02 16:03:56 -0700228 void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
229
230 ASSERT_DL_NOTNULL(handle2);
231 ASSERT_TRUE(handle == handle2);
232
233 dlclose(handle2);
234 dlclose(handle);
235}
236
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700237TEST(dlfcn, dlopen_from_zip_absolute_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700238 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700239 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700240
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700241 void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700242 ASSERT_TRUE(handle != nullptr) << dlerror();
243
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700244 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
245 ASSERT_DL_NOTNULL(taxicab_number);
246 EXPECT_EQ(1729U, *taxicab_number);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700247
248 dlclose(handle);
249}
250
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700251TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700252 const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700253 const std::string lib_path = GetTestlibRoot() + lib_zip_path;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700254
255 void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
256
257 ASSERT_TRUE(handle != nullptr) << dlerror();
258
259 typedef void *(* dlopen_b_fn)();
260 dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
261 ASSERT_TRUE(fn != nullptr) << dlerror();
262
263 void *p = fn();
264 ASSERT_TRUE(p != nullptr) << dlerror();
265
266 dlclose(p);
267 dlclose(handle);
268}
269
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700270TEST(dlfcn, dlopen_from_zip_ld_library_path) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700271 const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700272 const std::string lib_path = GetTestlibRoot() + lib_zip_path + "!/libdir";
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700273
274 typedef void (*fn_t)(const char*);
275 fn_t android_update_LD_LIBRARY_PATH =
276 reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
277
278 ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
279
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700280 void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700281 ASSERT_TRUE(handle == nullptr);
282
283 android_update_LD_LIBRARY_PATH(lib_path.c_str());
284
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700285 handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700286 ASSERT_TRUE(handle != nullptr) << dlerror();
287
288 int (*fn)(void);
289 fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
290 ASSERT_TRUE(fn != nullptr);
291 EXPECT_EQ(4, fn());
292
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800293 uint32_t* taxicab_number =
294 reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700295 ASSERT_DL_NOTNULL(taxicab_number);
296 EXPECT_EQ(1729U, *taxicab_number);
297
Dmitriy Ivanov52393a52015-03-18 22:50:01 -0700298 dlclose(handle);
299}
300
301
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000302TEST_F(DlExtTest, Reserved) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700303 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000304 ASSERT_TRUE(start != MAP_FAILED);
305 android_dlextinfo extinfo;
306 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
307 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700308 extinfo.reserved_size = kLibSize;
309 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000310 ASSERT_DL_NOTNULL(handle_);
311 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
312 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700313 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000314 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700315 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000316 EXPECT_EQ(4, f());
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800317
318 // Check that after dlclose reserved address space is unmapped (and can be reused)
319 dlclose(handle_);
320 handle_ = nullptr;
321
322 void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
323 ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000324}
325
326TEST_F(DlExtTest, ReservedTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800327 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000328 ASSERT_TRUE(start != MAP_FAILED);
329 android_dlextinfo extinfo;
330 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
331 extinfo.reserved_addr = start;
332 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700333 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700334 EXPECT_EQ(nullptr, handle_);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000335}
336
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400337TEST_F(DlExtTest, ReservedRecursive) {
338 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
339 ASSERT_TRUE(start != MAP_FAILED);
340 android_dlextinfo extinfo;
341 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
342 extinfo.reserved_addr = start;
343 extinfo.reserved_size = kLibSize;
344 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
345 ASSERT_DL_NOTNULL(handle_);
346
347 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
348 ASSERT_DL_NOTNULL(f);
349 EXPECT_GE(reinterpret_cast<void*>(f), start);
350 EXPECT_LT(reinterpret_cast<void*>(f),
351 reinterpret_cast<char*>(start) + kLibSize);
352 EXPECT_EQ(4, f());
353
354 f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
355 ASSERT_DL_NOTNULL(f);
356 EXPECT_GE(reinterpret_cast<void*>(f), start);
357 EXPECT_LT(reinterpret_cast<void*>(f),
358 reinterpret_cast<char*>(start) + kLibSize);
359 EXPECT_EQ(8, f());
360
361 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
362 ASSERT_DL_NOTNULL(taxicab_number);
363 EXPECT_GE(reinterpret_cast<void*>(taxicab_number), start);
364 EXPECT_LT(reinterpret_cast<void*>(taxicab_number), reinterpret_cast<char*>(start) + kLibSize);
365 EXPECT_EQ(1729U, *taxicab_number);
366}
367
368TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
369 void* start = mmap(nullptr, kLibSize/2, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
370 ASSERT_TRUE(start != MAP_FAILED);
371 android_dlextinfo extinfo;
372 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
373 extinfo.reserved_addr = start;
374 extinfo.reserved_size = kLibSize/2;
375 handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
376 EXPECT_EQ(nullptr, handle_);
377}
378
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000379TEST_F(DlExtTest, ReservedHint) {
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700380 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000381 ASSERT_TRUE(start != MAP_FAILED);
382 android_dlextinfo extinfo;
383 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
384 extinfo.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700385 extinfo.reserved_size = kLibSize;
386 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000387 ASSERT_DL_NOTNULL(handle_);
388 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
389 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700390 EXPECT_GE(reinterpret_cast<void*>(f), start);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000391 EXPECT_LT(reinterpret_cast<void*>(f),
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700392 reinterpret_cast<char*>(start) + kLibSize);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000393 EXPECT_EQ(4, f());
394}
395
396TEST_F(DlExtTest, ReservedHintTooSmall) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800397 void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000398 ASSERT_TRUE(start != MAP_FAILED);
399 android_dlextinfo extinfo;
400 extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
401 extinfo.reserved_addr = start;
402 extinfo.reserved_size = PAGE_SIZE;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700403 handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000404 ASSERT_DL_NOTNULL(handle_);
405 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
406 ASSERT_DL_NOTNULL(f);
Chih-Hung Hsieha2c6ae62014-08-27 13:45:37 -0700407 EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
408 (reinterpret_cast<void*>(f) >=
409 reinterpret_cast<char*>(start) + PAGE_SIZE));
Torne (Richard Coles)12bbb912014-02-06 14:34:21 +0000410 EXPECT_EQ(4, f());
411}
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000412
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100413class DlExtRelroSharingTest : public DlExtTest {
414protected:
415 virtual void SetUp() {
416 DlExtTest::SetUp();
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700417 void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100418 ASSERT_TRUE(start != MAP_FAILED);
419 extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
420 extinfo_.reserved_addr = start;
Dimitry Ivanov927877c2016-09-21 11:17:13 -0700421 extinfo_.reserved_size = kLibSize;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100422 extinfo_.relro_fd = -1;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000423 }
424
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100425 virtual void TearDown() {
426 DlExtTest::TearDown();
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100427 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000428
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400429 void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
Elliott Hughes5cec3772018-01-19 15:45:23 -0800430 int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100431 ASSERT_NOERROR(relro_fd);
432
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400433 if (recursive) {
434 extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
435 }
436
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100437 pid_t pid = fork();
438 if (pid == 0) {
439 // child process
440 extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
441 extinfo_.relro_fd = relro_fd;
442 void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700443 if (handle == nullptr) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100444 fprintf(stderr, "in child: %s\n", dlerror());
445 exit(1);
446 }
447 exit(0);
448 }
449
450 // continuing in parent
451 ASSERT_NOERROR(close(relro_fd));
452 ASSERT_NOERROR(pid);
Elliott Hughes33697a02016-01-26 13:04:57 -0800453 AssertChildExited(pid, 0);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100454
455 // reopen file for reading so it can be used
Elliott Hughes5cec3772018-01-19 15:45:23 -0800456 relro_fd = open(relro_file, O_RDONLY | O_CLOEXEC);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100457 ASSERT_NOERROR(relro_fd);
458 extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
459 extinfo_.relro_fd = relro_fd;
460 }
461
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400462 void TryUsingRelro(const char* lib, bool recursive) {
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100463 handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
464 ASSERT_DL_NOTNULL(handle_);
465 fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
466 ASSERT_DL_NOTNULL(f);
467 EXPECT_EQ(4, f());
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700468
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400469 if (recursive) {
470 fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
471 ASSERT_DL_NOTNULL(f);
472 EXPECT_EQ(8, f());
473 }
474
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800475 uint32_t* taxicab_number =
476 reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -0700477 ASSERT_DL_NOTNULL(taxicab_number);
478 EXPECT_EQ(1729U, *taxicab_number);
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100479 }
480
Zhenhua WANG81aad002017-04-25 11:07:19 +0800481 void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
482 size_t* pss_out);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100483
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400484 std::string FindMappingName(void* ptr);
485
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100486 android_dlextinfo extinfo_;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100487};
488
489TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800490 TemporaryFile tf; // Use tf to get an unique filename.
491 ASSERT_NOERROR(close(tf.fd));
492
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400493 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
494 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
495 void* relro_data = dlsym(handle_, "lots_of_relro");
496 ASSERT_DL_NOTNULL(relro_data);
497 EXPECT_EQ(tf.path, FindMappingName(relro_data));
498
499 // Use destructor of tf to close and unlink the file.
500 tf.fd = extinfo_.relro_fd;
501}
502
503TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
504 TemporaryFile tf; // Use tf to get an unique filename.
505 ASSERT_NOERROR(close(tf.fd));
506
507 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
508 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
509 void* relro_data = dlsym(handle_, "lots_of_relro");
510 ASSERT_DL_NOTNULL(relro_data);
511 EXPECT_EQ(tf.path, FindMappingName(relro_data));
512 void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
513 ASSERT_DL_NOTNULL(recursive_relro_data);
514 EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
515
Yabin Cui294d1e22014-12-07 20:43:37 -0800516
517 // Use destructor of tf to close and unlink the file.
518 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100519}
520
521TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800522 TemporaryFile tf; // // Use tf to get an unique filename.
523 ASSERT_NOERROR(close(tf.fd));
524
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400525 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
526 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800527
528 // Use destructor of tf to close and unlink the file.
529 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26ec9672014-04-30 15:48:40 +0100530}
531
532TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400533 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +0000534}
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100535
536TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
Dan Albert69fb9f32014-09-03 11:30:21 -0700537 if (geteuid() != 0) {
538 GTEST_LOG_(INFO) << "This test must be run as root.\n";
539 return;
540 }
541
Yabin Cui294d1e22014-12-07 20:43:37 -0800542 TemporaryFile tf; // Use tf to get an unique filename.
543 ASSERT_NOERROR(close(tf.fd));
544
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400545 ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
Yabin Cui294d1e22014-12-07 20:43:37 -0800546
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100547 int pipefd[2];
548 ASSERT_NOERROR(pipe(pipefd));
549
550 size_t without_sharing, with_sharing;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -0800551 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
552 ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
Zhenhua WANG81aad002017-04-25 11:07:19 +0800553 ASSERT_LT(with_sharing, without_sharing);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100554
Zhenhua WANG81aad002017-04-25 11:07:19 +0800555 // We expect the sharing to save at least 50% of the library's total PSS.
556 // In practice it saves 80%+ for this library in the test.
557 size_t pss_saved = without_sharing - with_sharing;
558 size_t expected_min_saved = without_sharing / 2;
559
560 EXPECT_LT(expected_min_saved, pss_saved);
Yabin Cui294d1e22014-12-07 20:43:37 -0800561
562 // Use destructor of tf to close and unlink the file.
563 tf.fd = extinfo_.relro_fd;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100564}
565
Zhenhua WANG81aad002017-04-25 11:07:19 +0800566void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
567 size_t* total_pss) {
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800568 android::meminfo::ProcMemInfo proc_mem(pid);
569 const std::vector<android::meminfo::Vma>& maps = proc_mem.Maps();
570 ASSERT_GT(maps.size(), 0UL);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100571
Zhenhua WANG81aad002017-04-25 11:07:19 +0800572 // Calculate total PSS of the library.
573 *total_pss = 0;
574 bool saw_relro_file = false;
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800575 for (auto& vma : maps) {
576 if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
577 if (vma.name == relro_file) {
578 saw_relro_file = true;
579 }
Zhenhua WANG81aad002017-04-25 11:07:19 +0800580
Sandeep Patil4e02cc12019-01-21 14:22:05 -0800581 *total_pss += vma.usage.pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800582 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100583 }
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100584
Zhenhua WANG81aad002017-04-25 11:07:19 +0800585 if (shared_relro) ASSERT_TRUE(saw_relro_file);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100586}
587
Zhenhua WANG81aad002017-04-25 11:07:19 +0800588void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
589 bool share_relro, size_t* pss_out) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100590 const int CHILDREN = 20;
591
592 // Create children
Elliott Hughes33697a02016-01-26 13:04:57 -0800593 pid_t child_pids[CHILDREN];
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100594 int childpipe[CHILDREN];
595 for (int i=0; i<CHILDREN; ++i) {
596 char read_buf;
597 int child_done_pipe[2], parent_done_pipe[2];
598 ASSERT_NOERROR(pipe(child_done_pipe));
599 ASSERT_NOERROR(pipe(parent_done_pipe));
600
601 pid_t child = fork();
602 if (child == 0) {
603 // close the 'wrong' ends of the pipes in the child
604 close(child_done_pipe[0]);
605 close(parent_done_pipe[1]);
606
607 // open the library
608 void* handle;
609 if (share_relro) {
610 handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
611 } else {
612 handle = dlopen(lib, RTLD_NOW);
613 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -0700614 if (handle == nullptr) {
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100615 fprintf(stderr, "in child: %s\n", dlerror());
616 exit(1);
617 }
618
619 // close write end of child_done_pipe to signal the parent that we're done.
620 close(child_done_pipe[1]);
621
622 // wait for the parent to close parent_done_pipe, then exit
623 read(parent_done_pipe[0], &read_buf, 1);
624 exit(0);
625 }
626
627 ASSERT_NOERROR(child);
628
629 // close the 'wrong' ends of the pipes in the parent
630 close(child_done_pipe[1]);
631 close(parent_done_pipe[0]);
632
633 // wait for the child to be done
634 read(child_done_pipe[0], &read_buf, 1);
635 close(child_done_pipe[0]);
636
637 // save the child's pid and the parent_done_pipe
Elliott Hughes33697a02016-01-26 13:04:57 -0800638 child_pids[i] = child;
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100639 childpipe[i] = parent_done_pipe[1];
640 }
641
Zhenhua WANG81aad002017-04-25 11:07:19 +0800642 // Sum the PSS of tested library of all the children
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100643 size_t total_pss = 0;
644 for (int i=0; i<CHILDREN; ++i) {
645 size_t child_pss;
Zhenhua WANG81aad002017-04-25 11:07:19 +0800646 ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100647 total_pss += child_pss;
648 }
649 *pss_out = total_pss;
650
651 // Close pipes and wait for children to exit
652 for (int i=0; i<CHILDREN; ++i) {
653 ASSERT_NOERROR(close(childpipe[i]));
654 }
Elliott Hughes33697a02016-01-26 13:04:57 -0800655 for (int i = 0; i < CHILDREN; ++i) {
656 AssertChildExited(child_pids[i], 0);
Torne (Richard Coles)26052612014-05-02 14:57:42 +0100657 }
658}
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700659
Torne (Richard Coles)efbe9a52018-10-17 15:59:38 -0400660std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
661 uint64_t addr = reinterpret_cast<uint64_t>(ptr);
662 std::string found_name = "<not found>";
663
664 EXPECT_TRUE(android::procinfo::ReadMapFile(
665 "/proc/self/maps",
666 [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
667 if (addr >= start && addr < end) {
668 found_name = name;
669 }
670 }));
671
672 return found_name;
673}
674
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700675// Testing namespaces
676static const char* g_public_lib = "libnstest_public.so";
677
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800678// These are libs shared with default namespace
679static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
680
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700681TEST(dlext, ns_smoke) {
682 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800683 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700684
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800685 ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
686 ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
687 " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
688 dlerror());
Dimitry Ivanov54807612016-04-21 14:57:38 -0700689
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700690 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -0800691 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700692 ASSERT_TRUE(handle_public != nullptr) << dlerror();
693
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800694 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700695
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800696 // Check that libraries added to public namespace are not NODELETE
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700697 dlclose(handle_public);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800698 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800699 ASSERT_TRUE(handle_public == nullptr);
700 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
701 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
702
703 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700704
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800705 // create "public namespace", share limited set of public libraries with
706
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800707 android_namespace_t* ns1 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800708 android_create_namespace("private",
709 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700710 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800711 ANDROID_NAMESPACE_TYPE_REGULAR,
712 nullptr,
713 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700714 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800715 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700716
Dimitry Ivanov7331fe12015-12-14 14:11:17 -0800717 android_namespace_t* ns2 =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800718 android_create_namespace("private_isolated",
719 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700720 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800721 ANDROID_NAMESPACE_TYPE_ISOLATED,
722 nullptr,
723 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700724 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800725 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700726
727 // This should not have affect search path for default namespace:
728 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
729 void* handle = dlopen(g_public_lib, RTLD_NOW);
730 ASSERT_TRUE(handle != nullptr) << dlerror();
731 dlclose(handle);
732
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700733 // dlopen for a public library using an absolute path should work
734 // 1. For isolated namespaces
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700735 android_dlextinfo extinfo;
736 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -0700737 extinfo.library_namespace = ns2;
738 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
739 ASSERT_TRUE(handle != nullptr) << dlerror();
740 ASSERT_TRUE(handle == handle_public);
741
742 dlclose(handle);
743
744 // 1.1 even if it wasn't loaded before
745 dlclose(handle_public);
746
747 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
748 ASSERT_TRUE(handle_public == nullptr);
749 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
750 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
751
752 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
753 ASSERT_TRUE(handle != nullptr) << dlerror();
754
755 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
756 ASSERT_TRUE(handle == handle_public);
757
758 dlclose(handle);
759
760 // 2. And for regular namespaces (make sure it does not load second copy of the library)
761 extinfo.library_namespace = ns1;
762 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
763 ASSERT_TRUE(handle != nullptr) << dlerror();
764 ASSERT_TRUE(handle == handle_public);
765
766 dlclose(handle);
767
768 // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
769 // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
770 dlclose(handle_public);
771
772 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
773 ASSERT_TRUE(handle_public == nullptr);
774 ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
775 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
776
777 handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
778 ASSERT_TRUE(handle != nullptr) << dlerror();
779
780 handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
781
782 ASSERT_TRUE(handle != handle_public);
783
784 dlclose(handle);
785
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700786 extinfo.library_namespace = ns1;
787
788 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
789 ASSERT_TRUE(handle1 != nullptr) << dlerror();
790
791 extinfo.library_namespace = ns2;
792 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
793 ASSERT_TRUE(handle2 != nullptr) << dlerror();
794
795 ASSERT_TRUE(handle1 != handle2);
796
797 typedef const char* (*fn_t)();
798
799 fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
800 ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
801 fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
802 ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
803
804 EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
805 EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
806
807 ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
808
809 fn_t ns_get_private_extern_string1 =
810 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
811 ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
812 fn_t ns_get_private_extern_string2 =
813 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
814 ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
815
816 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
817 EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
818
819 ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
820
821 fn_t ns_get_public_extern_string1 =
822 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
823 ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
824 fn_t ns_get_public_extern_string2 =
825 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
826 ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
827
828 EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
829 ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
830
831 // and now check that dlopen() does the right thing in terms of preserving namespace
832 fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
833 ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
834 fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
835 ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
836
837 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
838 EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
839
840 ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
841
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800842 // Check that symbols from non-shared libraries a shared library depends on are not visible
843 // from original namespace.
844
845 fn_t ns_get_internal_extern_string =
846 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
847 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
848 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
849 "ns_get_internal_extern_string() expected to return null but returns \"" <<
850 ns_get_internal_extern_string() << "\"";
851
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700852 dlclose(handle1);
853
854 // Check if handle2 is still alive (and well)
855 ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
856 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
857 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
858 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
859
860 dlclose(handle2);
861}
862
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700863TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700864 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700865
866 int tmpfd = TEMP_FAILURE_RETRY(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700867 open(GetTestlibRoot().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700868
869 // Ignore kernels without O_TMPFILE flag support
870 if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
871 return;
872 }
873
874 ASSERT_TRUE(tmpfd != -1) << strerror(errno);
875
876 android_namespace_t* ns =
877 android_create_namespace("testing-o_tmpfile",
878 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700879 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700880 ANDROID_NAMESPACE_TYPE_ISOLATED,
881 nullptr,
882 nullptr);
883
884 ASSERT_DL_NOTNULL(ns);
885
886 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
887
888 std::string content;
889 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
890 ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
891
892 android_dlextinfo extinfo;
893 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
894 extinfo.library_fd = tmpfd;
895 extinfo.library_namespace = ns;
896
897 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
898
899 ASSERT_DL_NOTNULL(handle);
900
901 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
902 ASSERT_DL_NOTNULL(taxicab_number);
903 EXPECT_EQ(1729U, *taxicab_number);
904 dlclose(handle);
905}
906
907TEST(dlext, dlopen_ext_use_memfd) {
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700908 const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700909
910 // create memfd
911 int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
912 if (memfd == -1 && errno == ENOSYS) {
913 return;
914 }
915
916 ASSERT_TRUE(memfd != -1) << strerror(errno);
917
918 // Check st.f_type is TMPFS_MAGIC for memfd
919 struct statfs st;
920 ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
921 ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
922
923 android_namespace_t* ns =
924 android_create_namespace("testing-memfd",
925 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700926 GetTestlibRoot().c_str(),
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -0700927 ANDROID_NAMESPACE_TYPE_ISOLATED,
928 nullptr,
929 nullptr);
930
931 ASSERT_DL_NOTNULL(ns);
932
933 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
934
935 // read file into memfd backed one.
936 std::string content;
937 ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
938 ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
939
940 android_dlextinfo extinfo;
941 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
942 extinfo.library_fd = memfd;
943 extinfo.library_namespace = ns;
944
945 void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
946
947 ASSERT_DL_NOTNULL(handle);
948
949 uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
950 ASSERT_DL_NOTNULL(taxicab_number);
951 EXPECT_EQ(1729U, *taxicab_number);
952 dlclose(handle);
953}
954
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800955TEST(dlext, ns_symbol_visibilty_one_namespace) {
956 static const char* root_lib = "libnstest_root.so";
957 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
958
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700959 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs:" +
960 GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800961
962 android_namespace_t* ns =
963 android_create_namespace("one",
964 nullptr,
965 ns_search_path.c_str(),
966 ANDROID_NAMESPACE_TYPE_ISOLATED,
967 nullptr,
968 nullptr);
969
970 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
971
972 android_dlextinfo extinfo;
973 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
974 extinfo.library_namespace = ns;
975
976 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
977 ASSERT_TRUE(handle != nullptr) << dlerror();
978
979 typedef const char* (*fn_t)();
980
981 // Check that relocation worked correctly
982 fn_t ns_get_internal_extern_string =
983 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
984 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
985 ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
986
987 fn_t internal_extern_string_fn =
988 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
989 ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
990 ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
991}
992
993TEST(dlext, ns_symbol_visibilty_between_namespaces) {
994 static const char* root_lib = "libnstest_root.so";
995 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
996
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -0700997 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
998 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800999
1000 android_namespace_t* ns_public =
1001 android_create_namespace("public",
1002 nullptr,
1003 public_ns_search_path.c_str(),
1004 ANDROID_NAMESPACE_TYPE_ISOLATED,
1005 nullptr,
1006 nullptr);
1007
1008 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1009
1010 android_namespace_t* ns_private =
1011 android_create_namespace("private",
1012 nullptr,
1013 private_ns_search_path.c_str(),
1014 ANDROID_NAMESPACE_TYPE_ISOLATED,
1015 nullptr,
1016 nullptr);
1017
1018 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1019 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1020
1021 android_dlextinfo extinfo;
1022 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1023 extinfo.library_namespace = ns_private;
1024
1025 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1026 ASSERT_TRUE(handle != nullptr) << dlerror();
1027
1028 typedef const char* (*fn_t)();
1029
1030 // Check that relocation worked correctly
1031 fn_t ns_get_internal_extern_string =
1032 reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
1033 ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
1034 ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
1035 "ns_get_internal_extern_string() expected to return null but returns \"" <<
1036 ns_get_internal_extern_string() << "\"";
1037
1038 fn_t internal_extern_string_fn =
1039 reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
1040 ASSERT_TRUE(internal_extern_string_fn == nullptr);
1041 ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
1042}
1043
1044TEST(dlext, ns_unload_between_namespaces) {
1045 static const char* root_lib = "libnstest_root.so";
1046 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1047
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001048 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1049 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001050
1051 android_namespace_t* ns_public =
1052 android_create_namespace("public",
1053 nullptr,
1054 public_ns_search_path.c_str(),
1055 ANDROID_NAMESPACE_TYPE_ISOLATED,
1056 nullptr,
1057 nullptr);
1058
1059 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1060
1061 android_namespace_t* ns_private =
1062 android_create_namespace("private",
1063 nullptr,
1064 private_ns_search_path.c_str(),
1065 ANDROID_NAMESPACE_TYPE_ISOLATED,
1066 nullptr,
1067 nullptr);
1068
1069 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
1070 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1071
1072 android_dlextinfo extinfo;
1073 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1074 extinfo.library_namespace = ns_private;
1075
1076 void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1077 ASSERT_TRUE(handle != nullptr) << dlerror();
1078
1079 dlclose(handle);
1080 // Check that root_lib was unloaded
1081 handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1082 ASSERT_TRUE(handle == nullptr);
1083 ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
1084 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1085
1086 // Check that shared library was unloaded in public ns
1087 extinfo.library_namespace = ns_public;
1088 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1089 ASSERT_TRUE(handle == nullptr);
1090 ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
1091 "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
1092}
1093
dimitry965d06d2017-11-28 16:03:07 +01001094TEST(dlext, ns_unload_between_namespaces_missing_symbol_direct) {
1095 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1096
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001097 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1098 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001099
1100 android_namespace_t* ns_public =
1101 android_create_namespace("public",
1102 nullptr,
1103 public_ns_search_path.c_str(),
1104 ANDROID_NAMESPACE_TYPE_ISOLATED,
1105 nullptr,
1106 nullptr);
1107
1108 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1109
1110 android_namespace_t* ns_private =
1111 android_create_namespace("private",
1112 nullptr,
1113 private_ns_search_path.c_str(),
1114 ANDROID_NAMESPACE_TYPE_ISOLATED,
1115 nullptr,
1116 nullptr);
1117
1118 ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, "libtest_missing_symbol.so")) << dlerror();
1119 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1120
1121 android_dlextinfo extinfo;
1122 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1123 extinfo.library_namespace = ns_private;
1124
1125 void* handle = android_dlopen_ext((public_ns_search_path + "/libtest_missing_symbol.so").c_str(),
1126 RTLD_NOW,
1127 &extinfo);
1128 ASSERT_TRUE(handle == nullptr);
1129 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1130 public_ns_search_path + "/libtest_missing_symbol.so\"...",
1131 dlerror());
1132}
1133
1134TEST(dlext, ns_unload_between_namespaces_missing_symbol_indirect) {
1135 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1136
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001137 const std::string public_ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
1138 const std::string private_ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
dimitry965d06d2017-11-28 16:03:07 +01001139
1140 android_namespace_t* ns_public =
1141 android_create_namespace("public",
1142 nullptr,
1143 public_ns_search_path.c_str(),
1144 ANDROID_NAMESPACE_TYPE_ISOLATED,
1145 nullptr,
1146 nullptr);
1147
1148 ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
1149
1150 android_namespace_t* ns_private =
1151 android_create_namespace("private",
1152 nullptr,
1153 private_ns_search_path.c_str(),
1154 ANDROID_NAMESPACE_TYPE_ISOLATED,
1155 nullptr,
1156 nullptr);
1157
1158 ASSERT_TRUE(android_link_namespaces(ns_private,
1159 ns_public,
1160 "libnstest_public.so:libtest_missing_symbol_child_public.so")
1161 ) << dlerror();
1162 ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
1163
1164 android_dlextinfo extinfo;
1165 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1166 extinfo.library_namespace = ns_private;
1167
1168 void* handle = android_dlopen_ext("libtest_missing_symbol_root.so", RTLD_NOW, &extinfo);
1169 ASSERT_TRUE(handle == nullptr);
1170 ASSERT_EQ(std::string("dlopen failed: cannot locate symbol \"dlopen_testlib_missing_symbol\" referenced by \"") +
1171 private_ns_search_path + "/libtest_missing_symbol_root.so\"...",
1172 dlerror());
1173}
1174
Jiyong Park37b91af2017-05-05 22:07:05 +09001175TEST(dlext, ns_greylist_enabled) {
Dimitry Ivanov18623142017-02-21 13:41:08 -08001176 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1177
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001178 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Dimitry Ivanov18623142017-02-21 13:41:08 -08001179
1180 android_namespace_t* ns =
1181 android_create_namespace("namespace",
1182 nullptr,
1183 ns_search_path.c_str(),
Jiyong Park37b91af2017-05-05 22:07:05 +09001184 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
Dimitry Ivanov18623142017-02-21 13:41:08 -08001185 nullptr,
1186 nullptr);
1187
1188 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1189
1190 android_dlextinfo extinfo;
1191 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1192 extinfo.library_namespace = ns;
1193
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001194 // An app targeting M can open libnativehelper.so because it's on the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001195 android_set_application_target_sdk_version(__ANDROID_API_M__);
1196 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1197 ASSERT_TRUE(handle != nullptr) << dlerror();
1198
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001199 // Check that loader did not load another copy of libdl.so while loading greylisted library.
1200 void* dlsym_ptr = dlsym(handle, "dlsym");
1201 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
1202 ASSERT_EQ(&dlsym, dlsym_ptr);
1203
Dimitry Ivanov18623142017-02-21 13:41:08 -08001204 dlclose(handle);
1205
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001206 // An app targeting N no longer has the greylist.
Dimitry Ivanov18623142017-02-21 13:41:08 -08001207 android_set_application_target_sdk_version(__ANDROID_API_N__);
1208 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1209 ASSERT_TRUE(handle == nullptr);
1210 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1211}
1212
Jiyong Park37b91af2017-05-05 22:07:05 +09001213TEST(dlext, ns_greylist_disabled_by_default) {
1214 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1215
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001216 const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
Jiyong Park37b91af2017-05-05 22:07:05 +09001217
1218 android_namespace_t* ns =
1219 android_create_namespace("namespace",
1220 nullptr,
1221 ns_search_path.c_str(),
1222 ANDROID_NAMESPACE_TYPE_ISOLATED,
1223 nullptr,
1224 nullptr);
1225
1226 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
1227
1228 android_dlextinfo extinfo;
1229 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1230 extinfo.library_namespace = ns;
1231
1232 android_set_application_target_sdk_version(__ANDROID_API_M__);
1233 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
1234 ASSERT_TRUE(handle == nullptr);
1235 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
1236}
1237
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001238TEST(dlext, ns_cyclic_namespaces) {
1239 // Test that ns1->ns2->ns1 link does not break the loader
1240 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1241 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
1242
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001243 const std::string ns_search_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001244
1245 android_namespace_t* ns1 =
1246 android_create_namespace("ns1",
1247 nullptr,
1248 ns_search_path.c_str(),
1249 ANDROID_NAMESPACE_TYPE_ISOLATED,
1250 nullptr,
1251 nullptr);
1252
1253 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
1254
1255 android_namespace_t* ns2 =
1256 android_create_namespace("ns1",
1257 nullptr,
1258 ns_search_path.c_str(),
1259 ANDROID_NAMESPACE_TYPE_ISOLATED,
1260 nullptr,
1261 nullptr);
1262
1263 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
1264
1265 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
1266 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
1267
1268 android_dlextinfo extinfo;
1269 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1270 extinfo.library_namespace = ns1;
1271
1272 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
1273 ASSERT_TRUE(handle == nullptr);
1274 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
1275}
1276
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001277TEST(dlext, ns_isolated) {
1278 static const char* root_lib = "libnstest_root_not_isolated.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001279 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001280
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001281 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001282 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001283 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1284
Dmitriy Ivanov3cc35e22015-11-17 18:36:50 -08001285 android_set_application_target_sdk_version(42U); // something > 23
1286
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001287 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001288
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001289 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001290 android_create_namespace("private",
1291 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001292 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001293 ANDROID_NAMESPACE_TYPE_REGULAR,
1294 nullptr,
1295 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001296 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001297 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001298
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001299 android_namespace_t* ns_isolated =
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001300 android_create_namespace("private_isolated1",
1301 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001302 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001303 ANDROID_NAMESPACE_TYPE_ISOLATED,
1304 nullptr,
1305 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001306 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001307 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001308
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001309 android_namespace_t* ns_isolated2 =
1310 android_create_namespace("private_isolated2",
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001311 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001312 nullptr,
1313 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001314 GetTestlibRoot().c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001315 nullptr);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001316 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001317 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001318
1319 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
1320 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1321
1322 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001323 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001324
1325 // Load lib_private_external_path to default namespace
1326 // (it should remain invisible for the isolated namespaces after this)
1327 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
1328 ASSERT_TRUE(handle != nullptr) << dlerror();
1329
1330 android_dlextinfo extinfo;
1331 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1332 extinfo.library_namespace = ns_not_isolated;
1333
1334 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1335 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1336
1337 extinfo.library_namespace = ns_isolated;
1338
1339 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1340 ASSERT_TRUE(handle2 == nullptr);
1341 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1342
1343 // Check dlopen by absolute path
1344 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1345 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001346 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001347 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001348 " for the namespace \"private_isolated1\"", dlerror());
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001349
1350 extinfo.library_namespace = ns_isolated2;
1351
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001352 // this should work because isolation_path for private_isolated2 includes GetTestlibRoot()
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001353 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001354 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1355 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001356
1357 // Check dlopen by absolute path
1358 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08001359 ASSERT_TRUE(handle2 != nullptr) << dlerror();
1360 dlclose(handle2);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001361
1362 typedef const char* (*fn_t)();
1363 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1364 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1365
1366 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1367
1368 fn_t ns_get_private_extern_string =
1369 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1370 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1371
1372 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1373
1374 fn_t ns_get_public_extern_string =
1375 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1376 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1377
1378 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1379
1380 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1381 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1382
1383 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1384
1385 dlclose(handle1);
1386}
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001387
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001388TEST(dlext, ns_shared) {
1389 static const char* root_lib = "libnstest_root_not_isolated.so";
1390 static const char* root_lib_isolated = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001391
1392 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001393
Jiyong Park917d34a2017-08-31 14:07:13 +09001394 // create a parent namespace to use instead of the default namespace. This is
1395 // to make this test be independent from the configuration of the default
1396 // namespace.
1397 android_namespace_t* ns_parent =
1398 android_create_namespace("parent",
1399 nullptr,
1400 nullptr,
1401 ANDROID_NAMESPACE_TYPE_REGULAR,
1402 nullptr,
1403 nullptr);
1404 ASSERT_TRUE(ns_parent != nullptr) << dlerror();
1405 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
1406
1407 android_dlextinfo extinfo;
1408 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1409 extinfo.library_namespace = ns_parent;
1410
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001411 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Jiyong Park917d34a2017-08-31 14:07:13 +09001412 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001413 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1414
1415 android_set_application_target_sdk_version(42U); // something > 23
1416
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001417 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001418
Jiyong Park917d34a2017-08-31 14:07:13 +09001419 // preload this library to the parent namespace to check if it
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001420 // is shared later on.
1421 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001422 android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001423 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1424
Jiyong Park917d34a2017-08-31 14:07:13 +09001425 // create two child namespaces of 'ns_parent'. One with regular, the other
1426 // with isolated & shared.
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001427 android_namespace_t* ns_not_isolated =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001428 android_create_namespace("private",
1429 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001430 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001431 ANDROID_NAMESPACE_TYPE_REGULAR,
1432 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001433 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001434 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001435 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
1436 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001437
1438 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001439 android_create_namespace("private_isolated_shared",
1440 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001441 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001442 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001443 nullptr,
Jiyong Park917d34a2017-08-31 14:07:13 +09001444 ns_parent);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001445 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Jiyong Park917d34a2017-08-31 14:07:13 +09001446 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
1447 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001448
Jiyong Park917d34a2017-08-31 14:07:13 +09001449 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001450 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
1451
1452 std::string lib_private_external_path =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001453 GetTestlibRoot() + "/private_namespace_libs_external/libnstest_private_external.so";
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001454
Jiyong Park917d34a2017-08-31 14:07:13 +09001455 // Load lib_private_external_path to the parent namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001456 // (it should remain invisible for the isolated namespaces after this)
Jiyong Park917d34a2017-08-31 14:07:13 +09001457 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001458 ASSERT_TRUE(handle != nullptr) << dlerror();
1459
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001460 extinfo.library_namespace = ns_not_isolated;
1461
1462 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1463 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1464
1465 extinfo.library_namespace = ns_isolated_shared;
1466
1467 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1468 ASSERT_TRUE(handle2 == nullptr);
1469 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
1470
1471 // Check dlopen by absolute path
1472 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
1473 ASSERT_TRUE(handle2 == nullptr);
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001474 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001475 " or dlopened by \"" + android::base::GetExecutablePath() + "\" is not accessible"
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001476 " for the namespace \"private_isolated_shared\"", dlerror());
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08001477
1478 // load libnstest_root.so to shared namespace in order to check that everything is different
1479 // except shared libnstest_dlopened.so
1480
1481 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
1482
1483 typedef const char* (*fn_t)();
1484 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
1485 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
1486 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
1487 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
1488
1489 ASSERT_STREQ("This string is local to root library", ns_get_local_string());
1490 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
1491 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
1492
1493 fn_t ns_get_private_extern_string =
1494 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
1495 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
1496 fn_t ns_get_private_extern_string_shared =
1497 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
1498 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
1499
1500 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
1501 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
1502 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
1503
1504 fn_t ns_get_public_extern_string =
1505 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
1506 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
1507 fn_t ns_get_public_extern_string_shared =
1508 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
1509 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
1510
1511 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
1512 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
1513 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
1514
1515 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
1516 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
1517 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
1518 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
1519 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
1520 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
1521
1522 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
1523 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
1524 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
1525 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
1526 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
1527
1528 dlclose(handle1);
1529 dlclose(handle2);
1530}
1531
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001532TEST(dlext, ns_shared_links_and_paths) {
1533 // Create parent namespace (isolated, not shared)
1534 android_namespace_t* ns_isolated =
1535 android_create_namespace("private_isolated",
1536 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001537 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001538 ANDROID_NAMESPACE_TYPE_ISOLATED,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001539 (GetTestlibRoot() + "/public_namespace_libs").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001540 nullptr);
1541 ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
1542 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
1543
1544 // Create shared namespace with ns_isolated parent
1545 android_namespace_t* ns_shared =
1546 android_create_namespace("private_shared",
1547 nullptr,
1548 nullptr,
1549 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
1550 nullptr,
1551 ns_isolated);
1552 ASSERT_TRUE(ns_shared != nullptr) << dlerror();
1553
1554 // 1. Load a library in ns_shared to check that it has inherited
1555 // search path and the link to the default namespace.
1556 android_dlextinfo extinfo;
1557 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1558 extinfo.library_namespace = ns_shared;
1559
1560 {
1561 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
1562 ASSERT_TRUE(handle != nullptr) << dlerror();
1563 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
1564 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
1565 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
1566
1567 dlclose(handle);
1568 }
1569 // 2. Load another test library by absolute path to check that
1570 // it has inherited permitted_when_isolated_path
1571 {
1572 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001573 (GetTestlibRoot() + "/public_namespace_libs/libnstest_public.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001574 RTLD_NOW,
1575 &extinfo);
1576
1577 ASSERT_TRUE(handle != nullptr) << dlerror();
1578 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
1579 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
1580 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
1581
1582 dlclose(handle);
1583 }
1584
1585 // 3. Check that it is still isolated.
1586 {
1587 void* handle = android_dlopen_ext(
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001588 (GetTestlibRoot() + "/libtest_empty.so").c_str(),
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07001589 RTLD_NOW,
1590 &extinfo);
1591
1592 ASSERT_TRUE(handle == nullptr);
1593 }
1594}
1595
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001596TEST(dlext, ns_shared_dlclose) {
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001597 android_set_application_target_sdk_version(42U); // something > 23
1598
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001599 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001600
1601 // preload this library to the default namespace to check if it
1602 // is shared later on.
1603 void* handle_dlopened =
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001604 dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001605 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
1606
1607 android_namespace_t* ns_isolated_shared =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001608 android_create_namespace("private_isolated_shared",
1609 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001610 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001611 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001612 nullptr,
1613 nullptr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001614 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001615 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001616
1617 // Check if "libnstest_dlopened.so" is loaded (and the same)
1618 android_dlextinfo extinfo;
1619 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1620 extinfo.library_namespace = ns_isolated_shared;
1621
1622 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1623 ASSERT_TRUE(handle != nullptr) << dlerror();
1624 ASSERT_TRUE(handle == handle_dlopened);
1625 dlclose(handle);
1626 dlclose(handle_dlopened);
1627
1628 // And now check that the library cannot be found by soname (and is no longer loaded)
1629 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
1630 ASSERT_TRUE(handle == nullptr)
1631 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1632
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001633 handle = android_dlopen_ext((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001634 RTLD_NOW | RTLD_NOLOAD, &extinfo);
1635 ASSERT_TRUE(handle == nullptr)
1636 << "Error: libnstest_dlopened.so is still accessible in shared namespace";
1637
1638 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
1639 ASSERT_TRUE(handle == nullptr)
1640 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1641
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001642 handle = dlopen((GetTestlibRoot() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001643 RTLD_NOW | RTLD_NOLOAD);
1644 ASSERT_TRUE(handle == nullptr)
1645 << "Error: libnstest_dlopened.so is still accessible in default namespace";
1646
1647 // Now lets see if the soinfo area gets reused in the wrong way:
1648 // load a library to default namespace.
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001649 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07001650 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1651 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1652
1653 // try to find it in shared namespace
1654 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
1655 ASSERT_TRUE(handle == nullptr)
1656 << "Error: " << g_public_lib << " is accessible in shared namespace";
1657}
1658
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001659TEST(dlext, ns_isolated_rtld_global) {
1660 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001661 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001662
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001663 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs";
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001664
1665 android_namespace_t* ns1 =
1666 android_create_namespace("isolated1",
1667 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001668 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001669 ANDROID_NAMESPACE_TYPE_ISOLATED,
1670 lib_public_path.c_str(),
1671 nullptr);
1672 ASSERT_TRUE(ns1 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001673 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001674
1675 android_namespace_t* ns2 =
1676 android_create_namespace("isolated2",
1677 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001678 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001679 ANDROID_NAMESPACE_TYPE_ISOLATED,
1680 lib_public_path.c_str(),
1681 nullptr);
1682 ASSERT_TRUE(ns2 != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001683 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001684
1685 android_dlextinfo extinfo;
1686 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1687 extinfo.library_namespace = ns1;
1688
1689 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
1690 RTLD_GLOBAL,
1691 &extinfo);
1692
1693 ASSERT_TRUE(handle_global != nullptr) << dlerror();
1694
1695 android_namespace_t* ns1_child =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001696 android_create_namespace("isolated1_child",
1697 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001698 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001699 ANDROID_NAMESPACE_TYPE_ISOLATED,
1700 nullptr,
1701 ns1);
1702
1703 ASSERT_TRUE(ns1_child != nullptr) << dlerror();
1704 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07001705
1706 // Now - only ns1 and ns1 child should be able to dlopen root_lib
1707 // attempt to use ns2 should result in dlerror()
1708
1709 // Check ns1_child first.
1710 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1711 extinfo.library_namespace = ns1_child;
1712
1713 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1714 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1715
1716 // now ns1
1717 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1718 extinfo.library_namespace = ns1;
1719
1720 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1721 ASSERT_TRUE(handle1 != nullptr) << dlerror();
1722
1723 // and ns2 should fail
1724 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1725 extinfo.library_namespace = ns2;
1726
1727 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
1728 ASSERT_TRUE(handle1 == nullptr);
1729 ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
1730}
1731
dimitry8db36a52017-10-23 15:10:10 +02001732TEST(dlext, ns_inaccessible_error_message) {
1733 // We set up 2 namespaces (a and b) and link a->b with a shared library
1734 // libtestshared.so. Then try to dlopen different library with the same
1735 // name from in namespace a. Note that library should not be accessible
1736 // in either namespace but since it's soname is in the list of shared libs
1737 // the linker will attempt to find it in linked namespace.
1738 //
1739 // Check the error message and make sure it mentions correct namespace name.
1740 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1741
1742 android_namespace_t* ns_a =
1743 android_create_namespace("ns_a",
1744 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001745 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001746 ANDROID_NAMESPACE_TYPE_ISOLATED,
1747 nullptr,
1748 nullptr);
1749 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1750 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1751
1752 android_namespace_t* ns_b =
1753 android_create_namespace("ns_b",
1754 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001755 GetTestlibRoot().c_str(),
dimitry8db36a52017-10-23 15:10:10 +02001756 ANDROID_NAMESPACE_TYPE_ISOLATED,
1757 nullptr,
1758 nullptr);
1759 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1760 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1761
1762 ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
1763
1764 android_dlextinfo extinfo;
1765 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1766 extinfo.library_namespace = ns_a;
1767
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001768 std::string library_path = GetTestlibRoot() + "/inaccessible_libs/libtestshared.so";
dimitry8db36a52017-10-23 15:10:10 +02001769
1770 void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
1771 ASSERT_TRUE(handle == nullptr);
1772 std::string expected_dlerror =
1773 android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
1774 " is not accessible for the namespace \"ns_a\"",
1775 library_path.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001776 android::base::GetExecutablePath().c_str());
dimitry8db36a52017-10-23 15:10:10 +02001777 ASSERT_EQ(expected_dlerror, dlerror());
1778}
1779
dimitry321476a2018-01-29 15:32:37 +01001780extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
1781 android_namespace_t* namespace_to);
1782
Logan Chien9ee45912018-01-18 12:05:09 +08001783TEST(dlext, ns_link_namespaces_invalid_arguments) {
1784 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1785
1786 android_namespace_t* ns =
1787 android_create_namespace("private",
1788 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001789 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001790 ANDROID_NAMESPACE_TYPE_REGULAR,
1791 nullptr,
1792 nullptr);
1793 ASSERT_TRUE(ns != nullptr) << dlerror();
1794
1795 // Test android_link_namespaces()
1796 ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
1797 ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
1798 dlerror());
1799
1800 ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
1801 ASSERT_STREQ("android_link_namespaces failed: "
1802 "error linking namespaces \"private\"->\"(default)\": "
1803 "the list of shared libraries is empty.", dlerror());
1804
1805 ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
1806 ASSERT_STREQ("android_link_namespaces failed: "
1807 "error linking namespaces \"private\"->\"(default)\": "
1808 "the list of shared libraries is empty.", dlerror());
1809
dimitry321476a2018-01-29 15:32:37 +01001810 // Test __loader_android_link_namespaces_all_libs()
1811 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001812 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1813 "error linking namespaces: namespace_from is null.", dlerror());
1814
dimitry321476a2018-01-29 15:32:37 +01001815 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
Logan Chien9ee45912018-01-18 12:05:09 +08001816 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1817 "error linking namespaces: namespace_from is null.", dlerror());
1818
dimitry321476a2018-01-29 15:32:37 +01001819 ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
Logan Chien9ee45912018-01-18 12:05:09 +08001820 ASSERT_STREQ("android_link_namespaces_all_libs failed: "
1821 "error linking namespaces: namespace_to is null.", dlerror());
1822}
1823
1824TEST(dlext, ns_allow_all_shared_libs) {
1825 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
1826
1827 android_namespace_t* ns_a =
1828 android_create_namespace("ns_a",
1829 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001830 (GetTestlibRoot() + "/ns_a").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001831 ANDROID_NAMESPACE_TYPE_ISOLATED,
1832 nullptr,
1833 nullptr);
1834 ASSERT_TRUE(ns_a != nullptr) << dlerror();
1835 ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
1836
1837 android_namespace_t* ns_b =
1838 android_create_namespace("ns_b",
1839 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001840 (GetTestlibRoot() + "/ns_b").c_str(),
Logan Chien9ee45912018-01-18 12:05:09 +08001841 ANDROID_NAMESPACE_TYPE_ISOLATED,
1842 nullptr,
1843 nullptr);
1844 ASSERT_TRUE(ns_b != nullptr) << dlerror();
1845 ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
1846
1847 ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
dimitry321476a2018-01-29 15:32:37 +01001848 ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
Logan Chien9ee45912018-01-18 12:05:09 +08001849
1850 // Load libs with android_dlopen_ext() from namespace b
1851 android_dlextinfo extinfo;
1852 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1853 extinfo.library_namespace = ns_b;
1854
1855 void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1856 ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
1857
1858 void* ns_b_handle1_internal =
1859 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1860 ASSERT_TRUE(ns_b_handle1_internal == nullptr);
1861
1862 void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1863 ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
1864
1865 void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1866 ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
1867
1868 // Load libs with android_dlopen_ext() from namespace a
1869 extinfo.library_namespace = ns_a;
1870
1871 void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
1872 ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
1873
1874 void* ns_a_handle1_internal =
1875 android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
1876 ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
1877
1878 void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
1879 ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
1880
1881 void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
1882 ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
1883
1884 // Compare the dlopen handle
1885 ASSERT_EQ(ns_b_handle1, ns_a_handle1);
1886 ASSERT_EQ(ns_b_handle2, ns_a_handle2);
1887 ASSERT_EQ(ns_b_handle3, ns_a_handle3);
1888
1889 // Close libs
1890 dlclose(ns_b_handle1);
1891 dlclose(ns_b_handle2);
1892 dlclose(ns_b_handle3);
1893
1894 dlclose(ns_a_handle1);
1895 dlclose(ns_a_handle1_internal);
1896 dlclose(ns_a_handle2);
1897 dlclose(ns_a_handle3);
1898}
1899
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001900TEST(dlext, ns_anonymous) {
1901 static const char* root_lib = "libnstest_root.so";
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001902 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001903
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001904 const std::string lib_public_path = GetTestlibRoot() + "/public_namespace_libs/" + g_public_lib;
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001905 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
1906
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001907 ASSERT_TRUE(handle_public != nullptr) << dlerror();
1908
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001909 ASSERT_TRUE(
1910 android_init_anonymous_namespace(shared_libs.c_str(),
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001911 (GetTestlibRoot() + "/private_namespace_libs").c_str())
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001912 ) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001913
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001914 android_namespace_t* ns =
1915 android_create_namespace("private",
1916 nullptr,
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001917 (GetTestlibRoot() + "/private_namespace_libs").c_str(),
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001918 ANDROID_NAMESPACE_TYPE_REGULAR,
1919 nullptr,
1920 nullptr);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001921
1922 ASSERT_TRUE(ns != nullptr) << dlerror();
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08001923 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001924
Christopher Ferris6d2c0bd2018-08-21 18:13:10 -07001925 std::string private_library_absolute_path = GetTestlibRoot() + "/private_namespace_libs/" + root_lib;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001926
1927 android_dlextinfo extinfo;
1928 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
1929 extinfo.library_namespace = ns;
1930
1931 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
1932 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
1933 ASSERT_TRUE(handle != nullptr) << dlerror();
1934
1935 uintptr_t ns_get_dlopened_string_addr =
1936 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
1937 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
1938 typedef const char* (*fn_t)();
1939 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
1940
1941 std::vector<map_record> maps;
1942 Maps::parse_maps(&maps);
1943
1944 uintptr_t addr_start = 0;
1945 uintptr_t addr_end = 0;
dimitry8eaf28d2017-10-11 10:04:14 +02001946 bool has_executable_segment = false;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001947 std::vector<map_record> maps_to_copy;
1948
1949 for (const auto& rec : maps) {
1950 if (rec.pathname == private_library_absolute_path) {
1951 if (addr_start == 0) {
1952 addr_start = rec.addr_start;
1953 }
1954 addr_end = rec.addr_end;
dimitry8eaf28d2017-10-11 10:04:14 +02001955 has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001956
1957 maps_to_copy.push_back(rec);
1958 }
1959 }
1960
1961 // some sanity checks..
1962 ASSERT_TRUE(addr_start > 0);
1963 ASSERT_TRUE(addr_end > 0);
dimitry3b0a5b72018-06-06 11:11:25 +02001964 ASSERT_TRUE(maps_to_copy.size() > 0);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001965 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
1966 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
1967
dimitry8eaf28d2017-10-11 10:04:14 +02001968 if (!has_executable_segment) {
1969 // For some natively bridged environments this code might be missing
1970 // the executable flag. This is because the guest code is not supposed
1971 // to be executed directly and making it non-executable is more secure.
1972 // If this is the case we assume that the first segment is the one that
1973 // has this flag.
1974 ASSERT_TRUE((maps_to_copy[0].perms & PROT_WRITE) == 0);
1975 maps_to_copy[0].perms |= PROT_EXEC;
1976 }
1977
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08001978 // copy
1979 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
1980 PROT_NONE, MAP_ANON | MAP_PRIVATE,
1981 -1, 0));
1982 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
1983
1984 for (const auto& rec : maps_to_copy) {
1985 uintptr_t offset = rec.addr_start - addr_start;
1986 size_t size = rec.addr_end - rec.addr_start;
1987 void* addr = reinterpret_cast<void*>(reserved_addr + offset);
1988 void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
1989 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
1990 ASSERT_TRUE(map != MAP_FAILED);
1991 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
1992 mprotect(map, size, rec.perms);
1993 }
1994
1995 // call the function copy
1996 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
1997 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
1998 ASSERT_STREQ("This string is from private namespace (dlopened library)",
1999 ns_get_dlopened_string_anon());
2000
2001 // They should belong to different namespaces (private and anonymous)
2002 ASSERT_STREQ("This string is from private namespace (dlopened library)",
2003 ns_get_dlopened_string_private());
2004
2005 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
2006}
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002007
2008TEST(dlext, dlopen_handle_value_platform) {
2009 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2010 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
2011 << "dlopen should return odd value for the handle";
2012 dlclose(handle);
2013}
2014
2015TEST(dlext, dlopen_handle_value_app_compat) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08002016 android_set_application_target_sdk_version(__ANDROID_API_M__);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002017 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
2018 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
2019 << "dlopen should return valid pointer";
2020 dlclose(handle);
2021}