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 
19 #include <android-base/strings.h>
20 
21 #include "linkerconfig/apex.h"
22 #include "linkerconfig/log.h"
23 
24 namespace {
25 
26 constexpr const char* kDataAsanPath = "/data/asan";
27 
28 bool FindFromPathList(const std::vector<std::string>& list,
29                       const std::string& path) {
30   for (auto& path_member : list) {
31     for (auto& path_item : android::base::Split(path_member, ":")) {
32       if (path_item == path) return true;
33     }
34   }
35 
36   return false;
37 }
38 
39 }  // namespace
40 
41 namespace android {
42 namespace linkerconfig {
43 namespace modules {
44 
45 void InitializeWithApex(Namespace& ns, const ApexInfo& apex_info) {
46   ns.AddSearchPath(apex_info.path + "/${LIB}");
47   ns.AddPermittedPath(apex_info.path + "/${LIB}");
48   ns.AddPermittedPath("/system/${LIB}");
49   ns.AddProvides(apex_info.provide_libs);
50   ns.AddRequires(apex_info.require_libs);
51 }
52 
53 Link& Namespace::GetLink(const std::string& target_namespace) {
54   for (auto& link : links_) {
55     if (link.To() == target_namespace) {
56       return link;
57     }
58   }
59   return links_.emplace_back(name_, target_namespace);
60 }
61 
62 void Namespace::WriteConfig(ConfigWriter& writer) {
63   const auto prefix = "namespace." + name_ + ".";
64 
65   writer.WriteLine(prefix + "isolated = " + (is_isolated_ ? "true" : "false"));
66 
67   if (is_visible_) {
68     writer.WriteLine(prefix + "visible = true");
69   }
70 
71   writer.WriteVars(prefix + "search.paths", search_paths_);
72   writer.WriteVars(prefix + "permitted.paths", permitted_paths_);
73   writer.WriteVars(prefix + "asan.search.paths", asan_search_paths_);
74   writer.WriteVars(prefix + "asan.permitted.paths", asan_permitted_paths_);
75   writer.WriteVars(prefix + "whitelisted", whitelisted_);
76 
77   if (!links_.empty()) {
78     std::vector<std::string> link_list;
79     link_list.reserve(links_.size());
80     for (const auto& link : links_) {
81       link_list.push_back(link.To());
82     }
83     writer.WriteLine(prefix + "links = " + android::base::Join(link_list, ","));
84 
85     for (const auto& link : links_) {
86       link.WriteConfig(writer);
87     }
88   }
89 }
90 
91 void Namespace::AddSearchPath(const std::string& path, AsanPath path_from_asan) {
92   search_paths_.push_back(path);
93 
94   switch (path_from_asan) {
95     case AsanPath::NONE:
96       break;
97     case AsanPath::SAME_PATH:
98       asan_search_paths_.push_back(path);
99       break;
100     case AsanPath::WITH_DATA_ASAN:
101       asan_search_paths_.push_back(kDataAsanPath + path);
102       asan_search_paths_.push_back(path);
103       break;
104   }
105 }
106 
107 void Namespace::AddPermittedPath(const std::string& path,
108                                  AsanPath path_from_asan) {
109   permitted_paths_.push_back(path);
110 
111   switch (path_from_asan) {
112     case AsanPath::NONE:
113       break;
114     case AsanPath::SAME_PATH:
115       asan_permitted_paths_.push_back(path);
116       break;
117     case AsanPath::WITH_DATA_ASAN:
118       asan_permitted_paths_.push_back(kDataAsanPath + path);
119       asan_permitted_paths_.push_back(path);
120       break;
121   }
122 }
123 
124 void Namespace::AddWhitelisted(const std::string& path) {
125   whitelisted_.push_back(path);
126 }
127 
128 std::string Namespace::GetName() const {
129   return name_;
130 }
131 
132 bool Namespace::ContainsSearchPath(const std::string& path,
133                                    AsanPath path_from_asan) {
134   return FindFromPathList(search_paths_, path) &&
135          (path_from_asan == AsanPath::NONE ||
136           FindFromPathList(asan_search_paths_, path)) &&
137          (path_from_asan != AsanPath::WITH_DATA_ASAN ||
138           FindFromPathList(asan_search_paths_, kDataAsanPath + path));
139 }
140 
141 bool Namespace::ContainsPermittedPath(const std::string& path,
142                                       AsanPath path_from_asan) {
143   return FindFromPathList(permitted_paths_, path) &&
144          (path_from_asan == AsanPath::NONE ||
145           FindFromPathList(asan_permitted_paths_, path)) &&
146          (path_from_asan != AsanPath::WITH_DATA_ASAN ||
147           FindFromPathList(asan_permitted_paths_, kDataAsanPath + path));
148 }
149 
150 }  // namespace modules
151 }  // namespace linkerconfig
152 }  // namespace android
153