blob: bbfbad9aa8ca2358a3497a9804e726c320379c74 [file] [log] [blame]
Mårten Kongstad02751232018-04-27 13:16:32 +02001/*
2 * Copyright (C) 2018 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 <cstdio> // fclose
18
19#include <fstream>
20#include <memory>
21#include <sstream>
22#include <string>
23#include <vector>
24
25#include "gmock/gmock.h"
26#include "gtest/gtest.h"
27
28#include "android-base/macros.h"
29#include "androidfw/ApkAssets.h"
30
31#include "idmap2/BinaryStreamVisitor.h"
32#include "idmap2/CommandLineOptions.h"
33#include "idmap2/Idmap.h"
34
35#include "TestHelpers.h"
36
37using ::testing::IsNull;
38using ::testing::NotNull;
39
Mårten Kongstad0eba72a2018-11-29 08:23:14 +010040namespace android::idmap2 {
Mårten Kongstad02751232018-04-27 13:16:32 +020041
42TEST(IdmapTests, TestCanonicalIdmapPathFor) {
43 ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
44 "/foo/vendor@overlay@bar.apk@idmap");
45}
46
47TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
48 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
49 std::istringstream stream(raw);
50 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
51 ASSERT_THAT(header, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010052 ASSERT_EQ(header->GetMagic(), 0x504d4449U);
53 ASSERT_EQ(header->GetVersion(), 0x01U);
54 ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
55 ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
Mårten Kongstad02751232018-04-27 13:16:32 +020056 ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
57 ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
58}
59
60TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
61 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
62 // overwrite the target path string, including the terminating null, with '.'
63 for (size_t i = 0x10; i < 0x110; i++) {
64 raw[i] = '.';
65 }
66 std::istringstream stream(raw);
67 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
68 ASSERT_THAT(header, IsNull());
69}
70
71TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
72 const size_t offset = 0x210;
73 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
74 idmap_raw_data_len - offset);
75 std::istringstream stream(raw);
76
77 std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
78 ASSERT_THAT(header, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010079 ASSERT_EQ(header->GetTargetPackageId(), 0x7fU);
80 ASSERT_EQ(header->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +020081}
82
83TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
84 const size_t offset = 0x214;
85 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
86 idmap_raw_data_len - offset);
87 std::istringstream stream(raw);
88
89 std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
90 ASSERT_THAT(data, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010091 ASSERT_EQ(data->GetTargetTypeId(), 0x02U);
92 ASSERT_EQ(data->GetOverlayTypeId(), 0x02U);
93 ASSERT_EQ(data->GetEntryCount(), 1U);
94 ASSERT_EQ(data->GetEntryOffset(), 0U);
95 ASSERT_EQ(data->GetEntry(0), 0U);
Mårten Kongstad02751232018-04-27 13:16:32 +020096}
97
98TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
99 const size_t offset = 0x210;
100 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
101 idmap_raw_data_len - offset);
102 std::istringstream stream(raw);
103
104 std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
105 ASSERT_THAT(data, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100106 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
107 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200108 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100109 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200110
Mårten Kongstadb8779022018-11-29 09:53:17 +0100111 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
112 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
113 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
114 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
115 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200116
Mårten Kongstadb8779022018-11-29 09:53:17 +0100117 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
118 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
119 ASSERT_EQ(types[1]->GetEntryCount(), 3U);
120 ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
121 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200122 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100123 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200124}
125
126TEST(IdmapTests, CreateIdmapFromBinaryStream) {
127 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
128 std::istringstream stream(raw);
129
130 std::stringstream error;
131 std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error);
132 ASSERT_THAT(idmap, NotNull());
133
134 ASSERT_THAT(idmap->GetHeader(), NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100135 ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
136 ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
137 ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
138 ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200139 ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
140 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
141
142 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100143 ASSERT_EQ(dataBlocks.size(), 1U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200144
145 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
Mårten Kongstadb8779022018-11-29 09:53:17 +0100146 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
147 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200148 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100149 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200150
Mårten Kongstadb8779022018-11-29 09:53:17 +0100151 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
152 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
153 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
154 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
155 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200156
Mårten Kongstadb8779022018-11-29 09:53:17 +0100157 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
158 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
159 ASSERT_EQ(types[1]->GetEntryCount(), 3U);
160 ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
161 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200162 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100163 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200164}
165
166TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
167 std::string raw(reinterpret_cast<const char*>(idmap_raw_data),
168 10); // data too small
169 std::istringstream stream(raw);
170
171 std::stringstream error;
172 std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error);
173 ASSERT_THAT(idmap, IsNull());
174}
175
176TEST(IdmapTests, CreateIdmapFromApkAssets) {
177 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
178 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
179 ASSERT_THAT(target_apk, NotNull());
180
181 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
182 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
183 ASSERT_THAT(overlay_apk, NotNull());
184
185 std::stringstream error;
186 std::unique_ptr<const Idmap> idmap =
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800187 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
188 PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
Mårten Kongstad02751232018-04-27 13:16:32 +0200189 ASSERT_THAT(idmap, NotNull());
190
191 ASSERT_THAT(idmap->GetHeader(), NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100192 ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
193 ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800194 ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xd513ca1b);
195 ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x8635c2ed);
Mårten Kongstad02751232018-04-27 13:16:32 +0200196 ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
197 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
198 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
199
200 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100201 ASSERT_EQ(dataBlocks.size(), 1U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200202
203 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
204
Mårten Kongstadb8779022018-11-29 09:53:17 +0100205 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
206 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200207
208 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100209 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200210
Mårten Kongstadb8779022018-11-29 09:53:17 +0100211 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
212 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
213 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
214 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
215 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200216
Mårten Kongstadb8779022018-11-29 09:53:17 +0100217 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
218 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
219 ASSERT_EQ(types[1]->GetEntryCount(), 4U);
Winsonb4100202019-02-06 12:05:32 -0800220 ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100221 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200222 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100223 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
224 ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200225}
226
Ryan Mitchell19823452019-01-29 12:01:24 -0800227// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
228TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800229 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
230 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
231 ASSERT_THAT(target_apk, NotNull());
232
233 const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
234 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
235 ASSERT_THAT(overlay_apk, NotNull());
236
237 std::stringstream error;
238 std::unique_ptr<const Idmap> idmap =
239 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
240 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
241 /* enforce_overlayable */ true, error);
242 ASSERT_THAT(idmap, NotNull());
243
244 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
245 ASSERT_EQ(dataBlocks.size(), 1U);
246
247 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
248
249 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
250 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
251
252 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
253 ASSERT_EQ(types.size(), 1U);
254
255 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
256 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800257 ASSERT_EQ(types[0]->GetEntryCount(), 4U);
Ryan Mitchella3628462019-01-14 12:19:40 -0800258 ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100259 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public
260 ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
261 ASSERT_EQ(types[0]->GetEntry(2), 0x0001U); // string/policy_system
262 ASSERT_EQ(types[0]->GetEntry(3), 0x0002U); // string/policy_system_vendor
Winsonb4100202019-02-06 12:05:32 -0800263}
264
265TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
266 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
267 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
268 ASSERT_THAT(target_apk, NotNull());
269
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100270 const std::string overlay_apk_path(GetTestDataPath() +
271 "/signature-overlay/signature-overlay.apk");
Winsonb4100202019-02-06 12:05:32 -0800272 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
273 ASSERT_THAT(overlay_apk, NotNull());
274
275 uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE;
276
277 std::stringstream error;
278 std::unique_ptr<const Idmap> idmap =
279 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
280 policy_flags, /* enforce_overlayable */ true, error);
281 ASSERT_THAT(idmap, NotNull());
282
283 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
284 ASSERT_EQ(dataBlocks.size(), 1U);
285
286 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
287
288 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
289 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
290
291 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
292 ASSERT_EQ(types.size(), 1U);
293
294 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
295 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
296 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
297 ASSERT_EQ(types[0]->GetEntryOffset(), 7U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100298 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature
Winsonb4100202019-02-06 12:05:32 -0800299}
300
301TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
302 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
303 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
304 ASSERT_THAT(target_apk, NotNull());
305
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100306 const std::string overlay_apk_path(GetTestDataPath() +
307 "/signature-overlay/signature-overlay.apk");
Winsonb4100202019-02-06 12:05:32 -0800308 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
309 ASSERT_THAT(overlay_apk, NotNull());
310
311 uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC;
312
313 std::stringstream error;
314 std::unique_ptr<const Idmap> idmap =
315 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
316 policy_flags, /* enforce_overlayable */ true, error);
317 ASSERT_THAT(idmap, NotNull());
318
319 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
320 ASSERT_EQ(dataBlocks.size(), 1U);
321
322 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
323
324 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
325 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);
326
327 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100328 ASSERT_EQ(types.size(), 0U); // can't overlay, so contains nothing
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800329}
330
Ryan Mitchell19823452019-01-29 12:01:24 -0800331// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
332TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800333 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
334 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
335 ASSERT_THAT(target_apk, NotNull());
336
337 const std::string overlay_apk_path(GetTestDataPath() +
338 "/system-overlay-invalid/system-overlay-invalid.apk");
339 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
340 ASSERT_THAT(overlay_apk, NotNull());
341
342 std::stringstream error;
343 std::unique_ptr<const Idmap> idmap =
344 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
345 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
346 /* enforce_overlayable */ true, error);
347 ASSERT_THAT(idmap, NotNull());
348
349 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
350 ASSERT_EQ(dataBlocks.size(), 1U);
351
352 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
353
354 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
355 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
356
357 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
358 ASSERT_EQ(types.size(), 1U);
359
360 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
361 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800362 ASSERT_EQ(types[0]->GetEntryCount(), 4U);
Ryan Mitchell19823452019-01-29 12:01:24 -0800363 ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100364 ASSERT_EQ(types[0]->GetEntry(0), 0x0003U); // string/policy_public
365 ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
366 ASSERT_EQ(types[0]->GetEntry(2), 0x0005U); // string/policy_system
367 ASSERT_EQ(types[0]->GetEntry(3), 0x0006U); // string/policy_system_vendor
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800368}
369
Ryan Mitchell19823452019-01-29 12:01:24 -0800370// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
371TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800372 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
373 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
374 ASSERT_THAT(target_apk, NotNull());
375
376 const std::string overlay_apk_path(GetTestDataPath() +
377 "/system-overlay-invalid/system-overlay-invalid.apk");
378 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
379 ASSERT_THAT(overlay_apk, NotNull());
380
381 std::stringstream error;
382 std::unique_ptr<const Idmap> idmap =
383 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
384 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
385 /* enforce_overlayable */ false, error);
386 ASSERT_THAT(idmap, NotNull());
387
388 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
389 ASSERT_EQ(dataBlocks.size(), 1U);
390
391 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
392
393 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
394 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
395
396 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
397 ASSERT_EQ(types.size(), 1U);
398
399 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
400 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800401 ASSERT_EQ(types[0]->GetEntryCount(), 7U);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800402 ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
403 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
Ryan Mitchella3628462019-01-14 12:19:40 -0800404 ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
405 ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
Winsonb4100202019-02-06 12:05:32 -0800406 ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_signature
407 ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_public
408 ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
409 ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800410}
411
Ryan Mitchell19823452019-01-29 12:01:24 -0800412// The resources of APKs that do not include an overlayable declaration should not restrict what
413// resources can be overlaid.
414TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
415 const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
416 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
417 ASSERT_THAT(target_apk, NotNull());
418
419 const std::string overlay_apk_path(GetTestDataPath() +
420 "/system-overlay-invalid/system-overlay-invalid.apk");
421 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
422 ASSERT_THAT(overlay_apk, NotNull());
423
424 std::stringstream error;
425 std::unique_ptr<const Idmap> idmap =
426 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
427 PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
428 ASSERT_THAT(idmap, NotNull());
429
430 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
431 ASSERT_EQ(dataBlocks.size(), 1U);
432
433 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
434
435 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
436 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
437
438 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
439 ASSERT_EQ(types.size(), 1U);
440
441 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
442 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800443 ASSERT_EQ(types[0]->GetEntryCount(), 7U);
Ryan Mitchell19823452019-01-29 12:01:24 -0800444 ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
445 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
446 ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
447 ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
448 ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public
Winsonb4100202019-02-06 12:05:32 -0800449 ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/string/policy_signature
450 ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
451 ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
Ryan Mitchell19823452019-01-29 12:01:24 -0800452}
453
454// The resources of APKs that do not include an overlayable declaration should not restrict what
455// resources can be overlaid.
456TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
457 const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
458 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
459 ASSERT_THAT(target_apk, NotNull());
460
461 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay-no-name.apk");
462 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
463 ASSERT_THAT(overlay_apk, NotNull());
464
465 std::stringstream error;
466 std::unique_ptr<const Idmap> idmap =
467 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
468 PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
469 ASSERT_THAT(idmap, NotNull());
470
471 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
472 ASSERT_EQ(dataBlocks.size(), 1U);
473
474 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
475
476 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
477 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
478
479 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
480 ASSERT_EQ(types.size(), 2U);
481
482 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
483 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
484 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
485 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
486 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
487
488 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
489 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
490 ASSERT_EQ(types[1]->GetEntryCount(), 4U);
Winsonb4100202019-02-06 12:05:32 -0800491 ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
Ryan Mitchell19823452019-01-29 12:01:24 -0800492 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
493 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
494 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
495 ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
496}
497
Mårten Kongstad02751232018-04-27 13:16:32 +0200498TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
499 std::string target_apk_path(GetTestDataPath());
500 for (int i = 0; i < 32; i++) {
501 target_apk_path += "/target/../";
502 }
503 target_apk_path += "/target/target.apk";
504 ASSERT_GT(target_apk_path.size(), kIdmapStringLength);
505 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
506 ASSERT_THAT(target_apk, NotNull());
507
508 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
509 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
510 ASSERT_THAT(overlay_apk, NotNull());
511
512 std::stringstream error;
513 std::unique_ptr<const Idmap> idmap =
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800514 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
515 PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
Mårten Kongstad02751232018-04-27 13:16:32 +0200516 ASSERT_THAT(idmap, IsNull());
517}
518
519TEST(IdmapTests, IdmapHeaderIsUpToDate) {
520 fclose(stderr); // silence expected warnings from libandroidfw
521
522 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
523 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
524 ASSERT_THAT(target_apk, NotNull());
525
526 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
527 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
528 ASSERT_THAT(overlay_apk, NotNull());
529
530 std::stringstream error;
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800531 std::unique_ptr<const Idmap> idmap = Idmap::FromApkAssets(
532 target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
533 /* enforce_overlayable */ true, error);
Mårten Kongstad02751232018-04-27 13:16:32 +0200534 ASSERT_THAT(idmap, NotNull());
535
536 std::stringstream stream;
537 BinaryStreamVisitor visitor(stream);
538 idmap->accept(&visitor);
539
540 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
541 ASSERT_THAT(header, NotNull());
542 ASSERT_TRUE(header->IsUpToDate(error)) << error.str();
543
544 // magic: bytes (0x0, 0x03)
545 std::string bad_magic_string(stream.str());
546 bad_magic_string[0x0] = '.';
547 bad_magic_string[0x1] = '.';
548 bad_magic_string[0x2] = '.';
549 bad_magic_string[0x3] = '.';
550 std::stringstream bad_magic_stream(bad_magic_string);
551 std::unique_ptr<const IdmapHeader> bad_magic_header =
552 IdmapHeader::FromBinaryStream(bad_magic_stream);
553 ASSERT_THAT(bad_magic_header, NotNull());
554 ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
555 ASSERT_FALSE(bad_magic_header->IsUpToDate(error));
556
557 // version: bytes (0x4, 0x07)
558 std::string bad_version_string(stream.str());
559 bad_version_string[0x4] = '.';
560 bad_version_string[0x5] = '.';
561 bad_version_string[0x6] = '.';
562 bad_version_string[0x7] = '.';
563 std::stringstream bad_version_stream(bad_version_string);
564 std::unique_ptr<const IdmapHeader> bad_version_header =
565 IdmapHeader::FromBinaryStream(bad_version_stream);
566 ASSERT_THAT(bad_version_header, NotNull());
567 ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
568 ASSERT_FALSE(bad_version_header->IsUpToDate(error));
569
570 // target crc: bytes (0x8, 0xb)
571 std::string bad_target_crc_string(stream.str());
572 bad_target_crc_string[0x8] = '.';
573 bad_target_crc_string[0x9] = '.';
574 bad_target_crc_string[0xa] = '.';
575 bad_target_crc_string[0xb] = '.';
576 std::stringstream bad_target_crc_stream(bad_target_crc_string);
577 std::unique_ptr<const IdmapHeader> bad_target_crc_header =
578 IdmapHeader::FromBinaryStream(bad_target_crc_stream);
579 ASSERT_THAT(bad_target_crc_header, NotNull());
580 ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
581 ASSERT_FALSE(bad_target_crc_header->IsUpToDate(error));
582
583 // overlay crc: bytes (0xc, 0xf)
584 std::string bad_overlay_crc_string(stream.str());
585 bad_overlay_crc_string[0xc] = '.';
586 bad_overlay_crc_string[0xd] = '.';
587 bad_overlay_crc_string[0xe] = '.';
588 bad_overlay_crc_string[0xf] = '.';
589 std::stringstream bad_overlay_crc_stream(bad_overlay_crc_string);
590 std::unique_ptr<const IdmapHeader> bad_overlay_crc_header =
591 IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
592 ASSERT_THAT(bad_overlay_crc_header, NotNull());
593 ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
594 ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(error));
595
596 // target path: bytes (0x10, 0x10f)
597 std::string bad_target_path_string(stream.str());
598 bad_target_path_string[0x10] = '\0';
599 std::stringstream bad_target_path_stream(bad_target_path_string);
600 std::unique_ptr<const IdmapHeader> bad_target_path_header =
601 IdmapHeader::FromBinaryStream(bad_target_path_stream);
602 ASSERT_THAT(bad_target_path_header, NotNull());
603 ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
604 ASSERT_FALSE(bad_target_path_header->IsUpToDate(error));
605
606 // overlay path: bytes (0x110, 0x20f)
607 std::string bad_overlay_path_string(stream.str());
608 bad_overlay_path_string[0x110] = '\0';
609 std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
610 std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
611 IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
612 ASSERT_THAT(bad_overlay_path_header, NotNull());
613 ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
614 ASSERT_FALSE(bad_overlay_path_header->IsUpToDate(error));
615}
616
617class TestVisitor : public Visitor {
618 public:
619 explicit TestVisitor(std::ostream& stream) : stream_(stream) {
620 }
621
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100622 void visit(const Idmap& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200623 stream_ << "TestVisitor::visit(Idmap)" << std::endl;
624 }
625
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100626 void visit(const IdmapHeader& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200627 stream_ << "TestVisitor::visit(IdmapHeader)" << std::endl;
628 }
629
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100630 void visit(const IdmapData& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200631 stream_ << "TestVisitor::visit(IdmapData)" << std::endl;
632 }
633
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100634 void visit(const IdmapData::Header& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200635 stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
636 }
637
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100638 void visit(const IdmapData::TypeEntry& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200639 stream_ << "TestVisitor::visit(IdmapData::TypeEntry)" << std::endl;
640 }
641
642 private:
643 std::ostream& stream_;
644};
645
646TEST(IdmapTests, TestVisitor) {
647 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
648 std::istringstream stream(raw);
649
650 std::stringstream error;
651 std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error);
652 ASSERT_THAT(idmap, NotNull());
653
654 std::stringstream test_stream;
655 TestVisitor visitor(test_stream);
656 idmap->accept(&visitor);
657
658 ASSERT_EQ(test_stream.str(),
659 "TestVisitor::visit(Idmap)\n"
660 "TestVisitor::visit(IdmapHeader)\n"
661 "TestVisitor::visit(IdmapData)\n"
662 "TestVisitor::visit(IdmapData::Header)\n"
663 "TestVisitor::visit(IdmapData::TypeEntry)\n"
664 "TestVisitor::visit(IdmapData::TypeEntry)\n");
665}
666
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100667} // namespace android::idmap2