Add permitted_when_isolated_path to linker namespaces

The permitted_when_isolated_path is a way to white-list
directories not present in search-path. It is ignored for
not isolated namespaces.

Bug: http://b/25853516
Bug: http://b/22548808
Change-Id: Ib1538037268eea69323ea49968a34a4a1d1938a5
This commit is contained in:
Dimitry Ivanov
2015-12-08 10:47:13 -08:00
parent df196131f3
commit 284ae3559e
9 changed files with 70 additions and 25 deletions

View File

@@ -193,11 +193,12 @@ bool android_init_namespaces(const char* public_ns_sonames,
}
android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
const char* default_library_path, bool is_isolated) {
const char* default_library_path, bool is_isolated,
const char* permitted_when_isolated_path) {
ScopedPthreadMutexLocker locker(&g_dl_mutex);
android_namespace_t* result = create_namespace(name, ld_library_path,
default_library_path, is_isolated);
android_namespace_t* result = create_namespace(name, ld_library_path, default_library_path,
is_isolated, permitted_when_isolated_path);
if (result == nullptr) {
__bionic_format_dlerror("android_create_namespace failed", linker_get_error_buffer());

View File

@@ -94,6 +94,10 @@ struct android_namespace_t {
default_library_paths_ = library_paths;
}
void set_permitted_paths(std::vector<std::string>&& permitted_paths) {
permitted_paths_ = permitted_paths;
}
soinfo::soinfo_list_t& soinfo_list() { return soinfo_list_; }
// For isolated namespaces - checks if the file is on the search path;
@@ -105,6 +109,7 @@ struct android_namespace_t {
bool is_isolated_;
std::vector<std::string> ld_library_paths_;
std::vector<std::string> default_library_paths_;
std::vector<std::string> permitted_paths_;
soinfo::soinfo_list_t soinfo_list_;
DISALLOW_COPY_AND_ASSIGN(android_namespace_t);
@@ -316,6 +321,12 @@ bool android_namespace_t::is_accessible(const std::string& file) {
}
}
for (const auto& dir : permitted_paths_) {
if (file_is_under_dir(file, dir)) {
return true;
}
}
return false;
}
@@ -2285,7 +2296,7 @@ bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_
// create anonymous namespace
android_namespace_t* anon_ns =
create_namespace("(anonymous)", nullptr, anon_ns_library_path, false);
create_namespace("(anonymous)", nullptr, anon_ns_library_path, false, nullptr);
if (anon_ns == nullptr) {
g_public_namespace_initialized = false;
@@ -2299,7 +2310,8 @@ bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_
android_namespace_t* create_namespace(const char* name,
const char* ld_library_path,
const char* default_library_path,
bool is_isolated) {
bool is_isolated,
const char* permitted_when_isolated_path) {
if (!g_public_namespace_initialized) {
DL_ERR("cannot create namespace: public namespace is not initialized.");
return nullptr;
@@ -2308,15 +2320,18 @@ android_namespace_t* create_namespace(const char* name,
ProtectedDataGuard guard;
std::vector<std::string> ld_library_paths;
std::vector<std::string> default_library_paths;
std::vector<std::string> permitted_paths;
parse_path(ld_library_path, ":", &ld_library_paths);
parse_path(default_library_path, ":", &default_library_paths);
parse_path(permitted_when_isolated_path, ":", &permitted_paths);
android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
ns->set_name(name);
ns->set_isolated(is_isolated);
ns->set_ld_library_paths(std::move(ld_library_paths));
ns->set_default_library_paths(std::move(default_library_paths));
ns->set_permitted_paths(std::move(permitted_paths));
// TODO(dimtiry): Should this be global group of caller's namespace?
auto global_group = make_global_group(&g_default_namespace);

View File

@@ -446,6 +446,7 @@ uint32_t get_application_target_sdk_version();
bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path);
android_namespace_t* create_namespace(const char* name, const char* ld_library_path,
const char* default_library_path, bool is_isolated);
const char* default_library_path, bool is_isolated,
const char* permitted_when_isolated_path);
#endif

View File

@@ -66,9 +66,18 @@ bool file_is_in_dir(const std::string& file, const std::string& dir) {
const char* haystack = file.c_str();
size_t needle_len = strlen(needle);
return (strncmp(haystack, needle, needle_len) == 0 &&
haystack[needle_len] == '/' &&
strchr(haystack + needle_len + 1, '/') == nullptr);
return strncmp(haystack, needle, needle_len) == 0 &&
haystack[needle_len] == '/' &&
strchr(haystack + needle_len + 1, '/') == nullptr;
}
bool file_is_under_dir(const std::string& file, const std::string& dir) {
const char* needle = dir.c_str();
const char* haystack = file.c_str();
size_t needle_len = strlen(needle);
return strncmp(haystack, needle, needle_len) == 0 &&
haystack[needle_len] == '/';
}
const char* const kZipFileSeparator = "!/";

View File

@@ -22,6 +22,7 @@ extern const char* const kZipFileSeparator;
bool normalize_path(const char* path, std::string* normalized_path);
bool file_is_in_dir(const std::string& file, const std::string& dir);
bool file_is_under_dir(const std::string& file, const std::string& dir);
bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path);
off64_t page_start(off64_t offset);

View File

@@ -54,6 +54,18 @@ TEST(linker_utils, file_is_in_dir_smoke) {
ASSERT_FALSE(file_is_in_dir("/file", "/"));
}
TEST(linker_utils, file_is_under_dir_smoke) {
ASSERT_TRUE(file_is_under_dir("/foo/bar/file", "/foo/bar"));
ASSERT_TRUE(file_is_under_dir("/foo/bar/file", "/foo"));
ASSERT_FALSE(file_is_under_dir("/foo/bar/file", "/bar/foo"));
ASSERT_TRUE(file_is_under_dir("/file", ""));
ASSERT_TRUE(file_is_under_dir("/foo/bar/file", ""));
ASSERT_FALSE(file_is_under_dir("/file", "/"));
ASSERT_FALSE(file_is_under_dir("/foo/bar/file", "/"));
}
TEST(linker_utils, parse_zip_path_smoke) {
std::string zip_path;
std::string entry_path;