blob: 6cbc111e462b48adc46d89a7de9228b299c48814 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "linkerconfig/namespace.h"
#include <android-base/strings.h>
#include "linkerconfig/apex.h"
#include "linkerconfig/log.h"
using android::base::Result;
namespace {
constexpr const char* kDataAsanPath = "/data/asan";
Result<void> VerifyIfApexNamespaceContainsAllSharedLink(
const android::linkerconfig::modules::Namespace& ns) {
auto apex_name = ns.GetApexSource();
// If namespace is not from APEX there is no need to check this.
if (apex_name == "") {
return {};
}
const auto& links = ns.Links();
for (const auto& link : links) {
if (link.IsAllSharedLibsAllowed()) {
return Errorf(
"APEX namespace {} is not allowed to have link with all shared libs "
"allowed.",
ns.GetName());
}
}
return {};
}
} // namespace
namespace android {
namespace linkerconfig {
namespace modules {
void InitializeWithApex(Namespace& ns, const ApexInfo& apex_info) {
ns.AddSearchPath(apex_info.path + "/${LIB}");
if (apex_info.InVendor()) {
ns.AddSearchPath(apex_info.path + "/${LIB}/hw");
ns.AddSearchPath(apex_info.path + "/${LIB}/egl");
}
ns.AddPermittedPath(apex_info.path + "/${LIB}");
ns.AddPermittedPath("/system/${LIB}");
for (const auto& permitted_path : apex_info.permitted_paths) {
ns.AddPermittedPath(permitted_path);
}
if (apex_info.has_shared_lib) {
ns.AddPermittedPath("/apex");
}
ns.AddProvides(apex_info.provide_libs);
ns.AddRequires(apex_info.require_libs);
ns.SetApexSource(apex_info.name);
}
Link& Namespace::GetLink(const std::string& target_namespace) {
for (auto& link : links_) {
if (link.To() == target_namespace) {
return link;
}
}
return links_.emplace_back(name_, target_namespace);
}
void Namespace::WriteConfig(ConfigWriter& writer) {
auto verify_result = VerifyContents();
if (!verify_result.ok()) {
LOG(ERROR) << "Namespace " << name_
<< " is not valid : " << verify_result.error();
return;
}
const auto prefix = "namespace." + name_ + ".";
writer.WriteLine(prefix + "isolated = " + (is_isolated_ ? "true" : "false"));
if (is_visible_) {
writer.WriteLine(prefix + "visible = true");
}
writer.WriteVars(prefix + "search.paths", search_paths_);
writer.WriteVars(prefix + "permitted.paths", permitted_paths_);
writer.WriteVars(prefix + "asan.search.paths", asan_search_paths_);
writer.WriteVars(prefix + "asan.permitted.paths", asan_permitted_paths_);
writer.WriteVars(prefix + "allowed_libs", allowed_libs_);
std::vector<std::string> link_list;
link_list.reserve(links_.size());
for (const auto& link : links_) {
if (link.Empty()) continue;
link_list.push_back(link.To());
}
if (!link_list.empty()) {
writer.WriteLine(prefix + "links = " + android::base::Join(link_list, ","));
for (const auto& link : links_) {
if (link.Empty()) continue;
link.WriteConfig(writer);
}
}
}
void Namespace::AddSearchPath(const std::string& path) {
search_paths_.push_back(path);
if (RequiresAsanPath(path)) {
asan_search_paths_.push_back(CreateAsanPath(path));
}
asan_search_paths_.push_back(path);
}
void Namespace::AddPermittedPath(const std::string& path) {
permitted_paths_.push_back(path);
if (RequiresAsanPath(path)) {
asan_permitted_paths_.push_back(CreateAsanPath(path));
}
asan_permitted_paths_.push_back(path);
}
void Namespace::AddAllowedLib(const std::string& path) {
allowed_libs_.push_back(path);
}
std::string Namespace::GetName() const {
return name_;
}
bool Namespace::RequiresAsanPath(const std::string& path) {
return !android::base::StartsWith(path, "/apex");
}
const std::string Namespace::CreateAsanPath(const std::string& path) {
return kDataAsanPath + path;
}
Result<void> Namespace::VerifyContents() {
auto apex_with_all_shared_link =
VerifyIfApexNamespaceContainsAllSharedLink(*this);
if (!apex_with_all_shared_link.ok()) {
return apex_with_all_shared_link.error();
}
return {};
}
} // namespace modules
} // namespace linkerconfig
} // namespace android