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