1 /*
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 
17 #if defined(ART_TARGET_ANDROID)
18 
19 #include <dlfcn.h>
20 #include <memory>
21 #include <unordered_map>
22 
23 #include <android-base/strings.h>
24 #include <gmock/gmock.h>
25 #include <gtest/gtest.h>
26 #include <jni.h>
27 
28 #include "native_loader_namespace.h"
29 #include "nativehelper/scoped_utf_chars.h"
30 #include "nativeloader/dlext_namespaces.h"
31 #include "nativeloader/native_loader.h"
32 #include "public_libraries.h"
33 
34 namespace android {
35 namespace nativeloader {
36 
37 using ::testing::Eq;
38 using ::testing::Return;
39 using ::testing::StrEq;
40 using ::testing::_;
41 using internal::ConfigEntry;
42 using internal::ParseConfig;
43 using internal::ParseJniConfig;
44 
45 #if defined(__LP64__)
46 #define LIB_DIR "lib64"
47 #else
48 #define LIB_DIR "lib"
49 #endif
50 
51 // gmock interface that represents interested platform APIs on libdl and libnativebridge
52 class Platform {
53  public:
~Platform()54   virtual ~Platform() {}
55 
56   // libdl APIs
57   virtual void* dlopen(const char* filename, int flags) = 0;
58   virtual int dlclose(void* handle) = 0;
59   virtual char* dlerror(void) = 0;
60 
61   // These mock_* are the APIs semantically the same across libdl and libnativebridge.
62   // Instead of having two set of mock APIs for the two, define only one set with an additional
63   // argument 'bool bridged' to identify the context (i.e., called for libdl or libnativebridge).
64   typedef char* mock_namespace_handle;
65   virtual bool mock_init_anonymous_namespace(bool bridged, const char* sonames,
66                                              const char* search_paths) = 0;
67   virtual mock_namespace_handle mock_create_namespace(
68       bool bridged, const char* name, const char* ld_library_path, const char* default_library_path,
69       uint64_t type, const char* permitted_when_isolated_path, mock_namespace_handle parent) = 0;
70   virtual bool mock_link_namespaces(bool bridged, mock_namespace_handle from,
71                                     mock_namespace_handle to, const char* sonames) = 0;
72   virtual mock_namespace_handle mock_get_exported_namespace(bool bridged, const char* name) = 0;
73   virtual void* mock_dlopen_ext(bool bridged, const char* filename, int flags,
74                                 mock_namespace_handle ns) = 0;
75 
76   // libnativebridge APIs for which libdl has no corresponding APIs
77   virtual bool NativeBridgeInitialized() = 0;
78   virtual const char* NativeBridgeGetError() = 0;
79   virtual bool NativeBridgeIsPathSupported(const char*) = 0;
80   virtual bool NativeBridgeIsSupported(const char*) = 0;
81 
82   // To mock "ClassLoader Object.getParent()"
83   virtual const char* JniObject_getParent(const char*) = 0;
84 };
85 
86 // The mock does not actually create a namespace object. But simply casts the pointer to the
87 // string for the namespace name as the handle to the namespace object.
88 #define TO_ANDROID_NAMESPACE(str) \
89   reinterpret_cast<struct android_namespace_t*>(const_cast<char*>(str))
90 
91 #define TO_BRIDGED_NAMESPACE(str) \
92   reinterpret_cast<struct native_bridge_namespace_t*>(const_cast<char*>(str))
93 
94 #define TO_MOCK_NAMESPACE(ns) reinterpret_cast<Platform::mock_namespace_handle>(ns)
95 
96 // These represents built-in namespaces created by the linker according to ld.config.txt
97 static std::unordered_map<std::string, Platform::mock_namespace_handle> namespaces = {
98     {"system", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("system"))},
99     {"default", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("default"))},
100     {"com_android_i18n", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("com_android_i18n"))},
101     {"sphal", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("sphal"))},
102     {"vndk", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("vndk"))},
103     {"vndk_product", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("vndk_product"))},
104     {"com_android_neuralnetworks", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("com_android_neuralnetworks"))},
105     {"com_android_os_statsd", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("com_android_os_statsd"))},
106 };
107 
108 // The actual gmock object
109 class MockPlatform : public Platform {
110  public:
MockPlatform(bool is_bridged)111   explicit MockPlatform(bool is_bridged) : is_bridged_(is_bridged) {
112     ON_CALL(*this, NativeBridgeIsSupported(_)).WillByDefault(Return(is_bridged_));
113     ON_CALL(*this, NativeBridgeIsPathSupported(_)).WillByDefault(Return(is_bridged_));
114     ON_CALL(*this, mock_get_exported_namespace(_, _))
115         .WillByDefault(testing::Invoke([](bool, const char* name) -> mock_namespace_handle {
116           if (namespaces.find(name) != namespaces.end()) {
117             return namespaces[name];
118           }
119           return TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("(namespace not found"));
120         }));
121   }
122 
123   // Mocking libdl APIs
124   MOCK_METHOD2(dlopen, void*(const char*, int));
125   MOCK_METHOD1(dlclose, int(void*));
126   MOCK_METHOD0(dlerror, char*());
127 
128   // Mocking the common APIs
129   MOCK_METHOD3(mock_init_anonymous_namespace, bool(bool, const char*, const char*));
130   MOCK_METHOD7(mock_create_namespace,
131                mock_namespace_handle(bool, const char*, const char*, const char*, uint64_t,
132                                      const char*, mock_namespace_handle));
133   MOCK_METHOD4(mock_link_namespaces,
134                bool(bool, mock_namespace_handle, mock_namespace_handle, const char*));
135   MOCK_METHOD2(mock_get_exported_namespace, mock_namespace_handle(bool, const char*));
136   MOCK_METHOD4(mock_dlopen_ext, void*(bool, const char*, int, mock_namespace_handle));
137 
138   // Mocking libnativebridge APIs
139   MOCK_METHOD0(NativeBridgeInitialized, bool());
140   MOCK_METHOD0(NativeBridgeGetError, const char*());
141   MOCK_METHOD1(NativeBridgeIsPathSupported, bool(const char*));
142   MOCK_METHOD1(NativeBridgeIsSupported, bool(const char*));
143 
144   // Mocking "ClassLoader Object.getParent()"
145   MOCK_METHOD1(JniObject_getParent, const char*(const char*));
146 
147  private:
148   bool is_bridged_;
149 };
150 
151 static std::unique_ptr<MockPlatform> mock;
152 
153 // Provide C wrappers for the mock object.
154 extern "C" {
dlopen(const char * file,int flag)155 void* dlopen(const char* file, int flag) {
156   return mock->dlopen(file, flag);
157 }
158 
dlclose(void * handle)159 int dlclose(void* handle) {
160   return mock->dlclose(handle);
161 }
162 
dlerror(void)163 char* dlerror(void) {
164   return mock->dlerror();
165 }
166 
android_init_anonymous_namespace(const char * sonames,const char * search_path)167 bool android_init_anonymous_namespace(const char* sonames, const char* search_path) {
168   return mock->mock_init_anonymous_namespace(false, sonames, search_path);
169 }
170 
android_create_namespace(const char * name,const char * ld_library_path,const char * default_library_path,uint64_t type,const char * permitted_when_isolated_path,struct android_namespace_t * parent)171 struct android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
172                                                      const char* default_library_path,
173                                                      uint64_t type,
174                                                      const char* permitted_when_isolated_path,
175                                                      struct android_namespace_t* parent) {
176   return TO_ANDROID_NAMESPACE(
177       mock->mock_create_namespace(false, name, ld_library_path, default_library_path, type,
178                                   permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
179 }
180 
android_link_namespaces(struct android_namespace_t * from,struct android_namespace_t * to,const char * sonames)181 bool android_link_namespaces(struct android_namespace_t* from, struct android_namespace_t* to,
182                              const char* sonames) {
183   return mock->mock_link_namespaces(false, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
184 }
185 
android_get_exported_namespace(const char * name)186 struct android_namespace_t* android_get_exported_namespace(const char* name) {
187   return TO_ANDROID_NAMESPACE(mock->mock_get_exported_namespace(false, name));
188 }
189 
android_dlopen_ext(const char * filename,int flags,const android_dlextinfo * info)190 void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* info) {
191   return mock->mock_dlopen_ext(false, filename, flags, TO_MOCK_NAMESPACE(info->library_namespace));
192 }
193 
194 // libnativebridge APIs
NativeBridgeIsSupported(const char * libpath)195 bool NativeBridgeIsSupported(const char* libpath) {
196   return mock->NativeBridgeIsSupported(libpath);
197 }
198 
NativeBridgeGetExportedNamespace(const char * name)199 struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
200   return TO_BRIDGED_NAMESPACE(mock->mock_get_exported_namespace(true, name));
201 }
202 
NativeBridgeCreateNamespace(const char * name,const char * ld_library_path,const char * default_library_path,uint64_t type,const char * permitted_when_isolated_path,struct native_bridge_namespace_t * parent)203 struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
204     const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
205     const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent) {
206   return TO_BRIDGED_NAMESPACE(
207       mock->mock_create_namespace(true, name, ld_library_path, default_library_path, type,
208                                   permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
209 }
210 
NativeBridgeLinkNamespaces(struct native_bridge_namespace_t * from,struct native_bridge_namespace_t * to,const char * sonames)211 bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
212                                 struct native_bridge_namespace_t* to, const char* sonames) {
213   return mock->mock_link_namespaces(true, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
214 }
215 
NativeBridgeLoadLibraryExt(const char * libpath,int flag,struct native_bridge_namespace_t * ns)216 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
217                                  struct native_bridge_namespace_t* ns) {
218   return mock->mock_dlopen_ext(true, libpath, flag, TO_MOCK_NAMESPACE(ns));
219 }
220 
NativeBridgeInitialized()221 bool NativeBridgeInitialized() {
222   return mock->NativeBridgeInitialized();
223 }
224 
NativeBridgeInitAnonymousNamespace(const char * public_ns_sonames,const char * anon_ns_library_path)225 bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
226                                         const char* anon_ns_library_path) {
227   return mock->mock_init_anonymous_namespace(true, public_ns_sonames, anon_ns_library_path);
228 }
229 
NativeBridgeGetError()230 const char* NativeBridgeGetError() {
231   return mock->NativeBridgeGetError();
232 }
233 
NativeBridgeIsPathSupported(const char * path)234 bool NativeBridgeIsPathSupported(const char* path) {
235   return mock->NativeBridgeIsPathSupported(path);
236 }
237 
238 }  // extern "C"
239 
240 // A very simple JNI mock.
241 // jstring is a pointer to utf8 char array. We don't need utf16 char here.
242 // jobject, jclass, and jmethodID are also a pointer to utf8 char array
243 // Only a few JNI methods that are actually used in libnativeloader are mocked.
CreateJNINativeInterface()244 JNINativeInterface* CreateJNINativeInterface() {
245   JNINativeInterface* inf = new JNINativeInterface();
246   memset(inf, 0, sizeof(JNINativeInterface));
247 
248   inf->GetStringUTFChars = [](JNIEnv*, jstring s, jboolean*) -> const char* {
249     return reinterpret_cast<const char*>(s);
250   };
251 
252   inf->ReleaseStringUTFChars = [](JNIEnv*, jstring, const char*) -> void { return; };
253 
254   inf->NewStringUTF = [](JNIEnv*, const char* bytes) -> jstring {
255     return reinterpret_cast<jstring>(const_cast<char*>(bytes));
256   };
257 
258   inf->FindClass = [](JNIEnv*, const char* name) -> jclass {
259     return reinterpret_cast<jclass>(const_cast<char*>(name));
260   };
261 
262   inf->CallObjectMethodV = [](JNIEnv*, jobject obj, jmethodID mid, va_list) -> jobject {
263     if (strcmp("getParent", reinterpret_cast<const char*>(mid)) == 0) {
264       // JniObject_getParent can be a valid jobject or nullptr if there is
265       // no parent classloader.
266       const char* ret = mock->JniObject_getParent(reinterpret_cast<const char*>(obj));
267       return reinterpret_cast<jobject>(const_cast<char*>(ret));
268     }
269     return nullptr;
270   };
271 
272   inf->GetMethodID = [](JNIEnv*, jclass, const char* name, const char*) -> jmethodID {
273     return reinterpret_cast<jmethodID>(const_cast<char*>(name));
274   };
275 
276   inf->NewWeakGlobalRef = [](JNIEnv*, jobject obj) -> jobject { return obj; };
277 
278   inf->IsSameObject = [](JNIEnv*, jobject a, jobject b) -> jboolean {
279     return strcmp(reinterpret_cast<const char*>(a), reinterpret_cast<const char*>(b)) == 0;
280   };
281 
282   return inf;
283 }
284 
285 static void* const any_nonnull = reinterpret_cast<void*>(0x12345678);
286 
287 // Custom matcher for comparing namespace handles
288 MATCHER_P(NsEq, other, "") {
289   *result_listener << "comparing " << reinterpret_cast<const char*>(arg) << " and " << other;
290   return strcmp(reinterpret_cast<const char*>(arg), reinterpret_cast<const char*>(other)) == 0;
291 }
292 
293 /////////////////////////////////////////////////////////////////
294 
295 // Test fixture
296 class NativeLoaderTest : public ::testing::TestWithParam<bool> {
297  protected:
IsBridged()298   bool IsBridged() { return GetParam(); }
299 
SetUp()300   void SetUp() override {
301     mock = std::make_unique<testing::NiceMock<MockPlatform>>(IsBridged());
302 
303     env = std::make_unique<JNIEnv>();
304     env->functions = CreateJNINativeInterface();
305   }
306 
SetExpectations()307   void SetExpectations() {
308     std::vector<std::string> default_public_libs =
309         android::base::Split(preloadable_public_libraries(), ":");
310     for (auto l : default_public_libs) {
311       EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE))
312           .WillOnce(Return(any_nonnull));
313     }
314   }
315 
RunTest()316   void RunTest() { InitializeNativeLoader(); }
317 
TearDown()318   void TearDown() override {
319     ResetNativeLoader();
320     delete env->functions;
321     mock.reset();
322   }
323 
324   std::unique_ptr<JNIEnv> env;
325 };
326 
327 /////////////////////////////////////////////////////////////////
328 
TEST_P(NativeLoaderTest,InitializeLoadsDefaultPublicLibraries)329 TEST_P(NativeLoaderTest, InitializeLoadsDefaultPublicLibraries) {
330   SetExpectations();
331   RunTest();
332 }
333 
334 INSTANTIATE_TEST_SUITE_P(NativeLoaderTests, NativeLoaderTest, testing::Bool());
335 
336 /////////////////////////////////////////////////////////////////
337 
338 class NativeLoaderTest_Create : public NativeLoaderTest {
339  protected:
340   // Test inputs (initialized to the default values). Overriding these
341   // must be done before calling SetExpectations() and RunTest().
342   uint32_t target_sdk_version = 29;
343   std::string class_loader = "my_classloader";
344   bool is_shared = false;
345   std::string dex_path = "/data/app/foo/classes.dex";
346   std::string library_path = "/data/app/foo/" LIB_DIR "/arm";
347   std::string permitted_path = "/data/app/foo/" LIB_DIR;
348 
349   // expected output (.. for the default test inputs)
350   std::string expected_namespace_name = "classloader-namespace";
351   uint64_t expected_namespace_flags =
352       ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
353   std::string expected_library_path = library_path;
354   std::string expected_permitted_path = std::string("/data:/mnt/expand:") + permitted_path;
355   std::string expected_parent_namespace = "system";
356   bool expected_link_with_platform_ns = true;
357   bool expected_link_with_art_ns = true;
358   bool expected_link_with_i18n_ns = true;
359   bool expected_link_with_sphal_ns = !vendor_public_libraries().empty();
360   bool expected_link_with_vndk_ns = false;
361   bool expected_link_with_vndk_product_ns = false;
362   bool expected_link_with_default_ns = false;
363   bool expected_link_with_neuralnetworks_ns = true;
364   bool expected_link_with_statsd_ns = true;
365   std::string expected_shared_libs_to_platform_ns = default_public_libraries();
366   std::string expected_shared_libs_to_art_ns = art_public_libraries();
367   std::string expected_shared_libs_to_i18n_ns = i18n_public_libraries();
368   std::string expected_shared_libs_to_sphal_ns = vendor_public_libraries();
369   std::string expected_shared_libs_to_vndk_ns = vndksp_libraries_vendor();
370   std::string expected_shared_libs_to_vndk_product_ns = vndksp_libraries_product();
371   std::string expected_shared_libs_to_default_ns = default_public_libraries();
372   std::string expected_shared_libs_to_neuralnetworks_ns = neuralnetworks_public_libraries();
373   std::string expected_shared_libs_to_statsd_ns = statsd_public_libraries();
374 
SetExpectations()375   void SetExpectations() {
376     NativeLoaderTest::SetExpectations();
377 
378     ON_CALL(*mock, JniObject_getParent(StrEq(class_loader))).WillByDefault(Return(nullptr));
379 
380     EXPECT_CALL(*mock, NativeBridgeIsPathSupported(_)).Times(testing::AnyNumber());
381     EXPECT_CALL(*mock, NativeBridgeInitialized()).Times(testing::AnyNumber());
382 
383     EXPECT_CALL(*mock, mock_create_namespace(
384                            Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
385                            StrEq(expected_library_path), expected_namespace_flags,
386                            StrEq(expected_permitted_path), NsEq(expected_parent_namespace.c_str())))
387         .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(dex_path.c_str()))));
388     if (expected_link_with_platform_ns) {
389       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("system"),
390                                               StrEq(expected_shared_libs_to_platform_ns)))
391           .WillOnce(Return(true));
392     }
393     if (expected_link_with_art_ns) {
394       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_art"),
395                                               StrEq(expected_shared_libs_to_art_ns)))
396           .WillOnce(Return(true));
397     }
398     if (expected_link_with_i18n_ns) {
399       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_i18n"),
400                                               StrEq(expected_shared_libs_to_i18n_ns)))
401           .WillOnce(Return(true));
402     }
403     if (expected_link_with_sphal_ns) {
404       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("sphal"),
405                                               StrEq(expected_shared_libs_to_sphal_ns)))
406           .WillOnce(Return(true));
407     }
408     if (expected_link_with_vndk_ns) {
409       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("vndk"),
410                                               StrEq(expected_shared_libs_to_vndk_ns)))
411           .WillOnce(Return(true));
412     }
413     if (expected_link_with_vndk_product_ns) {
414       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("vndk_product"),
415                                               StrEq(expected_shared_libs_to_vndk_product_ns)))
416           .WillOnce(Return(true));
417     }
418     if (expected_link_with_default_ns) {
419       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("default"),
420                                               StrEq(expected_shared_libs_to_default_ns)))
421           .WillOnce(Return(true));
422     }
423     if (expected_link_with_neuralnetworks_ns) {
424       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_neuralnetworks"),
425                                               StrEq(expected_shared_libs_to_neuralnetworks_ns)))
426           .WillOnce(Return(true));
427     }
428     if (expected_link_with_statsd_ns) {
429       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_os_statsd"),
430                                               StrEq(expected_shared_libs_to_statsd_ns)))
431           .WillOnce(Return(true));
432     }
433   }
434 
RunTest()435   void RunTest() {
436     NativeLoaderTest::RunTest();
437 
438     jstring err = CreateClassLoaderNamespace(
439         env(), target_sdk_version, env()->NewStringUTF(class_loader.c_str()), is_shared,
440         env()->NewStringUTF(dex_path.c_str()), env()->NewStringUTF(library_path.c_str()),
441         env()->NewStringUTF(permitted_path.c_str()));
442 
443     // no error
444     EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env(), err).c_str());
445 
446     if (!IsBridged()) {
447       struct android_namespace_t* ns =
448           FindNamespaceByClassLoader(env(), env()->NewStringUTF(class_loader.c_str()));
449 
450       // The created namespace is for this apk
451       EXPECT_EQ(dex_path.c_str(), reinterpret_cast<const char*>(ns));
452     } else {
453       struct NativeLoaderNamespace* ns =
454           FindNativeLoaderNamespaceByClassLoader(env(), env()->NewStringUTF(class_loader.c_str()));
455 
456       // The created namespace is for the this apk
457       EXPECT_STREQ(dex_path.c_str(),
458                    reinterpret_cast<const char*>(ns->ToRawNativeBridgeNamespace()));
459     }
460   }
461 
env()462   JNIEnv* env() { return NativeLoaderTest::env.get(); }
463 };
464 
TEST_P(NativeLoaderTest_Create,DownloadedApp)465 TEST_P(NativeLoaderTest_Create, DownloadedApp) {
466   SetExpectations();
467   RunTest();
468 }
469 
TEST_P(NativeLoaderTest_Create,BundledSystemApp)470 TEST_P(NativeLoaderTest_Create, BundledSystemApp) {
471   dex_path = "/system/app/foo/foo.apk";
472   is_shared = true;
473 
474   expected_namespace_name = "classloader-namespace-shared";
475   expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
476   SetExpectations();
477   RunTest();
478 }
479 
TEST_P(NativeLoaderTest_Create,BundledVendorApp)480 TEST_P(NativeLoaderTest_Create, BundledVendorApp) {
481   dex_path = "/vendor/app/foo/foo.apk";
482   is_shared = true;
483 
484   expected_namespace_name = "classloader-namespace-shared";
485   expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
486   SetExpectations();
487   RunTest();
488 }
489 
TEST_P(NativeLoaderTest_Create,UnbundledVendorApp)490 TEST_P(NativeLoaderTest_Create, UnbundledVendorApp) {
491   dex_path = "/vendor/app/foo/foo.apk";
492   is_shared = false;
493 
494   expected_namespace_name = "vendor-classloader-namespace";
495   expected_library_path = expected_library_path + ":/vendor/" LIB_DIR;
496   expected_permitted_path = expected_permitted_path + ":/vendor/" LIB_DIR;
497   expected_shared_libs_to_platform_ns =
498       expected_shared_libs_to_platform_ns + ":" + llndk_libraries_vendor();
499   expected_link_with_vndk_ns = true;
500   SetExpectations();
501   RunTest();
502 }
503 
TEST_P(NativeLoaderTest_Create,BundledProductApp)504 TEST_P(NativeLoaderTest_Create, BundledProductApp) {
505   dex_path = "/product/app/foo/foo.apk";
506   is_shared = true;
507 
508   expected_namespace_name = "classloader-namespace-shared";
509   expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
510   SetExpectations();
511   RunTest();
512 }
513 
TEST_P(NativeLoaderTest_Create,UnbundledProductApp)514 TEST_P(NativeLoaderTest_Create, UnbundledProductApp) {
515   dex_path = "/product/app/foo/foo.apk";
516   is_shared = false;
517 
518   if (is_product_vndk_version_defined()) {
519     expected_namespace_name = "vendor-classloader-namespace";
520     expected_library_path = expected_library_path + ":/product/" LIB_DIR ":/system/product/" LIB_DIR;
521     expected_permitted_path =
522         expected_permitted_path + ":/product/" LIB_DIR ":/system/product/" LIB_DIR;
523     expected_shared_libs_to_platform_ns =
524         expected_shared_libs_to_platform_ns + ":" + llndk_libraries_product();
525     expected_link_with_vndk_product_ns = true;
526   }
527   SetExpectations();
528   RunTest();
529 }
530 
TEST_P(NativeLoaderTest_Create,NamespaceForSharedLibIsNotUsedAsAnonymousNamespace)531 TEST_P(NativeLoaderTest_Create, NamespaceForSharedLibIsNotUsedAsAnonymousNamespace) {
532   if (IsBridged()) {
533     // There is no shared lib in translated arch
534     // TODO(jiyong): revisit this
535     return;
536   }
537   // compared to apks, for java shared libs, library_path is empty; java shared
538   // libs don't have their own native libs. They use platform's.
539   library_path = "";
540   expected_library_path = library_path;
541   // no ALSO_USED_AS_ANONYMOUS
542   expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
543   SetExpectations();
544   RunTest();
545 }
546 
TEST_P(NativeLoaderTest_Create,TwoApks)547 TEST_P(NativeLoaderTest_Create, TwoApks) {
548   SetExpectations();
549   const uint32_t second_app_target_sdk_version = 29;
550   const std::string second_app_class_loader = "second_app_classloader";
551   const bool second_app_is_shared = false;
552   const std::string second_app_dex_path = "/data/app/bar/classes.dex";
553   const std::string second_app_library_path = "/data/app/bar/" LIB_DIR "/arm";
554   const std::string second_app_permitted_path = "/data/app/bar/" LIB_DIR;
555   const std::string expected_second_app_permitted_path =
556       std::string("/data:/mnt/expand:") + second_app_permitted_path;
557   const std::string expected_second_app_parent_namespace = "classloader-namespace";
558   // no ALSO_USED_AS_ANONYMOUS
559   const uint64_t expected_second_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
560 
561   // The scenario is that second app is loaded by the first app.
562   // So the first app's classloader (`classloader`) is parent of the second
563   // app's classloader.
564   ON_CALL(*mock, JniObject_getParent(StrEq(second_app_class_loader)))
565       .WillByDefault(Return(class_loader.c_str()));
566 
567   // namespace for the second app is created. Its parent is set to the namespace
568   // of the first app.
569   EXPECT_CALL(*mock, mock_create_namespace(
570                          Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
571                          StrEq(second_app_library_path), expected_second_namespace_flags,
572                          StrEq(expected_second_app_permitted_path), NsEq(dex_path.c_str())))
573       .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(second_app_dex_path.c_str()))));
574   EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), NsEq(second_app_dex_path.c_str()), _, _))
575       .WillRepeatedly(Return(true));
576 
577   RunTest();
578   jstring err = CreateClassLoaderNamespace(
579       env(), second_app_target_sdk_version, env()->NewStringUTF(second_app_class_loader.c_str()),
580       second_app_is_shared, env()->NewStringUTF(second_app_dex_path.c_str()),
581       env()->NewStringUTF(second_app_library_path.c_str()),
582       env()->NewStringUTF(second_app_permitted_path.c_str()));
583 
584   // success
585   EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env(), err).c_str());
586 
587   if (!IsBridged()) {
588     struct android_namespace_t* ns =
589         FindNamespaceByClassLoader(env(), env()->NewStringUTF(second_app_class_loader.c_str()));
590 
591     // The created namespace is for the second apk
592     EXPECT_EQ(second_app_dex_path.c_str(), reinterpret_cast<const char*>(ns));
593   } else {
594     struct NativeLoaderNamespace* ns = FindNativeLoaderNamespaceByClassLoader(
595         env(), env()->NewStringUTF(second_app_class_loader.c_str()));
596 
597     // The created namespace is for the second apk
598     EXPECT_STREQ(second_app_dex_path.c_str(),
599                  reinterpret_cast<const char*>(ns->ToRawNativeBridgeNamespace()));
600   }
601 }
602 
603 INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool());
604 
605 const std::function<Result<bool>(const struct ConfigEntry&)> always_true =
__anona7cbf4c60a02(const struct ConfigEntry&) 606     [](const struct ConfigEntry&) -> Result<bool> { return true; };
607 
TEST(NativeLoaderConfigParser,NamesAndComments)608 TEST(NativeLoaderConfigParser, NamesAndComments) {
609   const char file_content[] = R"(
610 ######
611 
612 libA.so
613 #libB.so
614 
615 
616       libC.so
617 libD.so
618     #### libE.so
619 )";
620   const std::vector<std::string> expected_result = {"libA.so", "libC.so", "libD.so"};
621   Result<std::vector<std::string>> result = ParseConfig(file_content, always_true);
622   ASSERT_RESULT_OK(result);
623   ASSERT_EQ(expected_result, *result);
624 }
625 
TEST(NativeLoaderConfigParser,WithBitness)626 TEST(NativeLoaderConfigParser, WithBitness) {
627   const char file_content[] = R"(
628 libA.so 32
629 libB.so 64
630 libC.so
631 )";
632 #if defined(__LP64__)
633   const std::vector<std::string> expected_result = {"libB.so", "libC.so"};
634 #else
635   const std::vector<std::string> expected_result = {"libA.so", "libC.so"};
636 #endif
637   Result<std::vector<std::string>> result = ParseConfig(file_content, always_true);
638   ASSERT_RESULT_OK(result);
639   ASSERT_EQ(expected_result, *result);
640 }
641 
TEST(NativeLoaderConfigParser,WithNoPreload)642 TEST(NativeLoaderConfigParser, WithNoPreload) {
643   const char file_content[] = R"(
644 libA.so nopreload
645 libB.so nopreload
646 libC.so
647 )";
648 
649   const std::vector<std::string> expected_result = {"libC.so"};
650   Result<std::vector<std::string>> result =
651       ParseConfig(file_content,
652                   [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; });
653   ASSERT_RESULT_OK(result);
654   ASSERT_EQ(expected_result, *result);
655 }
656 
TEST(NativeLoaderConfigParser,WithNoPreloadAndBitness)657 TEST(NativeLoaderConfigParser, WithNoPreloadAndBitness) {
658   const char file_content[] = R"(
659 libA.so nopreload 32
660 libB.so 64 nopreload
661 libC.so 32
662 libD.so 64
663 libE.so nopreload
664 )";
665 
666 #if defined(__LP64__)
667   const std::vector<std::string> expected_result = {"libD.so"};
668 #else
669   const std::vector<std::string> expected_result = {"libC.so"};
670 #endif
671   Result<std::vector<std::string>> result =
672       ParseConfig(file_content,
673                   [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; });
674   ASSERT_RESULT_OK(result);
675   ASSERT_EQ(expected_result, *result);
676 }
677 
TEST(NativeLoaderConfigParser,RejectMalformed)678 TEST(NativeLoaderConfigParser, RejectMalformed) {
679   ASSERT_FALSE(ParseConfig("libA.so 32 64", always_true).ok());
680   ASSERT_FALSE(ParseConfig("libA.so 32 32", always_true).ok());
681   ASSERT_FALSE(ParseConfig("libA.so 32 nopreload 64", always_true).ok());
682   ASSERT_FALSE(ParseConfig("32 libA.so nopreload", always_true).ok());
683   ASSERT_FALSE(ParseConfig("nopreload libA.so 32", always_true).ok());
684   ASSERT_FALSE(ParseConfig("libA.so nopreload # comment", always_true).ok());
685 }
686 
TEST(NativeLoaderJniConfigParser,BasicLoading)687 TEST(NativeLoaderJniConfigParser, BasicLoading) {
688   const char file_content[] = R"(
689 # comment
690 com_android_foo libfoo.so
691 # Empty line is ignored
692 
693 com_android_bar libbar.so:libbar2.so
694 )";
695 
696   std::map<std::string, std::string> expected_result{
697     {"com_android_foo", "libfoo.so"},
698     {"com_android_bar", "libbar.so:libbar2.so"},
699   };
700 
701   Result<std::map<std::string, std::string>> result = ParseJniConfig(file_content);
702   ASSERT_RESULT_OK(result);
703   ASSERT_EQ(expected_result, *result);
704 }
705 
TEST(NativeLoaderJniConfigParser,RejectMalformed)706 TEST(NativeLoaderJniConfigParser, RejectMalformed) {
707   ASSERT_FALSE(ParseJniConfig("com_android_foo").ok());
708 }
709 
710 }  // namespace nativeloader
711 }  // namespace android
712 
713 #endif  // defined(ART_TARGET_ANDROID)
714