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 /*contributions=*/{},
54 /*has_bin=*/false,
55 /*has_lib=*/true,
56 /*visible=*/false,
57 /*has_shared_lib=*/false));
58
59 ConfigWriter writer;
60 ns.WriteConfig(writer);
61 ASSERT_EQ(
62 "namespace.foo.isolated = false\n"
63 "namespace.foo.search.paths = /apex/com.android.foo/${LIB}\n"
64 "namespace.foo.permitted.paths = /apex/com.android.foo/${LIB}\n"
65 "namespace.foo.permitted.paths += /system/${LIB}\n"
66 "namespace.foo.asan.search.paths = /apex/com.android.foo/${LIB}\n"
67 "namespace.foo.asan.permitted.paths = /apex/com.android.foo/${LIB}\n"
68 "namespace.foo.asan.permitted.paths += /data/asan/system/${LIB}\n"
69 "namespace.foo.asan.permitted.paths += /system/${LIB}\n",
70 writer.ToString());
71 }
72
TEST(apex_namespace,resolve_between_apex_namespaces)73 TEST(apex_namespace, resolve_between_apex_namespaces) {
74 BaseContext ctx;
75 Namespace foo("foo"), bar("bar");
76 InitializeWithApex(foo,
77 ApexInfo("com.android.foo",
78 "/apex/com.android.foo",
79 /*provide_libs=*/{"foo.so"},
80 /*require_libs=*/{"bar.so"},
81 /*jni_libs=*/{},
82 /*permitted_paths=*/{},
83 /*contributions=*/{},
84 /*has_bin=*/false,
85 /*has_lib=*/true,
86 /*visible=*/false,
87 /*has_shared_lib=*/false));
88 InitializeWithApex(bar,
89 ApexInfo("com.android.bar",
90 "/apex/com.android.bar",
91 /*provide_libs=*/{"bar.so"},
92 /*require_libs=*/{},
93 /*jni_libs=*/{},
94 /*permitted_paths=*/{},
95 /*contributions=*/{},
96 /*has_bin=*/false,
97 /*has_lib=*/true,
98 /*visible=*/false,
99 /*has_shared_lib=*/false));
100
101 std::vector<Namespace> namespaces;
102 namespaces.push_back(std::move(foo));
103 namespaces.push_back(std::move(bar));
104 Section section("section", std::move(namespaces));
105
106 auto result = section.Resolve(ctx);
107 ASSERT_RESULT_OK(result);
108
109 // See if two namespaces are linked correctly
110 ASSERT_THAT(section.GetNamespace("foo")->GetLink("bar").GetSharedLibs(),
111 Contains("bar.so"));
112 }
113
TEST(apex_namespace,extra_permitted_paths)114 TEST(apex_namespace, extra_permitted_paths) {
115 Namespace ns("foo");
116 InitializeWithApex(ns,
117 ApexInfo("com.android.foo",
118 "/apex/com.android.foo",
119 /*provide_libs=*/{},
120 /*require_libs=*/{},
121 /*jni_libs=*/{},
122 /*permitted_paths=*/{"/a", "/b/c"},
123 /*contributions=*/{},
124 /*has_bin=*/false,
125 /*has_lib=*/true,
126 /*visible=*/false,
127 /*has_shared_lib=*/false));
128
129 ConfigWriter writer;
130 ns.WriteConfig(writer);
131 ASSERT_EQ(
132 "namespace.foo.isolated = false\n"
133 "namespace.foo.search.paths = /apex/com.android.foo/${LIB}\n"
134 "namespace.foo.permitted.paths = /apex/com.android.foo/${LIB}\n"
135 "namespace.foo.permitted.paths += /system/${LIB}\n"
136 "namespace.foo.permitted.paths += /a\n"
137 "namespace.foo.permitted.paths += /b/c\n"
138 "namespace.foo.asan.search.paths = /apex/com.android.foo/${LIB}\n"
139 "namespace.foo.asan.permitted.paths = /apex/com.android.foo/${LIB}\n"
140 "namespace.foo.asan.permitted.paths += /data/asan/system/${LIB}\n"
141 "namespace.foo.asan.permitted.paths += /system/${LIB}\n"
142 "namespace.foo.asan.permitted.paths += /data/asan/a\n"
143 "namespace.foo.asan.permitted.paths += /a\n"
144 "namespace.foo.asan.permitted.paths += /data/asan/b/c\n"
145 "namespace.foo.asan.permitted.paths += /b/c\n",
146 writer.ToString());
147 }
148
TEST_F(ApexTest,scan_apex_dir)149 TEST_F(ApexTest, scan_apex_dir) {
150 PrepareApex("foo", {}, {"bar.so"}, {});
151 WriteFile("/apex/foo/bin/foo", "");
152 PrepareApex("bar", {"bar.so"}, {}, {});
153 WriteFile("/apex/bar/lib64/bar.so", "");
154 PrepareApex("baz", {}, {}, {"baz.so"});
155 WriteFile("/apex/baz/lib64/baz.so", "");
156 CreateApexInfoList();
157 CreatePublicLibrariesTxt();
158
159 auto apexes = ScanActiveApexes(root);
160 ASSERT_TRUE(apexes.ok()) << "Failed to scan active APEXes : "
161 << apexes.error();
162 ASSERT_EQ(3U, apexes->size());
163
164 ASSERT_THAT((*apexes)["foo"].require_libs, Contains("bar.so"));
165 ASSERT_TRUE((*apexes)["foo"].has_bin);
166 ASSERT_FALSE((*apexes)["foo"].has_lib);
167
168 ASSERT_THAT((*apexes)["bar"].provide_libs, Contains("bar.so"));
169 ASSERT_FALSE((*apexes)["bar"].has_bin);
170 ASSERT_TRUE((*apexes)["bar"].has_lib);
171
172 ASSERT_THAT((*apexes)["baz"].jni_libs, Contains("baz.so"));
173 ASSERT_FALSE((*apexes)["baz"].has_bin);
174 ASSERT_TRUE((*apexes)["baz"].has_lib);
175 }
176
TEST_F(ApexTest,validate_path)177 TEST_F(ApexTest, validate_path) {
178 PrepareApex("foo", {}, {}, {});
179 CreateApexInfoList();
180 CreatePublicLibrariesTxt();
181
182 ::android::linkerconfig::proto::LinkerConfig two_slash;
183 two_slash.add_permittedpaths("/two//slash");
184
185 WriteFile("/apex/foo/etc/linker.config.pb", two_slash.SerializeAsString());
186 auto apexes = ScanActiveApexes(root);
187 ASSERT_FALSE(apexes.ok()) << "Two slash is not allowed from path string";
188
189 ::android::linkerconfig::proto::LinkerConfig invalid_char;
190 invalid_char.add_permittedpaths("/path/with*/invalid/char");
191
192 WriteFile("/apex/foo/etc/linker.config.pb", invalid_char.SerializeAsString());
193 apexes = ScanActiveApexes(root);
194 ASSERT_FALSE(apexes.ok()) << "* is invalid char for path.";
195
196 ::android::linkerconfig::proto::LinkerConfig end_with_lib;
197 end_with_lib.add_permittedpaths("/somewhere/${LIB}");
198
199 WriteFile("/apex/foo/etc/linker.config.pb", end_with_lib.SerializeAsString());
200 apexes = ScanActiveApexes(root);
201 ASSERT_TRUE(apexes.ok()) << "Path ends with ${LIB} should be accepted. : "
202 << apexes.error();
203
204 ::android::linkerconfig::proto::LinkerConfig lib_plus_char;
205 lib_plus_char.add_permittedpaths("/somewhere/${LIB}x/hw");
206
207 WriteFile("/apex/foo/etc/linker.config.pb", lib_plus_char.SerializeAsString());
208 apexes = ScanActiveApexes(root);
209 ASSERT_FALSE(apexes.ok())
210 << "There should be no extra char after ${LIB} in path.";
211
212 ::android::linkerconfig::proto::LinkerConfig char_plus_lib;
213 char_plus_lib.add_permittedpaths("/somewhere/x${LIB}/hw");
214
215 WriteFile("/apex/foo/etc/linker.config.pb", char_plus_lib.SerializeAsString());
216 apexes = ScanActiveApexes(root);
217 ASSERT_FALSE(apexes.ok())
218 << "There should be no extra char before ${LIB} in path.";
219
220 ::android::linkerconfig::proto::LinkerConfig lib_and_lib64;
221 lib_and_lib64.add_permittedpaths("/somewhere/${LIB}/hw");
222
223 WriteFile("/apex/foo/etc/linker.config.pb", lib_and_lib64.SerializeAsString());
224 apexes = ScanActiveApexes(root);
225 ASSERT_TRUE(apexes.ok()) << "Valid path with ${LIB} should be accepted. : "
226 << apexes.error();
227 }