1 /*
2  * Copyright (C) 2020 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 "linkerconfig/apexconfig.h"
18 
19 #include <android-base/file.h>
20 #include <apex_manifest.pb.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <vector>
24 
25 #include "configurationtest.h"
26 #include "linkerconfig/apex.h"
27 #include "linkerconfig/configwriter.h"
28 #include "mockenv.h"
29 
30 using android::linkerconfig::contents::Context;
31 using android::linkerconfig::contents::CreateApexConfiguration;
32 using android::linkerconfig::modules::ApexInfo;
33 using ::testing::Contains;
34 
35 namespace {
36 struct ApexConfigTest : ::testing::Test {
SetUp__anon19652efa0111::ApexConfigTest37   void SetUp() override {
38     MockGenericVariables();
39   }
40 
PrepareApex__anon19652efa0111::ApexConfigTest41   ApexInfo PrepareApex(const std::string& apex_name,
42                        const std::vector<std::string>& provide_libs,
43                        const std::vector<std::string>& require_libs) {
44     return ApexInfo(apex_name,
45                     "/apex/" + apex_name,
46                     provide_libs,
47                     require_libs,
48                     /*jni_libs=*/{},
49                     /*permitted_paths=*/{},
50                     /*has_bin=*/true,
51                     /*has_lib=*/true,
52                     /*visible=*/false,
53                     /*has_shared_lib=*/false);
54   }
55 };
56 }  // namespace
57 
TEST_F(ApexConfigTest,apex_no_dependency)58 TEST_F(ApexConfigTest, apex_no_dependency) {
59   android::linkerconfig::contents::Context ctx;
60   auto target_apex = PrepareApex("target", {}, {});
61   auto config = android::linkerconfig::contents::CreateApexConfiguration(
62       ctx, target_apex);
63 
64   android::linkerconfig::modules::ConfigWriter config_writer;
65   config.WriteConfig(config_writer);
66 
67   VerifyConfiguration(config_writer.ToString());
68 }
69 
TEST_F(ApexConfigTest,apex_with_required)70 TEST_F(ApexConfigTest, apex_with_required) {
71   android::linkerconfig::contents::Context ctx;
72   ctx.SetApexModules({PrepareApex("foo", {"a.so"}, {"b.so"}),
73                       PrepareApex("bar", {"b.so"}, {}),
74                       PrepareApex("baz", {"c.so"}, {"a.so"})});
75   auto target_apex = PrepareApex("target", {}, {"a.so", "b.so"});
76   auto config = android::linkerconfig::contents::CreateApexConfiguration(
77       ctx, target_apex);
78 
79   android::linkerconfig::modules::ConfigWriter config_writer;
80   config.WriteConfig(config_writer);
81 
82   VerifyConfiguration(config_writer.ToString());
83 }
84 
TEST_F(ApexConfigTest,vndk_in_system_vendor_apex)85 TEST_F(ApexConfigTest, vndk_in_system_vendor_apex) {
86   MockVndkUsingCoreVariant();
87   android::linkerconfig::contents::Context ctx;
88 
89   android::linkerconfig::proto::LinkerConfig vendor_config;
90   vendor_config.add_providelibs("libvendorprovide.so");
91   ctx.SetVendorConfig(vendor_config);
92 
93   auto vendor_apex =
94       PrepareApex("vendor_apex", {}, {":vndk", "libvendorprovide.so"});
95   vendor_apex.original_path = "/vendor/apex/com.android.vendor";
96   ctx.SetApexModules({vendor_apex, CreateTestVndkApex()});
97   auto config = android::linkerconfig::contents::CreateApexConfiguration(
98       ctx, vendor_apex);
99 
100   android::linkerconfig::modules::ConfigWriter config_writer;
101   config.WriteConfig(config_writer);
102 
103   VerifyConfiguration(config_writer.ToString());
104 }
105 
TEST_F(ApexConfigTest,vndk_in_system_product_apex)106 TEST_F(ApexConfigTest, vndk_in_system_product_apex) {
107   MockVndkUsingCoreVariant();
108   android::linkerconfig::contents::Context ctx;
109 
110   android::linkerconfig::proto::LinkerConfig product_config;
111   product_config.add_providelibs("libproductprovide.so");
112   ctx.SetProductConfig(product_config);
113 
114   auto product_apex =
115       PrepareApex("product_apex", {}, {":vndksp", "libproductprovide.so"});
116   product_apex.original_path = "/product/apex/com.android.product";
117   ctx.SetApexModules({product_apex, CreateTestVndkApex()});
118   auto config = android::linkerconfig::contents::CreateApexConfiguration(
119       ctx, product_apex);
120 
121   android::linkerconfig::modules::ConfigWriter config_writer;
122   config.WriteConfig(config_writer);
123 
124   VerifyConfiguration(config_writer.ToString());
125 }
126 
TEST_F(ApexConfigTest,vendor_apex_without_use_vndk_as_stable)127 TEST_F(ApexConfigTest, vendor_apex_without_use_vndk_as_stable) {
128   android::linkerconfig::contents::Context ctx;
129 
130   android::linkerconfig::proto::LinkerConfig vendor_config;
131   vendor_config.add_requirelibs("libapexprovide.so");
132   vendor_config.add_providelibs("libvendorprovide.so");
133   ctx.SetVendorConfig(vendor_config);
134 
135   // Vendor apex requires :vndk
136   auto vendor_apex = PrepareApex(
137       "com.android.vendor", {"libapexprovide.so"}, {"libvendorprovide.so"});
138   vendor_apex.original_path = "/vendor/apex/com.android.vendor";
139   ctx.SetApexModules({vendor_apex, CreateTestVndkApex()});
140 
141   auto config = CreateApexConfiguration(ctx, vendor_apex);
142 
143   auto* section = config.GetSection("com.android.vendor");
144   ASSERT_TRUE(section);
145 
146   // vendor apex should be able to load vndk libraries
147   auto vndk_namespace = section->GetNamespace("vndk");
148   ASSERT_TRUE(vndk_namespace);
149 
150   android::linkerconfig::modules::ConfigWriter config_writer;
151   config.WriteConfig(config_writer);
152   VerifyConfiguration(config_writer.ToString());
153 }
154 
155 // [apex]com.android.target --(require)--> missing.so
TEST_F(ApexConfigTest,StrictModeRejects_MissingRequiredLibs)156 TEST_F(ApexConfigTest, StrictModeRejects_MissingRequiredLibs) {
157   const std::string apex_name = "com.android.target";
158   Context ctx;
159   ctx.SetApexModules({CreateTestVndkApex()});
160   ctx.SetStrictMode(true);
161   ctx.SetTargetApex(apex_name);
162   auto apex = PrepareApex(apex_name, {}, /*require_libs=*/{"missing.so"});
163   ASSERT_EXIT(CreateApexConfiguration(ctx, apex),
164               testing::KilledBySignal(SIGABRT),
165 #ifndef __ANDROID__
166               "not found:.*missing\\.so"
167 #else
168               ""
169 #endif
170   );
171 }
172 
173 // [apex]com.android.target                          [apex]com.android.other
174 //                  `--(require)--> other.so <--(provide)--'  |
175 //                                                            `-(require)--> missing.so
TEST_F(ApexConfigTest,StrictModeAccepts_MissingRequiredLibsInOtherApex)176 TEST_F(ApexConfigTest, StrictModeAccepts_MissingRequiredLibsInOtherApex) {
177   const std::string apex_name = "com.android.target";
178   Context ctx;
179   ctx.SetStrictMode(true);
180   ctx.SetTargetApex(apex_name);
181   ctx.SetApexModules({PrepareApex("com.android.other",
182                                   /*provide_libs=*/{"other.so"},
183                                   /*require_libs=*/{"missing.so"}),
184                       CreateTestVndkApex()});
185   auto apex = PrepareApex(apex_name, {}, /*require_libs=*/{"other.so"});
186   auto config = CreateApexConfiguration(ctx, apex);
187   auto section = config.GetSection("com.android.target");
188   auto ns = section->GetNamespace("default");
189   ASSERT_THAT(ns->GetLink("com_android_other").GetSharedLibs(),
190               Contains("other.so"));
191 }
192