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