xref: /aosp_15_r20/bionic/linker/linker_config.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker  *
5*8d67ca89SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker  * are met:
8*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
12*8d67ca89SAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
13*8d67ca89SAndroid Build Coastguard Worker  *    distribution.
14*8d67ca89SAndroid Build Coastguard Worker  *
15*8d67ca89SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*8d67ca89SAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*8d67ca89SAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*8d67ca89SAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*8d67ca89SAndroid Build Coastguard Worker  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*8d67ca89SAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*8d67ca89SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*8d67ca89SAndroid Build Coastguard Worker  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*8d67ca89SAndroid Build Coastguard Worker  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*8d67ca89SAndroid Build Coastguard Worker  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*8d67ca89SAndroid Build Coastguard Worker  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8d67ca89SAndroid Build Coastguard Worker  * SUCH DAMAGE.
27*8d67ca89SAndroid Build Coastguard Worker  */
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker #include "linker_config.h"
30*8d67ca89SAndroid Build Coastguard Worker 
31*8d67ca89SAndroid Build Coastguard Worker #include "linker_globals.h"
32*8d67ca89SAndroid Build Coastguard Worker #include "linker_debug.h"
33*8d67ca89SAndroid Build Coastguard Worker #include "linker_utils.h"
34*8d67ca89SAndroid Build Coastguard Worker 
35*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
36*8d67ca89SAndroid Build Coastguard Worker #include <android-base/properties.h>
37*8d67ca89SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
38*8d67ca89SAndroid Build Coastguard Worker #include <android-base/strings.h>
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker #include <async_safe/log.h>
41*8d67ca89SAndroid Build Coastguard Worker 
42*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
43*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
44*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
45*8d67ca89SAndroid Build Coastguard Worker 
46*8d67ca89SAndroid Build Coastguard Worker #include <string>
47*8d67ca89SAndroid Build Coastguard Worker #include <unordered_map>
48*8d67ca89SAndroid Build Coastguard Worker 
49*8d67ca89SAndroid Build Coastguard Worker class ConfigParser {
50*8d67ca89SAndroid Build Coastguard Worker  public:
51*8d67ca89SAndroid Build Coastguard Worker   enum {
52*8d67ca89SAndroid Build Coastguard Worker     kPropertyAssign,
53*8d67ca89SAndroid Build Coastguard Worker     kPropertyAppend,
54*8d67ca89SAndroid Build Coastguard Worker     kSection,
55*8d67ca89SAndroid Build Coastguard Worker     kEndOfFile,
56*8d67ca89SAndroid Build Coastguard Worker     kError,
57*8d67ca89SAndroid Build Coastguard Worker   };
58*8d67ca89SAndroid Build Coastguard Worker 
ConfigParser(std::string && content)59*8d67ca89SAndroid Build Coastguard Worker   explicit ConfigParser(std::string&& content)
60*8d67ca89SAndroid Build Coastguard Worker       : content_(std::move(content)), p_(0), lineno_(0), was_end_of_file_(false) {}
61*8d67ca89SAndroid Build Coastguard Worker 
62*8d67ca89SAndroid Build Coastguard Worker   /*
63*8d67ca89SAndroid Build Coastguard Worker    * Possible return values
64*8d67ca89SAndroid Build Coastguard Worker    * kPropertyAssign: name is set to property name and value is set to property value
65*8d67ca89SAndroid Build Coastguard Worker    * kPropertyAppend: same as kPropertyAssign, but the value should be appended
66*8d67ca89SAndroid Build Coastguard Worker    * kSection: name is set to section name.
67*8d67ca89SAndroid Build Coastguard Worker    * kEndOfFile: reached end of file.
68*8d67ca89SAndroid Build Coastguard Worker    * kError: error_msg is set.
69*8d67ca89SAndroid Build Coastguard Worker    */
next_token(std::string * name,std::string * value,std::string * error_msg)70*8d67ca89SAndroid Build Coastguard Worker   int next_token(std::string* name, std::string* value, std::string* error_msg) {
71*8d67ca89SAndroid Build Coastguard Worker     std::string line;
72*8d67ca89SAndroid Build Coastguard Worker     while(NextLine(&line)) {
73*8d67ca89SAndroid Build Coastguard Worker       size_t found = line.find('#');
74*8d67ca89SAndroid Build Coastguard Worker       line = android::base::Trim(line.substr(0, found));
75*8d67ca89SAndroid Build Coastguard Worker 
76*8d67ca89SAndroid Build Coastguard Worker       if (line.empty()) {
77*8d67ca89SAndroid Build Coastguard Worker         continue;
78*8d67ca89SAndroid Build Coastguard Worker       }
79*8d67ca89SAndroid Build Coastguard Worker 
80*8d67ca89SAndroid Build Coastguard Worker       if (line[0] == '[' && line.back() == ']') {
81*8d67ca89SAndroid Build Coastguard Worker         *name = line.substr(1, line.size() - 2);
82*8d67ca89SAndroid Build Coastguard Worker         return kSection;
83*8d67ca89SAndroid Build Coastguard Worker       }
84*8d67ca89SAndroid Build Coastguard Worker 
85*8d67ca89SAndroid Build Coastguard Worker       size_t found_assign = line.find('=');
86*8d67ca89SAndroid Build Coastguard Worker       size_t found_append = line.find("+=");
87*8d67ca89SAndroid Build Coastguard Worker       if (found_assign != std::string::npos && found_append == std::string::npos) {
88*8d67ca89SAndroid Build Coastguard Worker         *name = android::base::Trim(line.substr(0, found_assign));
89*8d67ca89SAndroid Build Coastguard Worker         *value = android::base::Trim(line.substr(found_assign + 1));
90*8d67ca89SAndroid Build Coastguard Worker         return kPropertyAssign;
91*8d67ca89SAndroid Build Coastguard Worker       }
92*8d67ca89SAndroid Build Coastguard Worker 
93*8d67ca89SAndroid Build Coastguard Worker       if (found_append != std::string::npos) {
94*8d67ca89SAndroid Build Coastguard Worker         *name = android::base::Trim(line.substr(0, found_append));
95*8d67ca89SAndroid Build Coastguard Worker         *value = android::base::Trim(line.substr(found_append + 2));
96*8d67ca89SAndroid Build Coastguard Worker         return kPropertyAppend;
97*8d67ca89SAndroid Build Coastguard Worker       }
98*8d67ca89SAndroid Build Coastguard Worker 
99*8d67ca89SAndroid Build Coastguard Worker       *error_msg = std::string("invalid format: ") +
100*8d67ca89SAndroid Build Coastguard Worker                    line +
101*8d67ca89SAndroid Build Coastguard Worker                    ", expected \"name = property\", \"name += property\", or \"[section]\"";
102*8d67ca89SAndroid Build Coastguard Worker       return kError;
103*8d67ca89SAndroid Build Coastguard Worker     }
104*8d67ca89SAndroid Build Coastguard Worker 
105*8d67ca89SAndroid Build Coastguard Worker     // to avoid infinite cycles when programmer makes a mistake
106*8d67ca89SAndroid Build Coastguard Worker     CHECK(!was_end_of_file_);
107*8d67ca89SAndroid Build Coastguard Worker     was_end_of_file_ = true;
108*8d67ca89SAndroid Build Coastguard Worker     return kEndOfFile;
109*8d67ca89SAndroid Build Coastguard Worker   }
110*8d67ca89SAndroid Build Coastguard Worker 
lineno() const111*8d67ca89SAndroid Build Coastguard Worker   size_t lineno() const {
112*8d67ca89SAndroid Build Coastguard Worker     return lineno_;
113*8d67ca89SAndroid Build Coastguard Worker   }
114*8d67ca89SAndroid Build Coastguard Worker 
115*8d67ca89SAndroid Build Coastguard Worker  private:
NextLine(std::string * line)116*8d67ca89SAndroid Build Coastguard Worker   bool NextLine(std::string* line) {
117*8d67ca89SAndroid Build Coastguard Worker     if (p_ == std::string::npos) {
118*8d67ca89SAndroid Build Coastguard Worker       return false;
119*8d67ca89SAndroid Build Coastguard Worker     }
120*8d67ca89SAndroid Build Coastguard Worker 
121*8d67ca89SAndroid Build Coastguard Worker     size_t found = content_.find('\n', p_);
122*8d67ca89SAndroid Build Coastguard Worker     if (found != std::string::npos) {
123*8d67ca89SAndroid Build Coastguard Worker       *line = content_.substr(p_, found - p_);
124*8d67ca89SAndroid Build Coastguard Worker       p_ = found + 1;
125*8d67ca89SAndroid Build Coastguard Worker     } else {
126*8d67ca89SAndroid Build Coastguard Worker       *line = content_.substr(p_);
127*8d67ca89SAndroid Build Coastguard Worker       p_ = std::string::npos;
128*8d67ca89SAndroid Build Coastguard Worker     }
129*8d67ca89SAndroid Build Coastguard Worker 
130*8d67ca89SAndroid Build Coastguard Worker     lineno_++;
131*8d67ca89SAndroid Build Coastguard Worker     return true;
132*8d67ca89SAndroid Build Coastguard Worker   }
133*8d67ca89SAndroid Build Coastguard Worker 
134*8d67ca89SAndroid Build Coastguard Worker   std::string content_;
135*8d67ca89SAndroid Build Coastguard Worker   size_t p_;
136*8d67ca89SAndroid Build Coastguard Worker   size_t lineno_;
137*8d67ca89SAndroid Build Coastguard Worker   bool was_end_of_file_;
138*8d67ca89SAndroid Build Coastguard Worker 
139*8d67ca89SAndroid Build Coastguard Worker   DISALLOW_IMPLICIT_CONSTRUCTORS(ConfigParser);
140*8d67ca89SAndroid Build Coastguard Worker };
141*8d67ca89SAndroid Build Coastguard Worker 
142*8d67ca89SAndroid Build Coastguard Worker class PropertyValue {
143*8d67ca89SAndroid Build Coastguard Worker  public:
144*8d67ca89SAndroid Build Coastguard Worker   PropertyValue() = default;
145*8d67ca89SAndroid Build Coastguard Worker 
PropertyValue(std::string && value,size_t lineno)146*8d67ca89SAndroid Build Coastguard Worker   PropertyValue(std::string&& value, size_t lineno)
147*8d67ca89SAndroid Build Coastguard Worker     : value_(std::move(value)), lineno_(lineno) {}
148*8d67ca89SAndroid Build Coastguard Worker 
value() const149*8d67ca89SAndroid Build Coastguard Worker   const std::string& value() const {
150*8d67ca89SAndroid Build Coastguard Worker     return value_;
151*8d67ca89SAndroid Build Coastguard Worker   }
152*8d67ca89SAndroid Build Coastguard Worker 
append_value(std::string && value)153*8d67ca89SAndroid Build Coastguard Worker   void append_value(std::string&& value) {
154*8d67ca89SAndroid Build Coastguard Worker     value_ = value_ + value;
155*8d67ca89SAndroid Build Coastguard Worker     // lineno isn't updated as we might have cases like this:
156*8d67ca89SAndroid Build Coastguard Worker     // property.x = blah
157*8d67ca89SAndroid Build Coastguard Worker     // property.y = blah
158*8d67ca89SAndroid Build Coastguard Worker     // property.x += blah
159*8d67ca89SAndroid Build Coastguard Worker   }
160*8d67ca89SAndroid Build Coastguard Worker 
lineno() const161*8d67ca89SAndroid Build Coastguard Worker   size_t lineno() const {
162*8d67ca89SAndroid Build Coastguard Worker     return lineno_;
163*8d67ca89SAndroid Build Coastguard Worker   }
164*8d67ca89SAndroid Build Coastguard Worker 
165*8d67ca89SAndroid Build Coastguard Worker  private:
166*8d67ca89SAndroid Build Coastguard Worker   std::string value_;
167*8d67ca89SAndroid Build Coastguard Worker   size_t lineno_;
168*8d67ca89SAndroid Build Coastguard Worker };
169*8d67ca89SAndroid Build Coastguard Worker 
create_error_msg(const char * file,size_t lineno,const std::string & msg)170*8d67ca89SAndroid Build Coastguard Worker static std::string create_error_msg(const char* file,
171*8d67ca89SAndroid Build Coastguard Worker                                     size_t lineno,
172*8d67ca89SAndroid Build Coastguard Worker                                     const std::string& msg) {
173*8d67ca89SAndroid Build Coastguard Worker   char buf[1024];
174*8d67ca89SAndroid Build Coastguard Worker   async_safe_format_buffer(buf, sizeof(buf), "%s:%zu: error: %s", file, lineno, msg.c_str());
175*8d67ca89SAndroid Build Coastguard Worker 
176*8d67ca89SAndroid Build Coastguard Worker   return std::string(buf);
177*8d67ca89SAndroid Build Coastguard Worker }
178*8d67ca89SAndroid Build Coastguard Worker 
parse_config_file(const char * ld_config_file_path,const char * binary_realpath,std::unordered_map<std::string,PropertyValue> * properties,std::string * error_msg)179*8d67ca89SAndroid Build Coastguard Worker static bool parse_config_file(const char* ld_config_file_path,
180*8d67ca89SAndroid Build Coastguard Worker                               const char* binary_realpath,
181*8d67ca89SAndroid Build Coastguard Worker                               std::unordered_map<std::string, PropertyValue>* properties,
182*8d67ca89SAndroid Build Coastguard Worker                               std::string* error_msg) {
183*8d67ca89SAndroid Build Coastguard Worker   std::string content;
184*8d67ca89SAndroid Build Coastguard Worker   if (!android::base::ReadFileToString(ld_config_file_path, &content)) {
185*8d67ca89SAndroid Build Coastguard Worker     if (errno != ENOENT) {
186*8d67ca89SAndroid Build Coastguard Worker       *error_msg = std::string("error reading file \"") +
187*8d67ca89SAndroid Build Coastguard Worker                    ld_config_file_path + "\": " + strerror(errno);
188*8d67ca89SAndroid Build Coastguard Worker     }
189*8d67ca89SAndroid Build Coastguard Worker     return false;
190*8d67ca89SAndroid Build Coastguard Worker   }
191*8d67ca89SAndroid Build Coastguard Worker 
192*8d67ca89SAndroid Build Coastguard Worker   ConfigParser cp(std::move(content));
193*8d67ca89SAndroid Build Coastguard Worker 
194*8d67ca89SAndroid Build Coastguard Worker   std::string section_name;
195*8d67ca89SAndroid Build Coastguard Worker 
196*8d67ca89SAndroid Build Coastguard Worker   while (true) {
197*8d67ca89SAndroid Build Coastguard Worker     std::string name;
198*8d67ca89SAndroid Build Coastguard Worker     std::string value;
199*8d67ca89SAndroid Build Coastguard Worker     std::string error;
200*8d67ca89SAndroid Build Coastguard Worker 
201*8d67ca89SAndroid Build Coastguard Worker     int result = cp.next_token(&name, &value, &error);
202*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kError) {
203*8d67ca89SAndroid Build Coastguard Worker       DL_WARN("%s:%zd: warning: couldn't parse %s (ignoring this line)",
204*8d67ca89SAndroid Build Coastguard Worker               ld_config_file_path,
205*8d67ca89SAndroid Build Coastguard Worker               cp.lineno(),
206*8d67ca89SAndroid Build Coastguard Worker               error.c_str());
207*8d67ca89SAndroid Build Coastguard Worker       continue;
208*8d67ca89SAndroid Build Coastguard Worker     }
209*8d67ca89SAndroid Build Coastguard Worker 
210*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kSection || result == ConfigParser::kEndOfFile) {
211*8d67ca89SAndroid Build Coastguard Worker       return false;
212*8d67ca89SAndroid Build Coastguard Worker     }
213*8d67ca89SAndroid Build Coastguard Worker 
214*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kPropertyAssign) {
215*8d67ca89SAndroid Build Coastguard Worker       if (!android::base::StartsWith(name, "dir.")) {
216*8d67ca89SAndroid Build Coastguard Worker         DL_WARN("%s:%zd: warning: unexpected property name \"%s\", "
217*8d67ca89SAndroid Build Coastguard Worker                 "expected format dir.<section_name> (ignoring this line)",
218*8d67ca89SAndroid Build Coastguard Worker                 ld_config_file_path,
219*8d67ca89SAndroid Build Coastguard Worker                 cp.lineno(),
220*8d67ca89SAndroid Build Coastguard Worker                 name.c_str());
221*8d67ca89SAndroid Build Coastguard Worker         continue;
222*8d67ca89SAndroid Build Coastguard Worker       }
223*8d67ca89SAndroid Build Coastguard Worker 
224*8d67ca89SAndroid Build Coastguard Worker       // remove trailing '/'
225*8d67ca89SAndroid Build Coastguard Worker       while (!value.empty() && value.back() == '/') {
226*8d67ca89SAndroid Build Coastguard Worker         value.pop_back();
227*8d67ca89SAndroid Build Coastguard Worker       }
228*8d67ca89SAndroid Build Coastguard Worker 
229*8d67ca89SAndroid Build Coastguard Worker       if (value.empty()) {
230*8d67ca89SAndroid Build Coastguard Worker         DL_WARN("%s:%zd: warning: property value is empty (ignoring this line)",
231*8d67ca89SAndroid Build Coastguard Worker                 ld_config_file_path,
232*8d67ca89SAndroid Build Coastguard Worker                 cp.lineno());
233*8d67ca89SAndroid Build Coastguard Worker         continue;
234*8d67ca89SAndroid Build Coastguard Worker       }
235*8d67ca89SAndroid Build Coastguard Worker 
236*8d67ca89SAndroid Build Coastguard Worker       // If the path can be resolved, resolve it
237*8d67ca89SAndroid Build Coastguard Worker       char buf[PATH_MAX];
238*8d67ca89SAndroid Build Coastguard Worker       std::string resolved_path;
239*8d67ca89SAndroid Build Coastguard Worker       if (access(value.c_str(), R_OK) != 0) {
240*8d67ca89SAndroid Build Coastguard Worker         if (errno == ENOENT) {
241*8d67ca89SAndroid Build Coastguard Worker           // no need to test for non-existing path. skip.
242*8d67ca89SAndroid Build Coastguard Worker           continue;
243*8d67ca89SAndroid Build Coastguard Worker         }
244*8d67ca89SAndroid Build Coastguard Worker         // If not accessible, don't call realpath as it will just cause
245*8d67ca89SAndroid Build Coastguard Worker         // SELinux denial spam. Use the path unresolved.
246*8d67ca89SAndroid Build Coastguard Worker         resolved_path = value;
247*8d67ca89SAndroid Build Coastguard Worker       } else if (realpath(value.c_str(), buf)) {
248*8d67ca89SAndroid Build Coastguard Worker         resolved_path = buf;
249*8d67ca89SAndroid Build Coastguard Worker       } else {
250*8d67ca89SAndroid Build Coastguard Worker         // realpath is expected to fail with EPERM in some situations, so log
251*8d67ca89SAndroid Build Coastguard Worker         // the failure with INFO rather than DL_WARN. e.g. A binary in
252*8d67ca89SAndroid Build Coastguard Worker         // /data/local/tmp may attempt to stat /postinstall. See
253*8d67ca89SAndroid Build Coastguard Worker         // http://b/120996057.
254*8d67ca89SAndroid Build Coastguard Worker         LD_DEBUG(any, "%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
255*8d67ca89SAndroid Build Coastguard Worker                  ld_config_file_path, cp.lineno(), value.c_str());
256*8d67ca89SAndroid Build Coastguard Worker         resolved_path = value;
257*8d67ca89SAndroid Build Coastguard Worker       }
258*8d67ca89SAndroid Build Coastguard Worker 
259*8d67ca89SAndroid Build Coastguard Worker       if (file_is_under_dir(binary_realpath, resolved_path)) {
260*8d67ca89SAndroid Build Coastguard Worker         section_name = name.substr(4);
261*8d67ca89SAndroid Build Coastguard Worker         break;
262*8d67ca89SAndroid Build Coastguard Worker       }
263*8d67ca89SAndroid Build Coastguard Worker     }
264*8d67ca89SAndroid Build Coastguard Worker   }
265*8d67ca89SAndroid Build Coastguard Worker 
266*8d67ca89SAndroid Build Coastguard Worker   LD_DEBUG(any, "[ Using config section \"%s\" ]", section_name.c_str());
267*8d67ca89SAndroid Build Coastguard Worker 
268*8d67ca89SAndroid Build Coastguard Worker   // skip everything until we meet a correct section
269*8d67ca89SAndroid Build Coastguard Worker   while (true) {
270*8d67ca89SAndroid Build Coastguard Worker     std::string name;
271*8d67ca89SAndroid Build Coastguard Worker     std::string value;
272*8d67ca89SAndroid Build Coastguard Worker     std::string error;
273*8d67ca89SAndroid Build Coastguard Worker 
274*8d67ca89SAndroid Build Coastguard Worker     int result = cp.next_token(&name, &value, &error);
275*8d67ca89SAndroid Build Coastguard Worker 
276*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kSection && name == section_name) {
277*8d67ca89SAndroid Build Coastguard Worker       break;
278*8d67ca89SAndroid Build Coastguard Worker     }
279*8d67ca89SAndroid Build Coastguard Worker 
280*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kEndOfFile) {
281*8d67ca89SAndroid Build Coastguard Worker       *error_msg = create_error_msg(ld_config_file_path,
282*8d67ca89SAndroid Build Coastguard Worker                                     cp.lineno(),
283*8d67ca89SAndroid Build Coastguard Worker                                     std::string("section \"") + section_name + "\" not found");
284*8d67ca89SAndroid Build Coastguard Worker       return false;
285*8d67ca89SAndroid Build Coastguard Worker     }
286*8d67ca89SAndroid Build Coastguard Worker   }
287*8d67ca89SAndroid Build Coastguard Worker 
288*8d67ca89SAndroid Build Coastguard Worker   // found the section - parse it
289*8d67ca89SAndroid Build Coastguard Worker   while (true) {
290*8d67ca89SAndroid Build Coastguard Worker     std::string name;
291*8d67ca89SAndroid Build Coastguard Worker     std::string value;
292*8d67ca89SAndroid Build Coastguard Worker     std::string error;
293*8d67ca89SAndroid Build Coastguard Worker 
294*8d67ca89SAndroid Build Coastguard Worker     int result = cp.next_token(&name, &value, &error);
295*8d67ca89SAndroid Build Coastguard Worker 
296*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kEndOfFile || result == ConfigParser::kSection) {
297*8d67ca89SAndroid Build Coastguard Worker       break;
298*8d67ca89SAndroid Build Coastguard Worker     }
299*8d67ca89SAndroid Build Coastguard Worker 
300*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kPropertyAssign) {
301*8d67ca89SAndroid Build Coastguard Worker       if (properties->contains(name)) {
302*8d67ca89SAndroid Build Coastguard Worker         DL_WARN("%s:%zd: warning: redefining property \"%s\" (overriding previous value)",
303*8d67ca89SAndroid Build Coastguard Worker                 ld_config_file_path,
304*8d67ca89SAndroid Build Coastguard Worker                 cp.lineno(),
305*8d67ca89SAndroid Build Coastguard Worker                 name.c_str());
306*8d67ca89SAndroid Build Coastguard Worker       }
307*8d67ca89SAndroid Build Coastguard Worker 
308*8d67ca89SAndroid Build Coastguard Worker       (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
309*8d67ca89SAndroid Build Coastguard Worker     } else if (result == ConfigParser::kPropertyAppend) {
310*8d67ca89SAndroid Build Coastguard Worker       if (!properties->contains(name)) {
311*8d67ca89SAndroid Build Coastguard Worker         DL_WARN("%s:%zd: warning: appending to undefined property \"%s\" (treating as assignment)",
312*8d67ca89SAndroid Build Coastguard Worker                 ld_config_file_path,
313*8d67ca89SAndroid Build Coastguard Worker                 cp.lineno(),
314*8d67ca89SAndroid Build Coastguard Worker                 name.c_str());
315*8d67ca89SAndroid Build Coastguard Worker         (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
316*8d67ca89SAndroid Build Coastguard Worker       } else {
317*8d67ca89SAndroid Build Coastguard Worker         if (android::base::EndsWith(name, ".links") ||
318*8d67ca89SAndroid Build Coastguard Worker             android::base::EndsWith(name, ".namespaces")) {
319*8d67ca89SAndroid Build Coastguard Worker           value = "," + value;
320*8d67ca89SAndroid Build Coastguard Worker           (*properties)[name].append_value(std::move(value));
321*8d67ca89SAndroid Build Coastguard Worker         } else if (android::base::EndsWith(name, ".paths") ||
322*8d67ca89SAndroid Build Coastguard Worker                    android::base::EndsWith(name, ".shared_libs") ||
323*8d67ca89SAndroid Build Coastguard Worker                    android::base::EndsWith(name, ".whitelisted") ||
324*8d67ca89SAndroid Build Coastguard Worker                    android::base::EndsWith(name, ".allowed_libs")) {
325*8d67ca89SAndroid Build Coastguard Worker           value = ":" + value;
326*8d67ca89SAndroid Build Coastguard Worker           (*properties)[name].append_value(std::move(value));
327*8d67ca89SAndroid Build Coastguard Worker         } else {
328*8d67ca89SAndroid Build Coastguard Worker           DL_WARN("%s:%zd: warning: += isn't allowed for property \"%s\" (ignoring)",
329*8d67ca89SAndroid Build Coastguard Worker                   ld_config_file_path,
330*8d67ca89SAndroid Build Coastguard Worker                   cp.lineno(),
331*8d67ca89SAndroid Build Coastguard Worker                   name.c_str());
332*8d67ca89SAndroid Build Coastguard Worker         }
333*8d67ca89SAndroid Build Coastguard Worker       }
334*8d67ca89SAndroid Build Coastguard Worker     }
335*8d67ca89SAndroid Build Coastguard Worker 
336*8d67ca89SAndroid Build Coastguard Worker     if (result == ConfigParser::kError) {
337*8d67ca89SAndroid Build Coastguard Worker       DL_WARN("%s:%zd: warning: couldn't parse %s (ignoring this line)",
338*8d67ca89SAndroid Build Coastguard Worker               ld_config_file_path,
339*8d67ca89SAndroid Build Coastguard Worker               cp.lineno(),
340*8d67ca89SAndroid Build Coastguard Worker               error.c_str());
341*8d67ca89SAndroid Build Coastguard Worker       continue;
342*8d67ca89SAndroid Build Coastguard Worker     }
343*8d67ca89SAndroid Build Coastguard Worker   }
344*8d67ca89SAndroid Build Coastguard Worker 
345*8d67ca89SAndroid Build Coastguard Worker   return true;
346*8d67ca89SAndroid Build Coastguard Worker }
347*8d67ca89SAndroid Build Coastguard Worker 
348*8d67ca89SAndroid Build Coastguard Worker static Config g_config;
349*8d67ca89SAndroid Build Coastguard Worker 
350*8d67ca89SAndroid Build Coastguard Worker static constexpr const char* kDefaultConfigName = "default";
351*8d67ca89SAndroid Build Coastguard Worker static constexpr const char* kPropertyAdditionalNamespaces = "additional.namespaces";
352*8d67ca89SAndroid Build Coastguard Worker 
353*8d67ca89SAndroid Build Coastguard Worker class Properties {
354*8d67ca89SAndroid Build Coastguard Worker  public:
Properties(std::unordered_map<std::string,PropertyValue> && properties)355*8d67ca89SAndroid Build Coastguard Worker   explicit Properties(std::unordered_map<std::string, PropertyValue>&& properties)
356*8d67ca89SAndroid Build Coastguard Worker       : properties_(std::move(properties)), target_sdk_version_(__ANDROID_API__) {}
357*8d67ca89SAndroid Build Coastguard Worker 
get_strings(const std::string & name,size_t * lineno=nullptr) const358*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> get_strings(const std::string& name, size_t* lineno = nullptr) const {
359*8d67ca89SAndroid Build Coastguard Worker     auto it = find_property(name, lineno);
360*8d67ca89SAndroid Build Coastguard Worker     if (it == properties_.end()) {
361*8d67ca89SAndroid Build Coastguard Worker       // return empty vector
362*8d67ca89SAndroid Build Coastguard Worker       return std::vector<std::string>();
363*8d67ca89SAndroid Build Coastguard Worker     }
364*8d67ca89SAndroid Build Coastguard Worker 
365*8d67ca89SAndroid Build Coastguard Worker     std::vector<std::string> strings = android::base::Split(it->second.value(), ",");
366*8d67ca89SAndroid Build Coastguard Worker 
367*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < strings.size(); ++i) {
368*8d67ca89SAndroid Build Coastguard Worker       strings[i] = android::base::Trim(strings[i]);
369*8d67ca89SAndroid Build Coastguard Worker     }
370*8d67ca89SAndroid Build Coastguard Worker 
371*8d67ca89SAndroid Build Coastguard Worker     return strings;
372*8d67ca89SAndroid Build Coastguard Worker   }
373*8d67ca89SAndroid Build Coastguard Worker 
get_bool(const std::string & name,size_t * lineno=nullptr) const374*8d67ca89SAndroid Build Coastguard Worker   bool get_bool(const std::string& name, size_t* lineno = nullptr) const {
375*8d67ca89SAndroid Build Coastguard Worker     auto it = find_property(name, lineno);
376*8d67ca89SAndroid Build Coastguard Worker     if (it == properties_.end()) {
377*8d67ca89SAndroid Build Coastguard Worker       return false;
378*8d67ca89SAndroid Build Coastguard Worker     }
379*8d67ca89SAndroid Build Coastguard Worker 
380*8d67ca89SAndroid Build Coastguard Worker     return it->second.value() == "true";
381*8d67ca89SAndroid Build Coastguard Worker   }
382*8d67ca89SAndroid Build Coastguard Worker 
get_string(const std::string & name,size_t * lineno=nullptr) const383*8d67ca89SAndroid Build Coastguard Worker   std::string get_string(const std::string& name, size_t* lineno = nullptr) const {
384*8d67ca89SAndroid Build Coastguard Worker     auto it = find_property(name, lineno);
385*8d67ca89SAndroid Build Coastguard Worker     return (it == properties_.end()) ? "" : it->second.value();
386*8d67ca89SAndroid Build Coastguard Worker   }
387*8d67ca89SAndroid Build Coastguard Worker 
get_paths(const std::string & name,bool resolve,size_t * lineno=nullptr)388*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> get_paths(const std::string& name, bool resolve, size_t* lineno = nullptr) {
389*8d67ca89SAndroid Build Coastguard Worker     std::string paths_str = get_string(name, lineno);
390*8d67ca89SAndroid Build Coastguard Worker 
391*8d67ca89SAndroid Build Coastguard Worker     std::vector<std::string> paths;
392*8d67ca89SAndroid Build Coastguard Worker     split_path(paths_str.c_str(), ":", &paths);
393*8d67ca89SAndroid Build Coastguard Worker 
394*8d67ca89SAndroid Build Coastguard Worker     std::vector<std::pair<std::string, std::string>> params;
395*8d67ca89SAndroid Build Coastguard Worker     params.push_back({ "LIB", kLibPath });
396*8d67ca89SAndroid Build Coastguard Worker     if (target_sdk_version_ != 0) {
397*8d67ca89SAndroid Build Coastguard Worker       char buf[16];
398*8d67ca89SAndroid Build Coastguard Worker       async_safe_format_buffer(buf, sizeof(buf), "%d", target_sdk_version_);
399*8d67ca89SAndroid Build Coastguard Worker       params.push_back({ "SDK_VER", buf });
400*8d67ca89SAndroid Build Coastguard Worker     }
401*8d67ca89SAndroid Build Coastguard Worker 
402*8d67ca89SAndroid Build Coastguard Worker     static std::string vndk_ver = Config::get_vndk_version_string('-');
403*8d67ca89SAndroid Build Coastguard Worker     params.push_back({ "VNDK_VER", vndk_ver });
404*8d67ca89SAndroid Build Coastguard Worker     static std::string vndk_apex_ver = Config::get_vndk_version_string('v');
405*8d67ca89SAndroid Build Coastguard Worker     params.push_back({ "VNDK_APEX_VER", vndk_apex_ver });
406*8d67ca89SAndroid Build Coastguard Worker 
407*8d67ca89SAndroid Build Coastguard Worker     for (auto& path : paths) {
408*8d67ca89SAndroid Build Coastguard Worker       format_string(&path, params);
409*8d67ca89SAndroid Build Coastguard Worker     }
410*8d67ca89SAndroid Build Coastguard Worker 
411*8d67ca89SAndroid Build Coastguard Worker     if (resolve) {
412*8d67ca89SAndroid Build Coastguard Worker       std::vector<std::string> resolved_paths;
413*8d67ca89SAndroid Build Coastguard Worker       for (const auto& path : paths) {
414*8d67ca89SAndroid Build Coastguard Worker         if (path.empty()) {
415*8d67ca89SAndroid Build Coastguard Worker           continue;
416*8d67ca89SAndroid Build Coastguard Worker         }
417*8d67ca89SAndroid Build Coastguard Worker         // this is single threaded. no need to lock
418*8d67ca89SAndroid Build Coastguard Worker         auto cached = resolved_paths_.find(path);
419*8d67ca89SAndroid Build Coastguard Worker         if (cached == resolved_paths_.end()) {
420*8d67ca89SAndroid Build Coastguard Worker           resolved_paths_[path] = resolve_path(path);
421*8d67ca89SAndroid Build Coastguard Worker           cached = resolved_paths_.find(path);
422*8d67ca89SAndroid Build Coastguard Worker         }
423*8d67ca89SAndroid Build Coastguard Worker         CHECK(cached != resolved_paths_.end());
424*8d67ca89SAndroid Build Coastguard Worker         if (cached->second.empty()) {
425*8d67ca89SAndroid Build Coastguard Worker           continue;
426*8d67ca89SAndroid Build Coastguard Worker         }
427*8d67ca89SAndroid Build Coastguard Worker         resolved_paths.push_back(cached->second);
428*8d67ca89SAndroid Build Coastguard Worker       }
429*8d67ca89SAndroid Build Coastguard Worker 
430*8d67ca89SAndroid Build Coastguard Worker       return resolved_paths;
431*8d67ca89SAndroid Build Coastguard Worker     } else {
432*8d67ca89SAndroid Build Coastguard Worker       return paths;
433*8d67ca89SAndroid Build Coastguard Worker     }
434*8d67ca89SAndroid Build Coastguard Worker   }
435*8d67ca89SAndroid Build Coastguard Worker 
set_target_sdk_version(int target_sdk_version)436*8d67ca89SAndroid Build Coastguard Worker   void set_target_sdk_version(int target_sdk_version) {
437*8d67ca89SAndroid Build Coastguard Worker     target_sdk_version_ = target_sdk_version;
438*8d67ca89SAndroid Build Coastguard Worker   }
439*8d67ca89SAndroid Build Coastguard Worker 
440*8d67ca89SAndroid Build Coastguard Worker  private:
441*8d67ca89SAndroid Build Coastguard Worker   std::unordered_map<std::string, PropertyValue>::const_iterator
find_property(const std::string & name,size_t * lineno) const442*8d67ca89SAndroid Build Coastguard Worker   find_property(const std::string& name, size_t* lineno) const {
443*8d67ca89SAndroid Build Coastguard Worker     auto it = properties_.find(name);
444*8d67ca89SAndroid Build Coastguard Worker     if (it != properties_.end() && lineno != nullptr) {
445*8d67ca89SAndroid Build Coastguard Worker       *lineno = it->second.lineno();
446*8d67ca89SAndroid Build Coastguard Worker     }
447*8d67ca89SAndroid Build Coastguard Worker 
448*8d67ca89SAndroid Build Coastguard Worker     return it;
449*8d67ca89SAndroid Build Coastguard Worker   }
450*8d67ca89SAndroid Build Coastguard Worker   std::unordered_map<std::string, PropertyValue> properties_;
451*8d67ca89SAndroid Build Coastguard Worker   std::unordered_map<std::string, std::string> resolved_paths_;
452*8d67ca89SAndroid Build Coastguard Worker   int target_sdk_version_;
453*8d67ca89SAndroid Build Coastguard Worker 
454*8d67ca89SAndroid Build Coastguard Worker   DISALLOW_IMPLICIT_CONSTRUCTORS(Properties);
455*8d67ca89SAndroid Build Coastguard Worker };
456*8d67ca89SAndroid Build Coastguard Worker 
read_binary_config(const char * ld_config_file_path,const char * binary_realpath,bool is_asan,bool is_hwasan,const Config ** config,std::string * error_msg)457*8d67ca89SAndroid Build Coastguard Worker bool Config::read_binary_config(const char* ld_config_file_path,
458*8d67ca89SAndroid Build Coastguard Worker                                       const char* binary_realpath,
459*8d67ca89SAndroid Build Coastguard Worker                                       bool is_asan,
460*8d67ca89SAndroid Build Coastguard Worker                                       bool is_hwasan,
461*8d67ca89SAndroid Build Coastguard Worker                                       const Config** config,
462*8d67ca89SAndroid Build Coastguard Worker                                       std::string* error_msg) {
463*8d67ca89SAndroid Build Coastguard Worker   g_config.clear();
464*8d67ca89SAndroid Build Coastguard Worker 
465*8d67ca89SAndroid Build Coastguard Worker   std::unordered_map<std::string, PropertyValue> property_map;
466*8d67ca89SAndroid Build Coastguard Worker   if (!parse_config_file(ld_config_file_path, binary_realpath, &property_map, error_msg)) {
467*8d67ca89SAndroid Build Coastguard Worker     return false;
468*8d67ca89SAndroid Build Coastguard Worker   }
469*8d67ca89SAndroid Build Coastguard Worker 
470*8d67ca89SAndroid Build Coastguard Worker   Properties properties(std::move(property_map));
471*8d67ca89SAndroid Build Coastguard Worker 
472*8d67ca89SAndroid Build Coastguard Worker   auto failure_guard = android::base::make_scope_guard([] { g_config.clear(); });
473*8d67ca89SAndroid Build Coastguard Worker 
474*8d67ca89SAndroid Build Coastguard Worker   std::unordered_map<std::string, NamespaceConfig*> namespace_configs;
475*8d67ca89SAndroid Build Coastguard Worker 
476*8d67ca89SAndroid Build Coastguard Worker   namespace_configs[kDefaultConfigName] = g_config.create_namespace_config(kDefaultConfigName);
477*8d67ca89SAndroid Build Coastguard Worker 
478*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> additional_namespaces = properties.get_strings(kPropertyAdditionalNamespaces);
479*8d67ca89SAndroid Build Coastguard Worker   for (const auto& name : additional_namespaces) {
480*8d67ca89SAndroid Build Coastguard Worker     namespace_configs[name] = g_config.create_namespace_config(name);
481*8d67ca89SAndroid Build Coastguard Worker   }
482*8d67ca89SAndroid Build Coastguard Worker 
483*8d67ca89SAndroid Build Coastguard Worker   bool versioning_enabled = properties.get_bool("enable.target.sdk.version");
484*8d67ca89SAndroid Build Coastguard Worker   int target_sdk_version = __ANDROID_API__;
485*8d67ca89SAndroid Build Coastguard Worker   if (versioning_enabled) {
486*8d67ca89SAndroid Build Coastguard Worker     std::string version_file = dirname(binary_realpath) + "/.version";
487*8d67ca89SAndroid Build Coastguard Worker     std::string content;
488*8d67ca89SAndroid Build Coastguard Worker     if (!android::base::ReadFileToString(version_file, &content)) {
489*8d67ca89SAndroid Build Coastguard Worker       if (errno != ENOENT) {
490*8d67ca89SAndroid Build Coastguard Worker         *error_msg = std::string("error reading version file \"") +
491*8d67ca89SAndroid Build Coastguard Worker                      version_file + "\": " + strerror(errno);
492*8d67ca89SAndroid Build Coastguard Worker         return false;
493*8d67ca89SAndroid Build Coastguard Worker       }
494*8d67ca89SAndroid Build Coastguard Worker     } else {
495*8d67ca89SAndroid Build Coastguard Worker       content = android::base::Trim(content);
496*8d67ca89SAndroid Build Coastguard Worker       errno = 0;
497*8d67ca89SAndroid Build Coastguard Worker       char* end = nullptr;
498*8d67ca89SAndroid Build Coastguard Worker       const char* content_str = content.c_str();
499*8d67ca89SAndroid Build Coastguard Worker       int result = strtol(content_str, &end, 10);
500*8d67ca89SAndroid Build Coastguard Worker       if (errno == 0 && *end == '\0' && result > 0) {
501*8d67ca89SAndroid Build Coastguard Worker         target_sdk_version = result;
502*8d67ca89SAndroid Build Coastguard Worker         properties.set_target_sdk_version(target_sdk_version);
503*8d67ca89SAndroid Build Coastguard Worker       } else {
504*8d67ca89SAndroid Build Coastguard Worker         *error_msg = std::string("invalid version \"") + version_file + "\": \"" + content +"\"";
505*8d67ca89SAndroid Build Coastguard Worker         return false;
506*8d67ca89SAndroid Build Coastguard Worker       }
507*8d67ca89SAndroid Build Coastguard Worker     }
508*8d67ca89SAndroid Build Coastguard Worker   }
509*8d67ca89SAndroid Build Coastguard Worker 
510*8d67ca89SAndroid Build Coastguard Worker   g_config.set_target_sdk_version(target_sdk_version);
511*8d67ca89SAndroid Build Coastguard Worker 
512*8d67ca89SAndroid Build Coastguard Worker   for (const auto& ns_config_it : namespace_configs) {
513*8d67ca89SAndroid Build Coastguard Worker     auto& name = ns_config_it.first;
514*8d67ca89SAndroid Build Coastguard Worker     NamespaceConfig* ns_config = ns_config_it.second;
515*8d67ca89SAndroid Build Coastguard Worker 
516*8d67ca89SAndroid Build Coastguard Worker     std::string property_name_prefix = std::string("namespace.") + name;
517*8d67ca89SAndroid Build Coastguard Worker 
518*8d67ca89SAndroid Build Coastguard Worker     size_t lineno = 0;
519*8d67ca89SAndroid Build Coastguard Worker     std::vector<std::string> linked_namespaces =
520*8d67ca89SAndroid Build Coastguard Worker         properties.get_strings(property_name_prefix + ".links", &lineno);
521*8d67ca89SAndroid Build Coastguard Worker 
522*8d67ca89SAndroid Build Coastguard Worker     for (const auto& linked_ns_name : linked_namespaces) {
523*8d67ca89SAndroid Build Coastguard Worker       if (!namespace_configs.contains(linked_ns_name)) {
524*8d67ca89SAndroid Build Coastguard Worker         *error_msg = create_error_msg(ld_config_file_path,
525*8d67ca89SAndroid Build Coastguard Worker                                       lineno,
526*8d67ca89SAndroid Build Coastguard Worker                                       std::string("undefined namespace: ") + linked_ns_name);
527*8d67ca89SAndroid Build Coastguard Worker         return false;
528*8d67ca89SAndroid Build Coastguard Worker       }
529*8d67ca89SAndroid Build Coastguard Worker 
530*8d67ca89SAndroid Build Coastguard Worker       bool allow_all_shared_libs = properties.get_bool(property_name_prefix + ".link." +
531*8d67ca89SAndroid Build Coastguard Worker                                                        linked_ns_name + ".allow_all_shared_libs");
532*8d67ca89SAndroid Build Coastguard Worker 
533*8d67ca89SAndroid Build Coastguard Worker       std::string shared_libs = properties.get_string(property_name_prefix +
534*8d67ca89SAndroid Build Coastguard Worker                                                       ".link." +
535*8d67ca89SAndroid Build Coastguard Worker                                                       linked_ns_name +
536*8d67ca89SAndroid Build Coastguard Worker                                                       ".shared_libs", &lineno);
537*8d67ca89SAndroid Build Coastguard Worker 
538*8d67ca89SAndroid Build Coastguard Worker       if (!allow_all_shared_libs && shared_libs.empty()) {
539*8d67ca89SAndroid Build Coastguard Worker         *error_msg = create_error_msg(ld_config_file_path,
540*8d67ca89SAndroid Build Coastguard Worker                                       lineno,
541*8d67ca89SAndroid Build Coastguard Worker                                       std::string("list of shared_libs for ") +
542*8d67ca89SAndroid Build Coastguard Worker                                       name +
543*8d67ca89SAndroid Build Coastguard Worker                                       "->" +
544*8d67ca89SAndroid Build Coastguard Worker                                       linked_ns_name +
545*8d67ca89SAndroid Build Coastguard Worker                                       " link is not specified or is empty.");
546*8d67ca89SAndroid Build Coastguard Worker         return false;
547*8d67ca89SAndroid Build Coastguard Worker       }
548*8d67ca89SAndroid Build Coastguard Worker 
549*8d67ca89SAndroid Build Coastguard Worker       if (allow_all_shared_libs && !shared_libs.empty()) {
550*8d67ca89SAndroid Build Coastguard Worker         *error_msg = create_error_msg(ld_config_file_path, lineno,
551*8d67ca89SAndroid Build Coastguard Worker                                       std::string("both shared_libs and allow_all_shared_libs "
552*8d67ca89SAndroid Build Coastguard Worker                                                   "are set for ") +
553*8d67ca89SAndroid Build Coastguard Worker                                       name + "->" + linked_ns_name + " link.");
554*8d67ca89SAndroid Build Coastguard Worker         return false;
555*8d67ca89SAndroid Build Coastguard Worker       }
556*8d67ca89SAndroid Build Coastguard Worker 
557*8d67ca89SAndroid Build Coastguard Worker       ns_config->add_namespace_link(linked_ns_name, shared_libs, allow_all_shared_libs);
558*8d67ca89SAndroid Build Coastguard Worker     }
559*8d67ca89SAndroid Build Coastguard Worker 
560*8d67ca89SAndroid Build Coastguard Worker     ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));
561*8d67ca89SAndroid Build Coastguard Worker     ns_config->set_visible(properties.get_bool(property_name_prefix + ".visible"));
562*8d67ca89SAndroid Build Coastguard Worker 
563*8d67ca89SAndroid Build Coastguard Worker     std::string allowed_libs =
564*8d67ca89SAndroid Build Coastguard Worker         properties.get_string(property_name_prefix + ".whitelisted", &lineno);
565*8d67ca89SAndroid Build Coastguard Worker     const std::string libs = properties.get_string(property_name_prefix + ".allowed_libs", &lineno);
566*8d67ca89SAndroid Build Coastguard Worker     if (!allowed_libs.empty() && !libs.empty()) {
567*8d67ca89SAndroid Build Coastguard Worker       allowed_libs += ":";
568*8d67ca89SAndroid Build Coastguard Worker     }
569*8d67ca89SAndroid Build Coastguard Worker     allowed_libs += libs;
570*8d67ca89SAndroid Build Coastguard Worker     if (!allowed_libs.empty()) {
571*8d67ca89SAndroid Build Coastguard Worker       ns_config->set_allowed_libs(android::base::Split(allowed_libs, ":"));
572*8d67ca89SAndroid Build Coastguard Worker     }
573*8d67ca89SAndroid Build Coastguard Worker 
574*8d67ca89SAndroid Build Coastguard Worker     // these are affected by is_asan flag
575*8d67ca89SAndroid Build Coastguard Worker     if (is_asan) {
576*8d67ca89SAndroid Build Coastguard Worker       property_name_prefix += ".asan";
577*8d67ca89SAndroid Build Coastguard Worker     } else if (is_hwasan) {
578*8d67ca89SAndroid Build Coastguard Worker       property_name_prefix += ".hwasan";
579*8d67ca89SAndroid Build Coastguard Worker     }
580*8d67ca89SAndroid Build Coastguard Worker 
581*8d67ca89SAndroid Build Coastguard Worker     // search paths are resolved (canonicalized). This is required mainly for
582*8d67ca89SAndroid Build Coastguard Worker     // the case when /vendor is a symlink to /system/vendor, which is true for
583*8d67ca89SAndroid Build Coastguard Worker     // non Treble-ized legacy devices.
584*8d67ca89SAndroid Build Coastguard Worker     ns_config->set_search_paths(properties.get_paths(property_name_prefix + ".search.paths", true));
585*8d67ca89SAndroid Build Coastguard Worker 
586*8d67ca89SAndroid Build Coastguard Worker     // However, for permitted paths, we are not required to resolve the paths
587*8d67ca89SAndroid Build Coastguard Worker     // since they are only set for isolated namespaces, which implies the device
588*8d67ca89SAndroid Build Coastguard Worker     // is Treble-ized (= /vendor is not a symlink to /system/vendor).
589*8d67ca89SAndroid Build Coastguard Worker     // In fact, the resolving is causing an unexpected side effect of selinux
590*8d67ca89SAndroid Build Coastguard Worker     // denials on some executables which are not allowed to access some of the
591*8d67ca89SAndroid Build Coastguard Worker     // permitted paths.
592*8d67ca89SAndroid Build Coastguard Worker     ns_config->set_permitted_paths(properties.get_paths(property_name_prefix + ".permitted.paths", false));
593*8d67ca89SAndroid Build Coastguard Worker   }
594*8d67ca89SAndroid Build Coastguard Worker 
595*8d67ca89SAndroid Build Coastguard Worker   failure_guard.Disable();
596*8d67ca89SAndroid Build Coastguard Worker   *config = &g_config;
597*8d67ca89SAndroid Build Coastguard Worker   return true;
598*8d67ca89SAndroid Build Coastguard Worker }
599*8d67ca89SAndroid Build Coastguard Worker 
get_vndk_version_string(const char delimiter)600*8d67ca89SAndroid Build Coastguard Worker std::string Config::get_vndk_version_string(const char delimiter) {
601*8d67ca89SAndroid Build Coastguard Worker   std::string version = android::base::GetProperty("ro.vndk.version", "");
602*8d67ca89SAndroid Build Coastguard Worker   if (version != "" && version != "current") {
603*8d67ca89SAndroid Build Coastguard Worker     //add the delimiter char in front of the string and return it.
604*8d67ca89SAndroid Build Coastguard Worker     return version.insert(0, 1, delimiter);
605*8d67ca89SAndroid Build Coastguard Worker   }
606*8d67ca89SAndroid Build Coastguard Worker   return "";
607*8d67ca89SAndroid Build Coastguard Worker }
608*8d67ca89SAndroid Build Coastguard Worker 
create_namespace_config(const std::string & name)609*8d67ca89SAndroid Build Coastguard Worker NamespaceConfig* Config::create_namespace_config(const std::string& name) {
610*8d67ca89SAndroid Build Coastguard Worker   namespace_configs_.push_back(std::unique_ptr<NamespaceConfig>(new NamespaceConfig(name)));
611*8d67ca89SAndroid Build Coastguard Worker   NamespaceConfig* ns_config_ptr = namespace_configs_.back().get();
612*8d67ca89SAndroid Build Coastguard Worker   namespace_configs_map_[name] = ns_config_ptr;
613*8d67ca89SAndroid Build Coastguard Worker   return ns_config_ptr;
614*8d67ca89SAndroid Build Coastguard Worker }
615*8d67ca89SAndroid Build Coastguard Worker 
clear()616*8d67ca89SAndroid Build Coastguard Worker void Config::clear() {
617*8d67ca89SAndroid Build Coastguard Worker   namespace_configs_.clear();
618*8d67ca89SAndroid Build Coastguard Worker   namespace_configs_map_.clear();
619*8d67ca89SAndroid Build Coastguard Worker }
620