You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
8.7 KiB

/*
* 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 <string>
#include <vector>
#include <android-base/file.h>
#include <apex_manifest.pb.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <linker_config.pb.h>
#include "apex_testbase.h"
#include "linkerconfig/apex.h"
#include "linkerconfig/basecontext.h"
#include "linkerconfig/configwriter.h"
#include "linkerconfig/namespace.h"
#include "linkerconfig/section.h"
using ::android::base::WriteStringToFile;
using ::android::linkerconfig::modules::ApexInfo;
using ::android::linkerconfig::modules::BaseContext;
using ::android::linkerconfig::modules::ConfigWriter;
using ::android::linkerconfig::modules::InitializeWithApex;
using ::android::linkerconfig::modules::Namespace;
using ::android::linkerconfig::modules::ScanActiveApexes;
using ::android::linkerconfig::modules::Section;
using ::apex::proto::ApexManifest;
using ::testing::Contains;
TEST(apex_namespace, build_namespace) {
Namespace ns("foo");
InitializeWithApex(ns,
ApexInfo("com.android.foo",
"/apex/com.android.foo",
/*provide_libs=*/{},
/*require_libs=*/{},
/*jni_libs=*/{},
/*permitted_paths=*/{},
/*has_bin=*/false,
/*has_lib=*/true,
/*visible=*/false,
/*has_shared_lib=*/false));
ConfigWriter writer;
ns.WriteConfig(writer);
ASSERT_EQ(
"namespace.foo.isolated = false\n"
"namespace.foo.search.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.permitted.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.permitted.paths += /system/${LIB}\n"
"namespace.foo.asan.search.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.asan.permitted.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.asan.permitted.paths += /data/asan/system/${LIB}\n"
"namespace.foo.asan.permitted.paths += /system/${LIB}\n",
writer.ToString());
}
TEST(apex_namespace, resolve_between_apex_namespaces) {
BaseContext ctx;
Namespace foo("foo"), bar("bar");
InitializeWithApex(foo,
ApexInfo("com.android.foo",
"/apex/com.android.foo",
/*provide_libs=*/{"foo.so"},
/*require_libs=*/{"bar.so"},
/*jni_libs=*/{},
/*permitted_paths=*/{},
/*has_bin=*/false,
/*has_lib=*/true,
/*visible=*/false,
/*has_shared_lib=*/false));
InitializeWithApex(bar,
ApexInfo("com.android.bar",
"/apex/com.android.bar",
/*provide_libs=*/{"bar.so"},
/*require_libs=*/{},
/*jni_libs=*/{},
/*permitted_paths=*/{},
/*has_bin=*/false,
/*has_lib=*/true,
/*visible=*/false,
/*has_shared_lib=*/false));
std::vector<Namespace> namespaces;
namespaces.push_back(std::move(foo));
namespaces.push_back(std::move(bar));
Section section("section", std::move(namespaces));
auto result = section.Resolve(ctx);
ASSERT_RESULT_OK(result);
// See if two namespaces are linked correctly
ASSERT_THAT(section.GetNamespace("foo")->GetLink("bar").GetSharedLibs(),
Contains("bar.so"));
}
TEST(apex_namespace, extra_permitted_paths) {
Namespace ns("foo");
InitializeWithApex(ns,
ApexInfo("com.android.foo",
"/apex/com.android.foo",
/*provide_libs=*/{},
/*require_libs=*/{},
/*jni_libs=*/{},
/*permitted_paths=*/{"/a", "/b/c"},
/*has_bin=*/false,
/*has_lib=*/true,
/*visible=*/false,
/*has_shared_lib=*/false));
ConfigWriter writer;
ns.WriteConfig(writer);
ASSERT_EQ(
"namespace.foo.isolated = false\n"
"namespace.foo.search.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.permitted.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.permitted.paths += /system/${LIB}\n"
"namespace.foo.permitted.paths += /a\n"
"namespace.foo.permitted.paths += /b/c\n"
"namespace.foo.asan.search.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.asan.permitted.paths = /apex/com.android.foo/${LIB}\n"
"namespace.foo.asan.permitted.paths += /data/asan/system/${LIB}\n"
"namespace.foo.asan.permitted.paths += /system/${LIB}\n"
"namespace.foo.asan.permitted.paths += /data/asan/a\n"
"namespace.foo.asan.permitted.paths += /a\n"
"namespace.foo.asan.permitted.paths += /data/asan/b/c\n"
"namespace.foo.asan.permitted.paths += /b/c\n",
writer.ToString());
}
TEST_F(ApexTest, scan_apex_dir) {
PrepareApex("foo", {}, {"bar.so"}, {});
WriteFile("/apex/foo/bin/foo", "");
PrepareApex("bar", {"bar.so"}, {}, {});
WriteFile("/apex/bar/lib64/bar.so", "");
PrepareApex("baz", {}, {}, {"baz.so"});
WriteFile("/apex/baz/lib64/baz.so", "");
CreateApexInfoList();
CreatePublicLibrariesTxt();
auto apexes = ScanActiveApexes(root);
ASSERT_TRUE(apexes.ok()) << "Failed to scan active APEXes : "
<< apexes.error();
ASSERT_EQ(3U, apexes->size());
ASSERT_THAT((*apexes)["foo"].require_libs, Contains("bar.so"));
ASSERT_TRUE((*apexes)["foo"].has_bin);
ASSERT_FALSE((*apexes)["foo"].has_lib);
ASSERT_THAT((*apexes)["bar"].provide_libs, Contains("bar.so"));
ASSERT_FALSE((*apexes)["bar"].has_bin);
ASSERT_TRUE((*apexes)["bar"].has_lib);
ASSERT_THAT((*apexes)["baz"].jni_libs, Contains("baz.so"));
ASSERT_FALSE((*apexes)["baz"].has_bin);
ASSERT_TRUE((*apexes)["baz"].has_lib);
}
TEST_F(ApexTest, validate_path) {
PrepareApex("foo", {}, {}, {});
CreateApexInfoList();
CreatePublicLibrariesTxt();
::android::linkerconfig::proto::LinkerConfig two_slash;
two_slash.add_permittedpaths("/two//slash");
WriteFile("/apex/foo/etc/linker.config.pb", two_slash.SerializeAsString());
auto apexes = ScanActiveApexes(root);
ASSERT_FALSE(apexes.ok()) << "Two slash is not allowed from path string";
::android::linkerconfig::proto::LinkerConfig invalid_char;
invalid_char.add_permittedpaths("/path/with*/invalid/char");
WriteFile("/apex/foo/etc/linker.config.pb", invalid_char.SerializeAsString());
apexes = ScanActiveApexes(root);
ASSERT_FALSE(apexes.ok()) << "* is invalid char for path.";
::android::linkerconfig::proto::LinkerConfig end_with_lib;
end_with_lib.add_permittedpaths("/somewhere/${LIB}");
WriteFile("/apex/foo/etc/linker.config.pb", end_with_lib.SerializeAsString());
apexes = ScanActiveApexes(root);
ASSERT_TRUE(apexes.ok()) << "Path ends with ${LIB} should be accepted. : "
<< apexes.error();
::android::linkerconfig::proto::LinkerConfig lib_plus_char;
lib_plus_char.add_permittedpaths("/somewhere/${LIB}x/hw");
WriteFile("/apex/foo/etc/linker.config.pb", lib_plus_char.SerializeAsString());
apexes = ScanActiveApexes(root);
ASSERT_FALSE(apexes.ok())
<< "There should be no extra char after ${LIB} in path.";
::android::linkerconfig::proto::LinkerConfig char_plus_lib;
char_plus_lib.add_permittedpaths("/somewhere/x${LIB}/hw");
WriteFile("/apex/foo/etc/linker.config.pb", char_plus_lib.SerializeAsString());
apexes = ScanActiveApexes(root);
ASSERT_FALSE(apexes.ok())
<< "There should be no extra char before ${LIB} in path.";
::android::linkerconfig::proto::LinkerConfig lib_and_lib64;
lib_and_lib64.add_permittedpaths("/somewhere/${LIB}/hw");
WriteFile("/apex/foo/etc/linker.config.pb", lib_and_lib64.SerializeAsString());
apexes = ScanActiveApexes(root);
ASSERT_TRUE(apexes.ok()) << "Valid path with ${LIB} should be accepted. : "
<< apexes.error();
}