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 #include "linkerconfig/namespace.h"
18 #include "linkerconfig/sectionbuilder.h"
19 
20 #include <functional>
21 #include <vector>
22 
23 #include "linkerconfig/common.h"
24 #include "linkerconfig/environment.h"
25 #include "linkerconfig/log.h"
26 #include "linkerconfig/namespacebuilder.h"
27 #include "linkerconfig/section.h"
28 
29 using android::linkerconfig::contents::SectionType;
30 using android::linkerconfig::modules::ApexInfo;
31 using android::linkerconfig::modules::LibProvider;
32 using android::linkerconfig::modules::LibProviders;
33 using android::linkerconfig::modules::Namespace;
34 using android::linkerconfig::modules::Section;
35 using android::linkerconfig::modules::SharedLibs;
36 
37 namespace android {
38 namespace linkerconfig {
39 namespace contents {
40 
41 // Builds default section for the apex
42 // For com.android.foo,
43 //   dir.com.android.foo = /apex/com.android.foo/bin
44 //   [com.android.foo]
45 //   additional.namespaces = system
46 //   namespace.default....
47 //   namespace.system...
BuildApexDefaultSection(Context & ctx,const ApexInfo & apex_info)48 Section BuildApexDefaultSection(Context& ctx, const ApexInfo& apex_info) {
49   ctx.SetCurrentSection(SectionType::Other);
50 
51   bool target_apex_visible = apex_info.visible;
52   std::set<std::string> visible_apexes;
53   if (apex_info.name == "com.android.art") {
54     // ld.config.txt for the ART module needs to have the namespaces with public
55     // and JNI libs visible since it runs dalvikvm and hence libnativeloader,
56     // which builds classloader namespaces that may link to those libs.
57     for (const auto& apex : ctx.GetApexModules()) {
58       if (apex.jni_libs.size() > 0 || apex.public_libs.size() > 0) {
59         visible_apexes.insert(apex.name);
60         if (apex.name == apex_info.name) {
61           target_apex_visible = true;
62         }
63       }
64     }
65   }
66 
67   std::vector<Namespace> namespaces;
68 
69   // If target APEX should be visible, then there will be two namespaces -
70   // default and APEX namespace - with same set of libraries. To avoid any
71   // confusion based on two same namespaces, and also to avoid loading same
72   // library twice based on the namespace, use empty default namespace which
73   // does not contain any search path and fully links to visible APEX namespace.
74   if (target_apex_visible) {
75     namespaces.emplace_back(BuildApexEmptyDefaultNamespace(ctx, apex_info));
76   } else {
77     namespaces.emplace_back(BuildApexDefaultNamespace(ctx, apex_info));
78   }
79   namespaces.emplace_back(BuildApexPlatformNamespace(ctx));
80 
81   // Vendor APEXes can use libs provided by "vendor"
82   // and Product APEXes can use libs provided by "product"
83   if (android::linkerconfig::modules::IsTreblelizedDevice()) {
84     if (apex_info.InVendor()) {
85       namespaces.emplace_back(BuildRsNamespace(ctx));
86       auto vendor = BuildVendorNamespace(ctx, "vendor");
87       if (!vendor.GetProvides().empty()) {
88         namespaces.emplace_back(std::move(vendor));
89       }
90       if (android::linkerconfig::modules::IsVendorVndkVersionDefined()) {
91         namespaces.emplace_back(
92             BuildVndkNamespace(ctx, VndkUserPartition::Vendor));
93         if (android::linkerconfig::modules::IsVndkInSystemNamespace()) {
94           namespaces.emplace_back(BuildVndkInSystemNamespace(ctx));
95         }
96       }
97     } else if (apex_info.InProduct()) {
98       auto product = BuildProductNamespace(ctx, "product");
99       if (!product.GetProvides().empty()) {
100         namespaces.emplace_back(std::move(product));
101       }
102       if (android::linkerconfig::modules::IsProductVndkVersionDefined()) {
103         namespaces.emplace_back(
104             BuildVndkNamespace(ctx, VndkUserPartition::Product));
105         if (android::linkerconfig::modules::IsVndkInSystemNamespace()) {
106           namespaces.emplace_back(BuildVndkInSystemNamespace(ctx));
107         }
108       }
109     }
110   }
111 
112   LibProviders libs_providers;
113   if (apex_info.InVendor()) {
114     // In Vendor APEX, sphal namespace is not required and possible to cause
115     // same library being loaded from two namespaces (sphal and vendor). As
116     // SPHAL itself is not required from vendor (APEX) section, add vendor
117     // namespace instead.
118     libs_providers[":sphal"] = {LibProvider{
119         "vendor",
120         std::bind(BuildVendorNamespace, ctx, "vendor"),
121         SharedLibs{{}},
122     }};
123   } else {
124     libs_providers[":sphal"] = {LibProvider{
125         "sphal",
126         std::bind(BuildSphalNamespace, ctx),
127         SharedLibs{{}},
128     }};
129   }
130 
131   bool in_vendor_with_vndk_enabled =
132       !apex_info.InProduct() &&
133       android::linkerconfig::modules::IsVendorVndkVersionDefined();
134   bool in_product_with_vndk_enabled =
135       apex_info.InProduct() &&
136       android::linkerconfig::modules::IsProductVndkVersionDefined();
137 
138   if (in_vendor_with_vndk_enabled || in_product_with_vndk_enabled) {
139     VndkUserPartition user_partition = VndkUserPartition::Vendor;
140     std::string user_partition_suffix = "VENDOR";
141     if (apex_info.InProduct()) {
142       user_partition = VndkUserPartition::Product;
143       user_partition_suffix = "PRODUCT";
144     }
145     libs_providers[":sanitizer"] = {LibProvider{
146         ctx.GetSystemNamespaceName(),
147         std::bind(BuildApexPlatformNamespace,
148                   ctx),  // "system" should be available
149         SharedLibs{{Var("SANITIZER_DEFAULT_" + user_partition_suffix)}},
150     }};
151     libs_providers[":vndk"] = GetVndkProvider(ctx, user_partition);
152     libs_providers[":vndksp"] = {LibProvider{
153         "vndk",
154         std::bind(BuildVndkNamespace, ctx, user_partition),
155         SharedLibs{{Var("VNDK_SAMEPROCESS_LIBRARIES_" + user_partition_suffix)}},
156     }};
157   } else if (apex_info.InProduct() || apex_info.InVendor()) {
158     // vendor or product partitions don't need this because they link LLNDK
159     // libs. however, vendor/product apexes still need to link LLNDK sanitizer
160     // libs even though these are not listed in "required".
161     libs_providers[":sanitizer"] = {LibProvider{
162         ctx.GetSystemNamespaceName(),
163         std::bind(BuildApexPlatformNamespace,
164                   ctx),  // "system" should be available
165         SharedLibs{{Var("SANITIZER_LIBRARIES_LLNDK")}},
166     }};
167   }
168 
169   if (apex_info.InVendor()) {
170     AddVendorSubdirNamespaceProviders(ctx, libs_providers);
171   }
172 
173   return BuildSection(
174       ctx, apex_info.name, std::move(namespaces), visible_apexes, libs_providers);
175 }
176 
177 }  // namespace contents
178 }  // namespace linkerconfig
179 }  // namespace android
180