1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <string>
18 #include <vector>
19
20 #include <android-base/file.h>
21 #include <apex_manifest.pb.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include <linker_config.pb.h>
25
26 #include "apex_testbase.h"
27 #include "linkerconfig/apex.h"
28 #include "linkerconfig/basecontext.h"
29 #include "linkerconfig/configwriter.h"
30 #include "linkerconfig/namespace.h"
31 #include "linkerconfig/section.h"
32
33 using ::android::base::WriteStringToFile;
34 using ::android::linkerconfig::modules::ApexInfo;
35 using ::android::linkerconfig::modules::BaseContext;
36 using ::android::linkerconfig::modules::ConfigWriter;
37 using ::android::linkerconfig::modules::InitializeWithApex;
38 using ::android::linkerconfig::modules::Namespace;
39 using ::android::linkerconfig::modules::ScanActiveApexes;
40 using ::android::linkerconfig::modules::Section;
41 using ::apex::proto::ApexManifest;
42 using ::testing::Contains;
43
TEST(apex_namespace,build_namespace)44 TEST(apex_namespace, build_namespace) {
45 Namespace ns("foo");
46 InitializeWithApex(ns,
47 ApexInfo("com.android.foo",
48 "/apex/com.android.foo",
49 /*provide_libs=*/{},
50 /*require_libs=*/{},
51 /*jni_libs=*/{},
52 /*permitted_paths=*/{},
53 /*has_bin=*/false,
54 /*has_lib=*/true,
55 /*visible=*/false,
56 /*has_shared_lib=*/false));
57
58 ConfigWriter writer;
59 ns.WriteConfig(writer);
60 ASSERT_EQ(
61 "namespace.foo.isolated = false\n"
62 "namespace.foo.search.paths = /apex/com.android.foo/${LIB}\n"
63 "namespace.foo.permitted.paths = /apex/com.android.foo/${LIB}\n"
64 "namespace.foo.permitted.paths += /system/${LIB}\n"
65 "namespace.foo.asan.search.paths = /apex/com.android.foo/${LIB}\n"
66 "namespace.foo.asan.permitted.paths = /apex/com.android.foo/${LIB}\n"
67 "namespace.foo.asan.permitted.paths += /data/asan/system/${LIB}\n"
68 "namespace.foo.asan.permitted.paths += /system/${LIB}\n",
69 writer.ToString());
70 }
71
TEST(apex_namespace,resolve_between_apex_namespaces)72 TEST(apex_namespace, resolve_between_apex_namespaces) {
73 BaseContext ctx;
74 Namespace foo("foo"), bar("bar");
75 InitializeWithApex(foo,
76 ApexInfo("com.android.foo",
77 "/apex/com.android.foo",
78 /*provide_libs=*/{"foo.so"},
79 /*require_libs=*/{"bar.so"},
80 /*jni_libs=*/{},
81 /*permitted_paths=*/{},
82 /*has_bin=*/false,
83 /*has_lib=*/true,
84 /*visible=*/false,
85 /*has_shared_lib=*/false));
86 InitializeWithApex(bar,
87 ApexInfo("com.android.bar",
88 "/apex/com.android.bar",
89 /*provide_libs=*/{"bar.so"},
90 /*require_libs=*/{},
91 /*jni_libs=*/{},
92 /*permitted_paths=*/{},
93 /*has_bin=*/false,
94 /*has_lib=*/true,
95 /*visible=*/false,
96 /*has_shared_lib=*/false));
97
98 std::vector<Namespace> namespaces;
99 namespaces.push_back(std::move(foo));
100 namespaces.push_back(std::move(bar));
101 Section section("section", std::move(namespaces));
102
103 auto result = section.Resolve(ctx);
104 ASSERT_RESULT_OK(result);
105
106 // See if two namespaces are linked correctly
107 ASSERT_THAT(section.GetNamespace("foo")->GetLink("bar").GetSharedLibs(),
108 Contains("bar.so"));
109 }
110
TEST(apex_namespace,extra_permitted_paths)111 TEST(apex_namespace, extra_permitted_paths) {
112 Namespace ns("foo");
113 InitializeWithApex(ns,
114 ApexInfo("com.android.foo",
115 "/apex/com.android.foo",
116 /*provide_libs=*/{},
117 /*require_libs=*/{},
118 /*jni_libs=*/{},
119 /*permitted_paths=*/{"/a", "/b/c"},
120 /*has_bin=*/false,
121 /*has_lib=*/true,
122 /*visible=*/false,
123 /*has_shared_lib=*/false));
124
125 ConfigWriter writer;
126 ns.WriteConfig(writer);
127 ASSERT_EQ(
128 "namespace.foo.isolated = false\n"
129 "namespace.foo.search.paths = /apex/com.android.foo/${LIB}\n"
130 "namespace.foo.permitted.paths = /apex/com.android.foo/${LIB}\n"
131 "namespace.foo.permitted.paths += /system/${LIB}\n"
132 "namespace.foo.permitted.paths += /a\n"
133 "namespace.foo.permitted.paths += /b/c\n"
134 "namespace.foo.asan.search.paths = /apex/com.android.foo/${LIB}\n"
135 "namespace.foo.asan.permitted.paths = /apex/com.android.foo/${LIB}\n"
136 "namespace.foo.asan.permitted.paths += /data/asan/system/${LIB}\n"
137 "namespace.foo.asan.permitted.paths += /system/${LIB}\n"
138 "namespace.foo.asan.permitted.paths += /data/asan/a\n"
139 "namespace.foo.asan.permitted.paths += /a\n"
140 "namespace.foo.asan.permitted.paths += /data/asan/b/c\n"
141 "namespace.foo.asan.permitted.paths += /b/c\n",
142 writer.ToString());
143 }
144
TEST_F(ApexTest,scan_apex_dir)145 TEST_F(ApexTest, scan_apex_dir) {
146 PrepareApex("foo", {}, {"bar.so"}, {});
147 WriteFile("/apex/foo/bin/foo", "");
148 PrepareApex("bar", {"bar.so"}, {}, {});
149 WriteFile("/apex/bar/lib64/bar.so", "");
150 PrepareApex("baz", {}, {}, {"baz.so"});
151 WriteFile("/apex/baz/lib64/baz.so", "");
152 CreateApexInfoList();
153 CreatePublicLibrariesTxt();
154
155 auto apexes = ScanActiveApexes(root);
156 ASSERT_TRUE(apexes.ok()) << "Failed to scan active APEXes : "
157 << apexes.error();
158 ASSERT_EQ(3U, apexes->size());
159
160 ASSERT_THAT((*apexes)["foo"].require_libs, Contains("bar.so"));
161 ASSERT_TRUE((*apexes)["foo"].has_bin);
162 ASSERT_FALSE((*apexes)["foo"].has_lib);
163
164 ASSERT_THAT((*apexes)["bar"].provide_libs, Contains("bar.so"));
165 ASSERT_FALSE((*apexes)["bar"].has_bin);
166 ASSERT_TRUE((*apexes)["bar"].has_lib);
167
168 ASSERT_THAT((*apexes)["baz"].jni_libs, Contains("baz.so"));
169 ASSERT_FALSE((*apexes)["baz"].has_bin);
170 ASSERT_TRUE((*apexes)["baz"].has_lib);
171 }
172
TEST_F(ApexTest,validate_path)173 TEST_F(ApexTest, validate_path) {
174 PrepareApex("foo", {}, {}, {});
175 CreateApexInfoList();
176 CreatePublicLibrariesTxt();
177
178 ::android::linkerconfig::proto::LinkerConfig two_slash;
179 two_slash.add_permittedpaths("/two//slash");
180
181 WriteFile("/apex/foo/etc/linker.config.pb", two_slash.SerializeAsString());
182 auto apexes = ScanActiveApexes(root);
183 ASSERT_FALSE(apexes.ok()) << "Two slash is not allowed from path string";
184
185 ::android::linkerconfig::proto::LinkerConfig invalid_char;
186 invalid_char.add_permittedpaths("/path/with*/invalid/char");
187
188 WriteFile("/apex/foo/etc/linker.config.pb", invalid_char.SerializeAsString());
189 apexes = ScanActiveApexes(root);
190 ASSERT_FALSE(apexes.ok()) << "* is invalid char for path.";
191
192 ::android::linkerconfig::proto::LinkerConfig end_with_lib;
193 end_with_lib.add_permittedpaths("/somewhere/${LIB}");
194
195 WriteFile("/apex/foo/etc/linker.config.pb", end_with_lib.SerializeAsString());
196 apexes = ScanActiveApexes(root);
197 ASSERT_TRUE(apexes.ok()) << "Path ends with ${LIB} should be accepted. : "
198 << apexes.error();
199
200 ::android::linkerconfig::proto::LinkerConfig lib_plus_char;
201 lib_plus_char.add_permittedpaths("/somewhere/${LIB}x/hw");
202
203 WriteFile("/apex/foo/etc/linker.config.pb", lib_plus_char.SerializeAsString());
204 apexes = ScanActiveApexes(root);
205 ASSERT_FALSE(apexes.ok())
206 << "There should be no extra char after ${LIB} in path.";
207
208 ::android::linkerconfig::proto::LinkerConfig char_plus_lib;
209 char_plus_lib.add_permittedpaths("/somewhere/x${LIB}/hw");
210
211 WriteFile("/apex/foo/etc/linker.config.pb", char_plus_lib.SerializeAsString());
212 apexes = ScanActiveApexes(root);
213 ASSERT_FALSE(apexes.ok())
214 << "There should be no extra char before ${LIB} in path.";
215
216 ::android::linkerconfig::proto::LinkerConfig lib_and_lib64;
217 lib_and_lib64.add_permittedpaths("/somewhere/${LIB}/hw");
218
219 WriteFile("/apex/foo/etc/linker.config.pb", lib_and_lib64.SerializeAsString());
220 apexes = ScanActiveApexes(root);
221 ASSERT_TRUE(apexes.ok()) << "Valid path with ${LIB} should be accepted. : "
222 << apexes.error();
223 }