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 <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