blob: 878b9f8f1f2c80cc0d4cf7f91f33f63b2ecacc03 [file] [log] [blame]
Orion Hodson9b16e342019-10-09 13:29:16 +01001/*
2 * Copyright (C) 2019 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
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +010017#if defined(ART_TARGET_ANDROID)
18
Martin Stjernholm19d1feb2021-03-30 22:35:24 +010019#include "native_loader_test.h"
20
Orion Hodson9b16e342019-10-09 13:29:16 +010021#include <dlfcn.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010022
23#include <android-base/strings.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010024#include <gtest/gtest.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010025
Martin Stjernholm94fd9ea2019-10-24 16:57:34 +010026#include "nativehelper/scoped_utf_chars.h"
Orion Hodson9b16e342019-10-09 13:29:16 +010027#include "nativeloader/native_loader.h"
28#include "public_libraries.h"
29
Orion Hodson9b16e342019-10-09 13:29:16 +010030namespace android {
31namespace nativeloader {
32
Martin Stjernholm48297332019-11-12 21:21:32 +000033using ::testing::Eq;
Martin Stjernholm26659432021-04-16 19:55:03 +010034using ::testing::NotNull;
Martin Stjernholm48297332019-11-12 21:21:32 +000035using ::testing::StrEq;
Martin Stjernholm48297332019-11-12 21:21:32 +000036using internal::ConfigEntry;
Calin Juravle91d2c5c2021-05-07 22:44:29 +000037using internal::ParseApexLibrariesConfig;
Martin Stjernholm26659432021-04-16 19:55:03 +010038using internal::ParseConfig;
Martin Stjernholm48297332019-11-12 21:21:32 +000039
Martin Stjernholmbe08b202019-11-12 20:11:00 +000040#if defined(__LP64__)
41#define LIB_DIR "lib64"
42#else
43#define LIB_DIR "lib"
44#endif
45
Orion Hodson9b16e342019-10-09 13:29:16 +010046static void* const any_nonnull = reinterpret_cast<void*>(0x12345678);
47
48// Custom matcher for comparing namespace handles
49MATCHER_P(NsEq, other, "") {
50 *result_listener << "comparing " << reinterpret_cast<const char*>(arg) << " and " << other;
51 return strcmp(reinterpret_cast<const char*>(arg), reinterpret_cast<const char*>(other)) == 0;
52}
53
54/////////////////////////////////////////////////////////////////
55
56// Test fixture
57class NativeLoaderTest : public ::testing::TestWithParam<bool> {
58 protected:
59 bool IsBridged() { return GetParam(); }
60
61 void SetUp() override {
Martin Stjernholm48297332019-11-12 21:21:32 +000062 mock = std::make_unique<testing::NiceMock<MockPlatform>>(IsBridged());
Orion Hodson9b16e342019-10-09 13:29:16 +010063
64 env = std::make_unique<JNIEnv>();
65 env->functions = CreateJNINativeInterface();
66 }
67
68 void SetExpectations() {
69 std::vector<std::string> default_public_libs =
70 android::base::Split(preloadable_public_libraries(), ":");
71 for (auto l : default_public_libs) {
Martin Stjernholm26659432021-04-16 19:55:03 +010072 EXPECT_CALL(*mock,
73 mock_dlopen_ext(false, StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE, NotNull()))
Orion Hodson9b16e342019-10-09 13:29:16 +010074 .WillOnce(Return(any_nonnull));
75 }
76 }
77
78 void RunTest() { InitializeNativeLoader(); }
79
80 void TearDown() override {
81 ResetNativeLoader();
82 delete env->functions;
83 mock.reset();
84 }
85
86 std::unique_ptr<JNIEnv> env;
87};
88
89/////////////////////////////////////////////////////////////////
90
91TEST_P(NativeLoaderTest, InitializeLoadsDefaultPublicLibraries) {
92 SetExpectations();
93 RunTest();
94}
95
Martin Stjernholm26659432021-04-16 19:55:03 +010096TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderInApex) {
97 const char* test_lib_path = "libfoo.so";
98 void* fake_handle = &fake_handle; // Arbitrary non-null value
99 EXPECT_CALL(*mock,
100 mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("com_android_art")))
101 .WillOnce(Return(fake_handle));
102
103 bool needs_native_bridge = false;
104 char* errmsg = nullptr;
105 EXPECT_EQ(fake_handle,
106 OpenNativeLibrary(env.get(),
107 /*target_sdk_version=*/17,
108 test_lib_path,
109 /*class_loader=*/nullptr,
110 /*caller_location=*/"/apex/com.android.art/javalib/myloadinglib.jar",
111 /*library_path=*/nullptr,
112 &needs_native_bridge,
113 &errmsg));
114 // OpenNativeLibrary never uses nativebridge when there's no classloader. That
115 // should maybe change.
116 EXPECT_EQ(needs_native_bridge, false);
117 EXPECT_EQ(errmsg, nullptr);
118}
119
120TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderInFramework) {
121 const char* test_lib_path = "libfoo.so";
122 void* fake_handle = &fake_handle; // Arbitrary non-null value
123 EXPECT_CALL(*mock, mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("system")))
124 .WillOnce(Return(fake_handle));
125
126 bool needs_native_bridge = false;
127 char* errmsg = nullptr;
128 EXPECT_EQ(fake_handle,
129 OpenNativeLibrary(env.get(),
130 /*target_sdk_version=*/17,
131 test_lib_path,
132 /*class_loader=*/nullptr,
133 /*caller_location=*/"/system/framework/framework.jar!classes1.dex",
134 /*library_path=*/nullptr,
135 &needs_native_bridge,
136 &errmsg));
137 // OpenNativeLibrary never uses nativebridge when there's no classloader. That
138 // should maybe change.
139 EXPECT_EQ(needs_native_bridge, false);
140 EXPECT_EQ(errmsg, nullptr);
141}
142
143TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderAndCallerLocation) {
144 const char* test_lib_path = "libfoo.so";
145 void* fake_handle = &fake_handle; // Arbitrary non-null value
146 EXPECT_CALL(*mock, mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("system")))
147 .WillOnce(Return(fake_handle));
148
149 bool needs_native_bridge = false;
150 char* errmsg = nullptr;
151 EXPECT_EQ(fake_handle,
152 OpenNativeLibrary(env.get(),
153 /*target_sdk_version=*/17,
154 test_lib_path,
155 /*class_loader=*/nullptr,
156 /*caller_location=*/nullptr,
157 /*library_path=*/nullptr,
158 &needs_native_bridge,
159 &errmsg));
160 // OpenNativeLibrary never uses nativebridge when there's no classloader. That
161 // should maybe change.
162 EXPECT_EQ(needs_native_bridge, false);
163 EXPECT_EQ(errmsg, nullptr);
164}
165
Orion Hodson9b16e342019-10-09 13:29:16 +0100166INSTANTIATE_TEST_SUITE_P(NativeLoaderTests, NativeLoaderTest, testing::Bool());
167
168/////////////////////////////////////////////////////////////////
169
170class NativeLoaderTest_Create : public NativeLoaderTest {
171 protected:
172 // Test inputs (initialized to the default values). Overriding these
173 // must be done before calling SetExpectations() and RunTest().
174 uint32_t target_sdk_version = 29;
175 std::string class_loader = "my_classloader";
176 bool is_shared = false;
177 std::string dex_path = "/data/app/foo/classes.dex";
Martin Stjernholmbe08b202019-11-12 20:11:00 +0000178 std::string library_path = "/data/app/foo/" LIB_DIR "/arm";
179 std::string permitted_path = "/data/app/foo/" LIB_DIR;
Orion Hodson9b16e342019-10-09 13:29:16 +0100180
181 // expected output (.. for the default test inputs)
182 std::string expected_namespace_name = "classloader-namespace";
183 uint64_t expected_namespace_flags =
184 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
185 std::string expected_library_path = library_path;
186 std::string expected_permitted_path = std::string("/data:/mnt/expand:") + permitted_path;
Kiyoung Kim99c19ca2020-01-29 16:09:38 +0900187 std::string expected_parent_namespace = "system";
Orion Hodson9b16e342019-10-09 13:29:16 +0100188 bool expected_link_with_platform_ns = true;
189 bool expected_link_with_art_ns = true;
Victor Changd20e51d2020-05-05 16:01:19 +0100190 bool expected_link_with_i18n_ns = true;
Jooyung Han180e1e72021-06-20 17:54:38 +0900191 bool expected_link_with_conscrypt_ns = false;
Orion Hodson9b16e342019-10-09 13:29:16 +0100192 bool expected_link_with_sphal_ns = !vendor_public_libraries().empty();
Justin Yuna21b5842021-08-10 14:05:49 +0900193 bool expected_link_with_product_ns = !product_public_libraries().empty();
Orion Hodson9b16e342019-10-09 13:29:16 +0100194 bool expected_link_with_vndk_ns = false;
Justin Yuneb4f08c2020-02-18 11:29:07 +0900195 bool expected_link_with_vndk_product_ns = false;
Orion Hodson9b16e342019-10-09 13:29:16 +0100196 bool expected_link_with_default_ns = false;
197 bool expected_link_with_neuralnetworks_ns = true;
198 std::string expected_shared_libs_to_platform_ns = default_public_libraries();
Jooyung Hancd616d02020-09-01 14:53:23 +0900199 std::string expected_shared_libs_to_art_ns = apex_public_libraries().at("com_android_art");
200 std::string expected_shared_libs_to_i18n_ns = apex_public_libraries().at("com_android_i18n");
Jooyung Han180e1e72021-06-20 17:54:38 +0900201 std::string expected_shared_libs_to_conscrypt_ns = apex_jni_libraries("com_android_conscrypt");
Orion Hodson9b16e342019-10-09 13:29:16 +0100202 std::string expected_shared_libs_to_sphal_ns = vendor_public_libraries();
Justin Yuna21b5842021-08-10 14:05:49 +0900203 std::string expected_shared_libs_to_product_ns = product_public_libraries();
Justin Yuneb4f08c2020-02-18 11:29:07 +0900204 std::string expected_shared_libs_to_vndk_ns = vndksp_libraries_vendor();
205 std::string expected_shared_libs_to_vndk_product_ns = vndksp_libraries_product();
Orion Hodson9b16e342019-10-09 13:29:16 +0100206 std::string expected_shared_libs_to_default_ns = default_public_libraries();
Jooyung Hancd616d02020-09-01 14:53:23 +0900207 std::string expected_shared_libs_to_neuralnetworks_ns = apex_public_libraries().at("com_android_neuralnetworks");
Orion Hodson9b16e342019-10-09 13:29:16 +0100208
209 void SetExpectations() {
210 NativeLoaderTest::SetExpectations();
211
212 ON_CALL(*mock, JniObject_getParent(StrEq(class_loader))).WillByDefault(Return(nullptr));
213
Martin Stjernholm48297332019-11-12 21:21:32 +0000214 EXPECT_CALL(*mock, NativeBridgeIsPathSupported(_)).Times(testing::AnyNumber());
215 EXPECT_CALL(*mock, NativeBridgeInitialized()).Times(testing::AnyNumber());
Orion Hodson9b16e342019-10-09 13:29:16 +0100216
217 EXPECT_CALL(*mock, mock_create_namespace(
218 Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
219 StrEq(expected_library_path), expected_namespace_flags,
220 StrEq(expected_permitted_path), NsEq(expected_parent_namespace.c_str())))
221 .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(dex_path.c_str()))));
222 if (expected_link_with_platform_ns) {
Kiyoung Kim99c19ca2020-01-29 16:09:38 +0900223 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("system"),
Orion Hodson9b16e342019-10-09 13:29:16 +0100224 StrEq(expected_shared_libs_to_platform_ns)))
225 .WillOnce(Return(true));
226 }
227 if (expected_link_with_art_ns) {
Kiyoung Kim272b36d2020-02-19 16:08:47 +0900228 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_art"),
Orion Hodson9b16e342019-10-09 13:29:16 +0100229 StrEq(expected_shared_libs_to_art_ns)))
230 .WillOnce(Return(true));
231 }
Victor Changd20e51d2020-05-05 16:01:19 +0100232 if (expected_link_with_i18n_ns) {
233 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_i18n"),
234 StrEq(expected_shared_libs_to_i18n_ns)))
235 .WillOnce(Return(true));
236 }
Orion Hodson9b16e342019-10-09 13:29:16 +0100237 if (expected_link_with_sphal_ns) {
238 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("sphal"),
239 StrEq(expected_shared_libs_to_sphal_ns)))
240 .WillOnce(Return(true));
241 }
Justin Yuna21b5842021-08-10 14:05:49 +0900242 if (expected_link_with_product_ns) {
243 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("product"),
244 StrEq(expected_shared_libs_to_product_ns)))
245 .WillOnce(Return(true));
246 }
Orion Hodson9b16e342019-10-09 13:29:16 +0100247 if (expected_link_with_vndk_ns) {
248 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("vndk"),
249 StrEq(expected_shared_libs_to_vndk_ns)))
250 .WillOnce(Return(true));
251 }
Justin Yuneb4f08c2020-02-18 11:29:07 +0900252 if (expected_link_with_vndk_product_ns) {
253 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("vndk_product"),
254 StrEq(expected_shared_libs_to_vndk_product_ns)))
255 .WillOnce(Return(true));
256 }
Orion Hodson9b16e342019-10-09 13:29:16 +0100257 if (expected_link_with_default_ns) {
258 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("default"),
259 StrEq(expected_shared_libs_to_default_ns)))
260 .WillOnce(Return(true));
261 }
262 if (expected_link_with_neuralnetworks_ns) {
Kiyoung Kim272b36d2020-02-19 16:08:47 +0900263 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_neuralnetworks"),
Orion Hodson9b16e342019-10-09 13:29:16 +0100264 StrEq(expected_shared_libs_to_neuralnetworks_ns)))
265 .WillOnce(Return(true));
266 }
Jooyung Han180e1e72021-06-20 17:54:38 +0900267 if (expected_link_with_conscrypt_ns) {
268 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_conscrypt"),
269 StrEq(expected_shared_libs_to_conscrypt_ns)))
270 .WillOnce(Return(true));
271 }
Orion Hodson9b16e342019-10-09 13:29:16 +0100272 }
273
274 void RunTest() {
275 NativeLoaderTest::RunTest();
276
277 jstring err = CreateClassLoaderNamespace(
278 env(), target_sdk_version, env()->NewStringUTF(class_loader.c_str()), is_shared,
279 env()->NewStringUTF(dex_path.c_str()), env()->NewStringUTF(library_path.c_str()),
Martin Stjernholmb3092402020-09-04 00:49:44 +0100280 env()->NewStringUTF(permitted_path.c_str()), /*uses_library_list=*/ nullptr);
Orion Hodson9b16e342019-10-09 13:29:16 +0100281
282 // no error
Martin Stjernholm94fd9ea2019-10-24 16:57:34 +0100283 EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env(), err).c_str());
Orion Hodson9b16e342019-10-09 13:29:16 +0100284
285 if (!IsBridged()) {
286 struct android_namespace_t* ns =
287 FindNamespaceByClassLoader(env(), env()->NewStringUTF(class_loader.c_str()));
288
289 // The created namespace is for this apk
290 EXPECT_EQ(dex_path.c_str(), reinterpret_cast<const char*>(ns));
291 } else {
292 struct NativeLoaderNamespace* ns =
293 FindNativeLoaderNamespaceByClassLoader(env(), env()->NewStringUTF(class_loader.c_str()));
294
295 // The created namespace is for the this apk
296 EXPECT_STREQ(dex_path.c_str(),
297 reinterpret_cast<const char*>(ns->ToRawNativeBridgeNamespace()));
298 }
299 }
300
301 JNIEnv* env() { return NativeLoaderTest::env.get(); }
302};
303
304TEST_P(NativeLoaderTest_Create, DownloadedApp) {
305 SetExpectations();
306 RunTest();
307}
308
309TEST_P(NativeLoaderTest_Create, BundledSystemApp) {
310 dex_path = "/system/app/foo/foo.apk";
311 is_shared = true;
312
Martin Stjernholm94fd9ea2019-10-24 16:57:34 +0100313 expected_namespace_name = "classloader-namespace-shared";
Orion Hodson9b16e342019-10-09 13:29:16 +0100314 expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
315 SetExpectations();
316 RunTest();
317}
318
319TEST_P(NativeLoaderTest_Create, BundledVendorApp) {
320 dex_path = "/vendor/app/foo/foo.apk";
321 is_shared = true;
322
Martin Stjernholm94fd9ea2019-10-24 16:57:34 +0100323 expected_namespace_name = "classloader-namespace-shared";
Orion Hodson9b16e342019-10-09 13:29:16 +0100324 expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
325 SetExpectations();
326 RunTest();
327}
328
329TEST_P(NativeLoaderTest_Create, UnbundledVendorApp) {
330 dex_path = "/vendor/app/foo/foo.apk";
331 is_shared = false;
332
333 expected_namespace_name = "vendor-classloader-namespace";
Martin Stjernholmbe08b202019-11-12 20:11:00 +0000334 expected_library_path = expected_library_path + ":/vendor/" LIB_DIR;
335 expected_permitted_path = expected_permitted_path + ":/vendor/" LIB_DIR;
Orion Hodson9b16e342019-10-09 13:29:16 +0100336 expected_shared_libs_to_platform_ns =
Justin Yun089c1352020-02-06 16:53:08 +0900337 expected_shared_libs_to_platform_ns + ":" + llndk_libraries_vendor();
Orion Hodson9b16e342019-10-09 13:29:16 +0100338 expected_link_with_vndk_ns = true;
339 SetExpectations();
340 RunTest();
341}
342
Justin Yun3db26d52019-12-16 14:09:39 +0900343TEST_P(NativeLoaderTest_Create, BundledProductApp) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100344 dex_path = "/product/app/foo/foo.apk";
345 is_shared = true;
346
Martin Stjernholm94fd9ea2019-10-24 16:57:34 +0100347 expected_namespace_name = "classloader-namespace-shared";
Orion Hodson9b16e342019-10-09 13:29:16 +0100348 expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
349 SetExpectations();
350 RunTest();
351}
352
Jooyung Han180e1e72021-06-20 17:54:38 +0900353TEST_P(NativeLoaderTest_Create, SystemServerWithApexJars) {
354 dex_path = "/system/framework/services.jar:/apex/com.android.conscrypt/javalib/service-foo.jar";
355 is_shared = true;
356
357 expected_namespace_name = "classloader-namespace-shared";
358 expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
359 expected_link_with_conscrypt_ns = true;
360 SetExpectations();
361 RunTest();
362}
363
Justin Yun3db26d52019-12-16 14:09:39 +0900364TEST_P(NativeLoaderTest_Create, UnbundledProductApp) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100365 dex_path = "/product/app/foo/foo.apk";
366 is_shared = false;
Orion Hodson9b16e342019-10-09 13:29:16 +0100367
Justin Yun3db26d52019-12-16 14:09:39 +0900368 if (is_product_vndk_version_defined()) {
369 expected_namespace_name = "vendor-classloader-namespace";
370 expected_library_path = expected_library_path + ":/product/" LIB_DIR ":/system/product/" LIB_DIR;
371 expected_permitted_path =
372 expected_permitted_path + ":/product/" LIB_DIR ":/system/product/" LIB_DIR;
373 expected_shared_libs_to_platform_ns =
Justin Yun089c1352020-02-06 16:53:08 +0900374 expected_shared_libs_to_platform_ns + ":" + llndk_libraries_product();
Justin Yuneb4f08c2020-02-18 11:29:07 +0900375 expected_link_with_vndk_product_ns = true;
Justin Yun3db26d52019-12-16 14:09:39 +0900376 }
Orion Hodson9b16e342019-10-09 13:29:16 +0100377 SetExpectations();
378 RunTest();
379}
380
381TEST_P(NativeLoaderTest_Create, NamespaceForSharedLibIsNotUsedAsAnonymousNamespace) {
382 if (IsBridged()) {
383 // There is no shared lib in translated arch
384 // TODO(jiyong): revisit this
385 return;
386 }
387 // compared to apks, for java shared libs, library_path is empty; java shared
388 // libs don't have their own native libs. They use platform's.
389 library_path = "";
390 expected_library_path = library_path;
391 // no ALSO_USED_AS_ANONYMOUS
392 expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
393 SetExpectations();
394 RunTest();
395}
396
397TEST_P(NativeLoaderTest_Create, TwoApks) {
398 SetExpectations();
399 const uint32_t second_app_target_sdk_version = 29;
400 const std::string second_app_class_loader = "second_app_classloader";
401 const bool second_app_is_shared = false;
402 const std::string second_app_dex_path = "/data/app/bar/classes.dex";
Martin Stjernholmbe08b202019-11-12 20:11:00 +0000403 const std::string second_app_library_path = "/data/app/bar/" LIB_DIR "/arm";
404 const std::string second_app_permitted_path = "/data/app/bar/" LIB_DIR;
Orion Hodson9b16e342019-10-09 13:29:16 +0100405 const std::string expected_second_app_permitted_path =
406 std::string("/data:/mnt/expand:") + second_app_permitted_path;
407 const std::string expected_second_app_parent_namespace = "classloader-namespace";
408 // no ALSO_USED_AS_ANONYMOUS
409 const uint64_t expected_second_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
410
411 // The scenario is that second app is loaded by the first app.
412 // So the first app's classloader (`classloader`) is parent of the second
413 // app's classloader.
414 ON_CALL(*mock, JniObject_getParent(StrEq(second_app_class_loader)))
415 .WillByDefault(Return(class_loader.c_str()));
416
417 // namespace for the second app is created. Its parent is set to the namespace
418 // of the first app.
419 EXPECT_CALL(*mock, mock_create_namespace(
420 Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
421 StrEq(second_app_library_path), expected_second_namespace_flags,
422 StrEq(expected_second_app_permitted_path), NsEq(dex_path.c_str())))
423 .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(second_app_dex_path.c_str()))));
424 EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), NsEq(second_app_dex_path.c_str()), _, _))
425 .WillRepeatedly(Return(true));
426
427 RunTest();
428 jstring err = CreateClassLoaderNamespace(
429 env(), second_app_target_sdk_version, env()->NewStringUTF(second_app_class_loader.c_str()),
430 second_app_is_shared, env()->NewStringUTF(second_app_dex_path.c_str()),
431 env()->NewStringUTF(second_app_library_path.c_str()),
Martin Stjernholmb3092402020-09-04 00:49:44 +0100432 env()->NewStringUTF(second_app_permitted_path.c_str()), /*uses_library_list=*/ nullptr);
Orion Hodson9b16e342019-10-09 13:29:16 +0100433
434 // success
Martin Stjernholm94fd9ea2019-10-24 16:57:34 +0100435 EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env(), err).c_str());
Orion Hodson9b16e342019-10-09 13:29:16 +0100436
437 if (!IsBridged()) {
438 struct android_namespace_t* ns =
439 FindNamespaceByClassLoader(env(), env()->NewStringUTF(second_app_class_loader.c_str()));
440
441 // The created namespace is for the second apk
442 EXPECT_EQ(second_app_dex_path.c_str(), reinterpret_cast<const char*>(ns));
443 } else {
444 struct NativeLoaderNamespace* ns = FindNativeLoaderNamespaceByClassLoader(
445 env(), env()->NewStringUTF(second_app_class_loader.c_str()));
446
447 // The created namespace is for the second apk
448 EXPECT_STREQ(second_app_dex_path.c_str(),
449 reinterpret_cast<const char*>(ns->ToRawNativeBridgeNamespace()));
450 }
451}
452
453INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool());
454
455const std::function<Result<bool>(const struct ConfigEntry&)> always_true =
456 [](const struct ConfigEntry&) -> Result<bool> { return true; };
457
458TEST(NativeLoaderConfigParser, NamesAndComments) {
459 const char file_content[] = R"(
460######
461
462libA.so
463#libB.so
464
465
466 libC.so
467libD.so
468 #### libE.so
469)";
470 const std::vector<std::string> expected_result = {"libA.so", "libC.so", "libD.so"};
471 Result<std::vector<std::string>> result = ParseConfig(file_content, always_true);
Bernie Innocentiac5ae3c2020-02-12 10:43:42 +0900472 ASSERT_RESULT_OK(result);
Orion Hodson9b16e342019-10-09 13:29:16 +0100473 ASSERT_EQ(expected_result, *result);
474}
475
476TEST(NativeLoaderConfigParser, WithBitness) {
477 const char file_content[] = R"(
478libA.so 32
479libB.so 64
480libC.so
481)";
482#if defined(__LP64__)
483 const std::vector<std::string> expected_result = {"libB.so", "libC.so"};
484#else
485 const std::vector<std::string> expected_result = {"libA.so", "libC.so"};
486#endif
487 Result<std::vector<std::string>> result = ParseConfig(file_content, always_true);
Bernie Innocentiac5ae3c2020-02-12 10:43:42 +0900488 ASSERT_RESULT_OK(result);
Orion Hodson9b16e342019-10-09 13:29:16 +0100489 ASSERT_EQ(expected_result, *result);
490}
491
492TEST(NativeLoaderConfigParser, WithNoPreload) {
493 const char file_content[] = R"(
494libA.so nopreload
495libB.so nopreload
496libC.so
497)";
498
499 const std::vector<std::string> expected_result = {"libC.so"};
500 Result<std::vector<std::string>> result =
501 ParseConfig(file_content,
502 [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; });
Bernie Innocentiac5ae3c2020-02-12 10:43:42 +0900503 ASSERT_RESULT_OK(result);
Orion Hodson9b16e342019-10-09 13:29:16 +0100504 ASSERT_EQ(expected_result, *result);
505}
506
507TEST(NativeLoaderConfigParser, WithNoPreloadAndBitness) {
508 const char file_content[] = R"(
509libA.so nopreload 32
510libB.so 64 nopreload
511libC.so 32
512libD.so 64
513libE.so nopreload
514)";
515
516#if defined(__LP64__)
517 const std::vector<std::string> expected_result = {"libD.so"};
518#else
519 const std::vector<std::string> expected_result = {"libC.so"};
520#endif
521 Result<std::vector<std::string>> result =
522 ParseConfig(file_content,
523 [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; });
Bernie Innocentiac5ae3c2020-02-12 10:43:42 +0900524 ASSERT_RESULT_OK(result);
Orion Hodson9b16e342019-10-09 13:29:16 +0100525 ASSERT_EQ(expected_result, *result);
526}
527
528TEST(NativeLoaderConfigParser, RejectMalformed) {
Bernie Innocentiac5ae3c2020-02-12 10:43:42 +0900529 ASSERT_FALSE(ParseConfig("libA.so 32 64", always_true).ok());
530 ASSERT_FALSE(ParseConfig("libA.so 32 32", always_true).ok());
531 ASSERT_FALSE(ParseConfig("libA.so 32 nopreload 64", always_true).ok());
532 ASSERT_FALSE(ParseConfig("32 libA.so nopreload", always_true).ok());
533 ASSERT_FALSE(ParseConfig("nopreload libA.so 32", always_true).ok());
534 ASSERT_FALSE(ParseConfig("libA.so nopreload # comment", always_true).ok());
Orion Hodson9b16e342019-10-09 13:29:16 +0100535}
536
Jooyung Hancd616d02020-09-01 14:53:23 +0900537TEST(NativeLoaderApexLibrariesConfigParser, BasicLoading) {
Jooyung Han538f99a2020-03-03 00:46:50 +0900538 const char file_content[] = R"(
539# comment
Jooyung Hancd616d02020-09-01 14:53:23 +0900540jni com_android_foo libfoo.so
Jooyung Han538f99a2020-03-03 00:46:50 +0900541# Empty line is ignored
542
Jooyung Hancd616d02020-09-01 14:53:23 +0900543jni com_android_bar libbar.so:libbar2.so
544
545 public com_android_bar libpublic.so
Jooyung Han538f99a2020-03-03 00:46:50 +0900546)";
547
Jooyung Hancd616d02020-09-01 14:53:23 +0900548 auto jni_libs = ParseApexLibrariesConfig(file_content, "jni");
549 ASSERT_RESULT_OK(jni_libs);
550 std::map<std::string, std::string> expected_jni_libs {
Jooyung Han538f99a2020-03-03 00:46:50 +0900551 {"com_android_foo", "libfoo.so"},
552 {"com_android_bar", "libbar.so:libbar2.so"},
553 };
Jooyung Hancd616d02020-09-01 14:53:23 +0900554 ASSERT_EQ(expected_jni_libs, *jni_libs);
Jooyung Han538f99a2020-03-03 00:46:50 +0900555
Jooyung Hancd616d02020-09-01 14:53:23 +0900556 auto public_libs = ParseApexLibrariesConfig(file_content, "public");
557 ASSERT_RESULT_OK(public_libs);
558 std::map<std::string, std::string> expected_public_libs {
559 {"com_android_bar", "libpublic.so"},
560 };
561 ASSERT_EQ(expected_public_libs, *public_libs);
Jooyung Han538f99a2020-03-03 00:46:50 +0900562}
563
Jooyung Hancd616d02020-09-01 14:53:23 +0900564TEST(NativeLoaderApexLibrariesConfigParser, RejectMalformedLine) {
565 const char file_content[] = R"(
566jni com_android_foo libfoo
567# missing <library list>
568jni com_android_bar
569)";
570 auto result = ParseApexLibrariesConfig(file_content, "jni");
571 ASSERT_FALSE(result.ok());
572 ASSERT_EQ("Malformed line \"jni com_android_bar\"", result.error().message());
Jooyung Han538f99a2020-03-03 00:46:50 +0900573}
574
Jooyung Hancd616d02020-09-01 14:53:23 +0900575TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidTag) {
576 const char file_content[] = R"(
577jni apex1 lib
578public apex2 lib
579# unknown tag
580unknown com_android_foo libfoo
581)";
582 auto result = ParseApexLibrariesConfig(file_content, "jni");
583 ASSERT_FALSE(result.ok());
584 ASSERT_EQ("Invalid tag \"unknown com_android_foo libfoo\"", result.error().message());
585}
586
587TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidApexNamespace) {
588 const char file_content[] = R"(
589# apex linker namespace should be mangled ('.' -> '_')
590jni com.android.foo lib
591)";
592 auto result = ParseApexLibrariesConfig(file_content, "jni");
593 ASSERT_FALSE(result.ok());
594 ASSERT_EQ("Invalid apex_namespace \"jni com.android.foo lib\"", result.error().message());
595}
596
597TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidLibraryList) {
598 const char file_content[] = R"(
599# library list is ":" separated list of filenames
600jni com_android_foo lib64/libfoo.so
601)";
602 auto result = ParseApexLibrariesConfig(file_content, "jni");
603 ASSERT_FALSE(result.ok());
604 ASSERT_EQ("Invalid library_list \"jni com_android_foo lib64/libfoo.so\"", result.error().message());
605}
606
Orion Hodson9b16e342019-10-09 13:29:16 +0100607} // namespace nativeloader
608} // namespace android
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100609
610#endif // defined(ART_TARGET_ANDROID)