Skip to content

Commit

Permalink
linker: Add support for "whitelisted" property in linker config files
Browse files Browse the repository at this point in the history
In order to enable no-vendor-variant VNDK, we need a way to restrict a
namespace to only a list of whitelisted libraries.  We add a new
"whitelisted" property for this.  If the property is not set, all
libraries in the search paths are available in a namespace.  If the
property is set, only the libraries named are available.

Bug: 119423884
Test: Boot with no-vendor-variant VNDK enabled using the new property.
Change-Id: Id808c1733c8e2c2c3462b04c72461f9698403571
  • Loading branch information
Vic Yang committed Mar 20, 2019
1 parent ebdf4c1 commit 2d020e4
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 2 deletions.
3 changes: 3 additions & 0 deletions linker/ld.config.format.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,8 @@ namespace.ns1.asan.permitted.paths = /data/vendor/${LIB}
# and links it to default namespace
namespace.ns.links = default
namespace.ns.link.default.shared_libs = libc.so:libdl.so:libm.so:libstdc++.so
# This defines what libraries are allowed to be loaded from ns1
namespace.ns1.whitelisted = libsomething.so
```

1 change: 1 addition & 0 deletions linker/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4156,6 +4156,7 @@ std::vector<android_namespace_t*> init_default_namespaces(const char* executable
ns->set_isolated(ns_config->isolated());
ns->set_default_library_paths(ns_config->search_paths());
ns->set_permitted_paths(ns_config->permitted_paths());
ns->set_whitelisted_libs(ns_config->whitelisted_libs());

namespaces[ns_config->name()] = ns;
if (ns_config->visible()) {
Expand Down
6 changes: 6 additions & 0 deletions linker/linker_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,12 @@ bool Config::read_binary_config(const char* ld_config_file_path,
ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));
ns_config->set_visible(properties.get_bool(property_name_prefix + ".visible"));

std::string whitelisted =
properties.get_string(property_name_prefix + ".whitelisted", &lineno);
if (!whitelisted.empty()) {
ns_config->set_whitelisted_libs(android::base::Split(whitelisted, ":"));
}

// these are affected by is_asan flag
if (is_asan) {
property_name_prefix += ".asan";
Expand Down
9 changes: 9 additions & 0 deletions linker/linker_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ class NamespaceConfig {
return permitted_paths_;
}

const std::vector<std::string>& whitelisted_libs() const {
return whitelisted_libs_;
}

const std::vector<NamespaceLinkConfig>& links() const {
return namespace_links_;
}
Expand All @@ -116,12 +120,17 @@ class NamespaceConfig {
void set_permitted_paths(std::vector<std::string>&& permitted_paths) {
permitted_paths_ = permitted_paths;
}

void set_whitelisted_libs(std::vector<std::string>&& whitelisted_libs) {
whitelisted_libs_ = whitelisted_libs;
}
private:
const std::string name_;
bool isolated_;
bool visible_;
std::vector<std::string> search_paths_;
std::vector<std::string> permitted_paths_;
std::vector<std::string> whitelisted_libs_;
std::vector<NamespaceLinkConfig> namespace_links_;

DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceConfig);
Expand Down
20 changes: 18 additions & 2 deletions linker/linker_config_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static const char* config_str =
"enable.target.sdk.version = true\n"
"additional.namespaces=system\n"
"additional.namespaces+=vndk\n"
"additional.namespaces+=vndk_in_system\n"
"namespace.default.isolated = true\n"
"namespace.default.search.paths = /vendor/${LIB}\n"
"namespace.default.permitted.paths = /vendor/${LIB}\n"
Expand All @@ -82,6 +83,12 @@ static const char* config_str =
"namespace.vndk.asan.search.paths += /system/${LIB}/vndk\n"
"namespace.vndk.links = default\n"
"namespace.vndk.link.default.allow_all_shared_libs = true\n"
"namespace.vndk.link.vndk_in_system.allow_all_shared_libs = true\n"
"namespace.vndk_in_system.isolated = true\n"
"namespace.vndk_in_system.visible = true\n"
"namespace.vndk_in_system.search.paths = /system/${LIB}\n"
"namespace.vndk_in_system.permitted.paths = /system/${LIB}\n"
"namespace.vndk_in_system.whitelisted = libz.so:libyuv.so:libtinyxml2.so\n"
"\n";

static bool write_version(const std::string& path, uint32_t version) {
Expand Down Expand Up @@ -165,20 +172,24 @@ static void run_linker_config_smoke_test(bool is_asan) {
ASSERT_FALSE(default_ns_links[1].allow_all_shared_libs());

auto& ns_configs = config->namespace_configs();
ASSERT_EQ(3U, ns_configs.size());
ASSERT_EQ(4U, ns_configs.size());

// find second namespace
const NamespaceConfig* ns_system = nullptr;
const NamespaceConfig* ns_vndk = nullptr;
const NamespaceConfig* ns_vndk_in_system = nullptr;
for (auto& ns : ns_configs) {
std::string ns_name = ns->name();
ASSERT_TRUE(ns_name == "system" || ns_name == "default" || ns_name == "vndk")
ASSERT_TRUE(ns_name == "system" || ns_name == "default" ||
ns_name == "vndk" || ns_name == "vndk_in_system")
<< "unexpected ns name: " << ns->name();

if (ns_name == "system") {
ns_system = ns.get();
} else if (ns_name == "vndk") {
ns_vndk = ns.get();
} else if (ns_name == "vndk_in_system") {
ns_vndk_in_system = ns.get();
}
}

Expand All @@ -199,6 +210,11 @@ static void run_linker_config_smoke_test(bool is_asan) {
ASSERT_EQ(1U, ns_vndk_links.size());
ASSERT_EQ("default", ns_vndk_links[0].ns_name());
ASSERT_TRUE(ns_vndk_links[0].allow_all_shared_libs());

ASSERT_TRUE(ns_vndk_in_system != nullptr) << "vndk_in_system namespace was not found";
ASSERT_EQ(
std::vector<std::string>({"libz.so", "libyuv.so", "libtinyxml2.so"}),
ns_vndk_in_system->whitelisted_libs());
}

TEST(linker_config, smoke) {
Expand Down
8 changes: 8 additions & 0 deletions linker/linker_namespaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ bool android_namespace_t::is_accessible(const std::string& file) {
return true;
}

if (!whitelisted_libs_.empty()) {
const char *lib_name = basename(file.c_str());
if (std::find(whitelisted_libs_.begin(), whitelisted_libs_.end(),
lib_name) == whitelisted_libs_.end()) {
return false;
}
}

for (const auto& dir : ld_library_paths_) {
if (file_is_in_dir(file, dir)) {
return true;
Expand Down
11 changes: 11 additions & 0 deletions linker/linker_namespaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ struct android_namespace_t {
permitted_paths_ = permitted_paths;
}

const std::vector<std::string>& get_whitelisted_libs() const {
return whitelisted_libs_;
}
void set_whitelisted_libs(std::vector<std::string>&& whitelisted_libs) {
whitelisted_libs_ = whitelisted_libs;
}
void set_whitelisted_libs(const std::vector<std::string>& whitelisted_libs) {
whitelisted_libs_ = whitelisted_libs;
}

const std::vector<android_namespace_link_t>& linked_namespaces() const {
return linked_namespaces_;
}
Expand Down Expand Up @@ -157,6 +167,7 @@ struct android_namespace_t {
std::vector<std::string> ld_library_paths_;
std::vector<std::string> default_library_paths_;
std::vector<std::string> permitted_paths_;
std::vector<std::string> whitelisted_libs_;
// Loader looks into linked namespace if it was not able
// to find a library in this namespace. Note that library
// lookup in linked namespaces are limited by the list of
Expand Down

0 comments on commit 2d020e4

Please sign in to comment.