blob: 621f50337aa3ce557c53af9321fcbc87a19f2751 [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>
Mårten Kongstadce424902019-03-01 08:35:37 +010023#include <utility>
Mårten Kongstad02751232018-04-27 13:16:32 +020024#include <vector>
25
26#include "gmock/gmock.h"
27#include "gtest/gtest.h"
28
29#include "android-base/macros.h"
30#include "androidfw/ApkAssets.h"
31
32#include "idmap2/BinaryStreamVisitor.h"
33#include "idmap2/CommandLineOptions.h"
34#include "idmap2/Idmap.h"
35
36#include "TestHelpers.h"
37
38using ::testing::IsNull;
39using ::testing::NotNull;
40
Mårten Kongstad0eba72a2018-11-29 08:23:14 +010041namespace android::idmap2 {
Mårten Kongstad02751232018-04-27 13:16:32 +020042
43TEST(IdmapTests, TestCanonicalIdmapPathFor) {
44 ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
45 "/foo/vendor@overlay@bar.apk@idmap");
46}
47
48TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
49 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
50 std::istringstream stream(raw);
51 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
52 ASSERT_THAT(header, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010053 ASSERT_EQ(header->GetMagic(), 0x504d4449U);
54 ASSERT_EQ(header->GetVersion(), 0x01U);
55 ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
56 ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
Mårten Kongstad02751232018-04-27 13:16:32 +020057 ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
58 ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
59}
60
61TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
62 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
63 // overwrite the target path string, including the terminating null, with '.'
64 for (size_t i = 0x10; i < 0x110; i++) {
65 raw[i] = '.';
66 }
67 std::istringstream stream(raw);
68 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
69 ASSERT_THAT(header, IsNull());
70}
71
72TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
73 const size_t offset = 0x210;
74 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
75 idmap_raw_data_len - offset);
76 std::istringstream stream(raw);
77
78 std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
79 ASSERT_THAT(header, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010080 ASSERT_EQ(header->GetTargetPackageId(), 0x7fU);
81 ASSERT_EQ(header->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +020082}
83
84TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
85 const size_t offset = 0x214;
86 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
87 idmap_raw_data_len - offset);
88 std::istringstream stream(raw);
89
90 std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
91 ASSERT_THAT(data, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010092 ASSERT_EQ(data->GetTargetTypeId(), 0x02U);
93 ASSERT_EQ(data->GetOverlayTypeId(), 0x02U);
94 ASSERT_EQ(data->GetEntryCount(), 1U);
95 ASSERT_EQ(data->GetEntryOffset(), 0U);
96 ASSERT_EQ(data->GetEntry(0), 0U);
Mårten Kongstad02751232018-04-27 13:16:32 +020097}
98
99TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
100 const size_t offset = 0x210;
101 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
102 idmap_raw_data_len - offset);
103 std::istringstream stream(raw);
104
105 std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
106 ASSERT_THAT(data, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100107 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
108 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200109 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100110 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200111
Mårten Kongstadb8779022018-11-29 09:53:17 +0100112 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
113 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
114 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
115 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
116 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200117
Mårten Kongstadb8779022018-11-29 09:53:17 +0100118 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
119 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
120 ASSERT_EQ(types[1]->GetEntryCount(), 3U);
121 ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
122 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200123 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100124 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200125}
126
127TEST(IdmapTests, CreateIdmapFromBinaryStream) {
128 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
129 std::istringstream stream(raw);
130
Mårten Kongstadce424902019-03-01 08:35:37 +0100131 auto result = Idmap::FromBinaryStream(stream);
132 ASSERT_TRUE(result);
133 const auto idmap = std::move(*result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200134
135 ASSERT_THAT(idmap->GetHeader(), NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100136 ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
137 ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
138 ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
139 ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200140 ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
141 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
142
143 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100144 ASSERT_EQ(dataBlocks.size(), 1U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200145
146 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
Mårten Kongstadb8779022018-11-29 09:53:17 +0100147 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
148 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200149 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100150 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200151
Mårten Kongstadb8779022018-11-29 09:53:17 +0100152 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
153 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
154 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
155 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
156 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200157
Mårten Kongstadb8779022018-11-29 09:53:17 +0100158 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
159 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
160 ASSERT_EQ(types[1]->GetEntryCount(), 3U);
161 ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
162 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200163 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100164 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200165}
166
167TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
168 std::string raw(reinterpret_cast<const char*>(idmap_raw_data),
169 10); // data too small
170 std::istringstream stream(raw);
171
Mårten Kongstadce424902019-03-01 08:35:37 +0100172 const auto result = Idmap::FromBinaryStream(stream);
173 ASSERT_FALSE(result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200174}
175
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800176void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
177 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
178 std::unique_ptr<const Idmap>* out_idmap) {
179 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
Mårten Kongstad02751232018-04-27 13:16:32 +0200180 ASSERT_THAT(target_apk, NotNull());
181
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800182 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
Mårten Kongstad02751232018-04-27 13:16:32 +0200183 ASSERT_THAT(overlay_apk, NotNull());
184
Mårten Kongstadce424902019-03-01 08:35:37 +0100185 auto result =
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800186 Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
Mårten Kongstadce424902019-03-01 08:35:37 +0100187 *overlay_apk, fulfilled_policies, enforce_overlayable);
188 *out_idmap = result ? std::move(*result) : nullptr;
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800189}
190
191TEST(IdmapTests, CreateIdmapFromApkAssets) {
192 std::unique_ptr<const Idmap> idmap;
193 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
194 std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
195 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
196 /* enforce_overlayable */ true, &idmap);
Mårten Kongstad02751232018-04-27 13:16:32 +0200197
198 ASSERT_THAT(idmap->GetHeader(), NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100199 ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
200 ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800201 ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xd513ca1b);
202 ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x8635c2ed);
Mårten Kongstad02751232018-04-27 13:16:32 +0200203 ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
204 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
205 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
206
207 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100208 ASSERT_EQ(dataBlocks.size(), 1U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200209
210 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
211
Mårten Kongstadb8779022018-11-29 09:53:17 +0100212 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
213 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200214
215 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100216 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200217
Mårten Kongstadb8779022018-11-29 09:53:17 +0100218 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
219 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
220 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
221 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
222 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200223
Mårten Kongstadb8779022018-11-29 09:53:17 +0100224 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
225 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
226 ASSERT_EQ(types[1]->GetEntryCount(), 4U);
Winsonb4100202019-02-06 12:05:32 -0800227 ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100228 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200229 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100230 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
231 ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200232}
233
Ryan Mitchell19823452019-01-29 12:01:24 -0800234// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
235TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800236 std::unique_ptr<const Idmap> idmap;
237 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
238 std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
239 CreateIdmap(target_apk_path, overlay_apk_path,
240 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
241 /* enforce_overlayable */ true, &idmap);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800242 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) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800266 std::unique_ptr<const Idmap> idmap;
267 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
268 std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
269 CreateIdmap(target_apk_path, overlay_apk_path,
270 PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
271 /* enforce_overlayable */ true, &idmap);
Winsonb4100202019-02-06 12:05:32 -0800272 ASSERT_THAT(idmap, NotNull());
273
274 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
275 ASSERT_EQ(dataBlocks.size(), 1U);
276
277 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
278
279 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
280 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
281
282 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
283 ASSERT_EQ(types.size(), 1U);
284
285 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
286 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
287 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
288 ASSERT_EQ(types[0]->GetEntryOffset(), 7U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100289 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature
Winsonb4100202019-02-06 12:05:32 -0800290}
291
Ryan Mitchell19823452019-01-29 12:01:24 -0800292// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
293TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800294 std::unique_ptr<const Idmap> idmap;
295 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
296 std::string overlay_apk_path =
297 GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
298 CreateIdmap(target_apk_path, overlay_apk_path,
299 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
300 /* enforce_overlayable */ true, &idmap);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800301 ASSERT_THAT(idmap, NotNull());
302
303 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
304 ASSERT_EQ(dataBlocks.size(), 1U);
305
306 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
307
308 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
309 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
310
311 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
312 ASSERT_EQ(types.size(), 1U);
313
314 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
315 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800316 ASSERT_EQ(types[0]->GetEntryCount(), 4U);
Ryan Mitchell19823452019-01-29 12:01:24 -0800317 ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100318 ASSERT_EQ(types[0]->GetEntry(0), 0x0003U); // string/policy_public
319 ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
320 ASSERT_EQ(types[0]->GetEntry(2), 0x0005U); // string/policy_system
321 ASSERT_EQ(types[0]->GetEntry(3), 0x0006U); // string/policy_system_vendor
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800322}
323
Ryan Mitchell19823452019-01-29 12:01:24 -0800324// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
325TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800326 std::unique_ptr<const Idmap> idmap;
327 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
328 std::string overlay_apk_path =
329 GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
330 CreateIdmap(target_apk_path, overlay_apk_path,
331 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
332 /* enforce_overlayable */ false, &idmap);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800333 ASSERT_THAT(idmap, NotNull());
334
335 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
336 ASSERT_EQ(dataBlocks.size(), 1U);
337
338 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
339
340 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
341 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
342
343 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
344 ASSERT_EQ(types.size(), 1U);
345
346 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
347 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800348 ASSERT_EQ(types[0]->GetEntryCount(), 7U);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800349 ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
350 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
Ryan Mitchella3628462019-01-14 12:19:40 -0800351 ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
352 ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
Winsonb4100202019-02-06 12:05:32 -0800353 ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_signature
354 ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_public
355 ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
356 ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800357}
358
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800359// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
Ryan Mitchell19823452019-01-29 12:01:24 -0800360TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800361 std::unique_ptr<const Idmap> idmap;
362 std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
363 std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
364 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
365 /* enforce_overlayable */ false, &idmap);
Ryan Mitchell19823452019-01-29 12:01:24 -0800366 ASSERT_THAT(idmap, NotNull());
367
368 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
369 ASSERT_EQ(dataBlocks.size(), 1U);
370
371 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
372
373 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
374 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
375
376 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
377 ASSERT_EQ(types.size(), 2U);
378
379 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
380 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
381 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
382 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800383 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/int1
Ryan Mitchell19823452019-01-29 12:01:24 -0800384
385 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
386 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
387 ASSERT_EQ(types[1]->GetEntryCount(), 4U);
Winsonb4100202019-02-06 12:05:32 -0800388 ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800389 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U); // string/str1
390 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry); // string/str2
391 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U); // string/str3
392 ASSERT_EQ(types[1]->GetEntry(3), 0x0002U); // string/str4
393}
394
395// Overlays that are not pre-installed and are not signed with the same signature as the target
396// cannot overlay packages that have not defined overlayable resources.
397TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
398 std::unique_ptr<const Idmap> idmap;
399 std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
400 std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
401 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
402 /* enforce_overlayable */ true, &idmap);
403 ASSERT_THAT(idmap, IsNull());
404}
405
406// Overlays that are pre-installed or are signed with the same signature as the target can overlay
407// packages that have not defined overlayable resources.
408TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
409 std::unique_ptr<const Idmap> idmap;
410 std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
411 std::string overlay_apk_path =
412 GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
413
414 auto CheckEntries = [&]() -> void {
415 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
416 ASSERT_EQ(dataBlocks.size(), 1U);
417
418 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
419
420 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
421 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
422
423 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
424 ASSERT_EQ(types.size(), 1U);
425
426 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
427 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
428 ASSERT_EQ(types[0]->GetEntryCount(), 7U);
429 ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
430 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
431 ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
432 ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
433 ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public
434 ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/string/policy_signature
435 ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
436 ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
437 };
438
439 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
440 /* enforce_overlayable */ true, &idmap);
441 ASSERT_THAT(idmap, NotNull());
442 CheckEntries();
443
444 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
445 /* enforce_overlayable */ true, &idmap);
446 ASSERT_THAT(idmap, NotNull());
447 CheckEntries();
448
449 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
450 /* enforce_overlayable */ true, &idmap);
451 ASSERT_THAT(idmap, NotNull());
452 CheckEntries();
453
454 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
455 /* enforce_overlayable */ true, &idmap);
456 ASSERT_THAT(idmap, NotNull());
457 CheckEntries();
Ryan Mitchell19823452019-01-29 12:01:24 -0800458}
459
Mårten Kongstad02751232018-04-27 13:16:32 +0200460TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
461 std::string target_apk_path(GetTestDataPath());
462 for (int i = 0; i < 32; i++) {
463 target_apk_path += "/target/../";
464 }
465 target_apk_path += "/target/target.apk";
466 ASSERT_GT(target_apk_path.size(), kIdmapStringLength);
467 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
468 ASSERT_THAT(target_apk, NotNull());
469
470 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
471 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
472 ASSERT_THAT(overlay_apk, NotNull());
473
Mårten Kongstadce424902019-03-01 08:35:37 +0100474 const auto result =
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800475 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
Mårten Kongstadce424902019-03-01 08:35:37 +0100476 PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
477 ASSERT_FALSE(result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200478}
479
480TEST(IdmapTests, IdmapHeaderIsUpToDate) {
481 fclose(stderr); // silence expected warnings from libandroidfw
482
483 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
484 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
485 ASSERT_THAT(target_apk, NotNull());
486
487 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
488 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
489 ASSERT_THAT(overlay_apk, NotNull());
490
Mårten Kongstadce424902019-03-01 08:35:37 +0100491 auto result = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
492 PolicyFlags::POLICY_PUBLIC,
493 /* enforce_overlayable */ true);
494 ASSERT_TRUE(result);
495 const auto idmap = std::move(*result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200496
497 std::stringstream stream;
498 BinaryStreamVisitor visitor(stream);
499 idmap->accept(&visitor);
500
501 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
502 ASSERT_THAT(header, NotNull());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100503 ASSERT_TRUE(header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200504
505 // magic: bytes (0x0, 0x03)
506 std::string bad_magic_string(stream.str());
507 bad_magic_string[0x0] = '.';
508 bad_magic_string[0x1] = '.';
509 bad_magic_string[0x2] = '.';
510 bad_magic_string[0x3] = '.';
511 std::stringstream bad_magic_stream(bad_magic_string);
512 std::unique_ptr<const IdmapHeader> bad_magic_header =
513 IdmapHeader::FromBinaryStream(bad_magic_stream);
514 ASSERT_THAT(bad_magic_header, NotNull());
515 ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100516 ASSERT_FALSE(bad_magic_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200517
518 // version: bytes (0x4, 0x07)
519 std::string bad_version_string(stream.str());
520 bad_version_string[0x4] = '.';
521 bad_version_string[0x5] = '.';
522 bad_version_string[0x6] = '.';
523 bad_version_string[0x7] = '.';
524 std::stringstream bad_version_stream(bad_version_string);
525 std::unique_ptr<const IdmapHeader> bad_version_header =
526 IdmapHeader::FromBinaryStream(bad_version_stream);
527 ASSERT_THAT(bad_version_header, NotNull());
528 ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100529 ASSERT_FALSE(bad_version_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200530
531 // target crc: bytes (0x8, 0xb)
532 std::string bad_target_crc_string(stream.str());
533 bad_target_crc_string[0x8] = '.';
534 bad_target_crc_string[0x9] = '.';
535 bad_target_crc_string[0xa] = '.';
536 bad_target_crc_string[0xb] = '.';
537 std::stringstream bad_target_crc_stream(bad_target_crc_string);
538 std::unique_ptr<const IdmapHeader> bad_target_crc_header =
539 IdmapHeader::FromBinaryStream(bad_target_crc_stream);
540 ASSERT_THAT(bad_target_crc_header, NotNull());
541 ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100542 ASSERT_FALSE(bad_target_crc_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200543
544 // overlay crc: bytes (0xc, 0xf)
545 std::string bad_overlay_crc_string(stream.str());
546 bad_overlay_crc_string[0xc] = '.';
547 bad_overlay_crc_string[0xd] = '.';
548 bad_overlay_crc_string[0xe] = '.';
549 bad_overlay_crc_string[0xf] = '.';
550 std::stringstream bad_overlay_crc_stream(bad_overlay_crc_string);
551 std::unique_ptr<const IdmapHeader> bad_overlay_crc_header =
552 IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
553 ASSERT_THAT(bad_overlay_crc_header, NotNull());
554 ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100555 ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200556
557 // target path: bytes (0x10, 0x10f)
558 std::string bad_target_path_string(stream.str());
559 bad_target_path_string[0x10] = '\0';
560 std::stringstream bad_target_path_stream(bad_target_path_string);
561 std::unique_ptr<const IdmapHeader> bad_target_path_header =
562 IdmapHeader::FromBinaryStream(bad_target_path_stream);
563 ASSERT_THAT(bad_target_path_header, NotNull());
564 ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100565 ASSERT_FALSE(bad_target_path_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200566
567 // overlay path: bytes (0x110, 0x20f)
568 std::string bad_overlay_path_string(stream.str());
569 bad_overlay_path_string[0x110] = '\0';
570 std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
571 std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
572 IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
573 ASSERT_THAT(bad_overlay_path_header, NotNull());
574 ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100575 ASSERT_FALSE(bad_overlay_path_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200576}
577
578class TestVisitor : public Visitor {
579 public:
580 explicit TestVisitor(std::ostream& stream) : stream_(stream) {
581 }
582
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100583 void visit(const Idmap& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200584 stream_ << "TestVisitor::visit(Idmap)" << std::endl;
585 }
586
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100587 void visit(const IdmapHeader& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200588 stream_ << "TestVisitor::visit(IdmapHeader)" << std::endl;
589 }
590
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100591 void visit(const IdmapData& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200592 stream_ << "TestVisitor::visit(IdmapData)" << std::endl;
593 }
594
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100595 void visit(const IdmapData::Header& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200596 stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
597 }
598
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100599 void visit(const IdmapData::TypeEntry& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200600 stream_ << "TestVisitor::visit(IdmapData::TypeEntry)" << std::endl;
601 }
602
603 private:
604 std::ostream& stream_;
605};
606
607TEST(IdmapTests, TestVisitor) {
608 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
609 std::istringstream stream(raw);
610
Mårten Kongstadce424902019-03-01 08:35:37 +0100611 const auto idmap = Idmap::FromBinaryStream(stream);
612 ASSERT_TRUE(idmap);
Mårten Kongstad02751232018-04-27 13:16:32 +0200613
614 std::stringstream test_stream;
615 TestVisitor visitor(test_stream);
Mårten Kongstadce424902019-03-01 08:35:37 +0100616 (*idmap)->accept(&visitor);
Mårten Kongstad02751232018-04-27 13:16:32 +0200617
618 ASSERT_EQ(test_stream.str(),
619 "TestVisitor::visit(Idmap)\n"
620 "TestVisitor::visit(IdmapHeader)\n"
621 "TestVisitor::visit(IdmapData)\n"
622 "TestVisitor::visit(IdmapData::Header)\n"
623 "TestVisitor::visit(IdmapData::TypeEntry)\n"
624 "TestVisitor::visit(IdmapData::TypeEntry)\n");
625}
626
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100627} // namespace android::idmap2