blob: 0f47f1e77d7ba280d94a4f8af8d2045ab8fd617c [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
Mårten Kongstad02751232018-04-27 13:16:32 +020018#include <fstream>
19#include <memory>
20#include <sstream>
21#include <string>
Mårten Kongstadce424902019-03-01 08:35:37 +010022#include <utility>
Mårten Kongstad02751232018-04-27 13:16:32 +020023#include <vector>
24
Ryan Mitchell52e1f7a2019-04-12 12:31:42 -070025#include "TestHelpers.h"
Mårten Kongstad02751232018-04-27 13:16:32 +020026#include "android-base/macros.h"
27#include "androidfw/ApkAssets.h"
Ryan Mitchell52e1f7a2019-04-12 12:31:42 -070028#include "gmock/gmock.h"
29#include "gtest/gtest.h"
Mårten Kongstad02751232018-04-27 13:16:32 +020030#include "idmap2/BinaryStreamVisitor.h"
31#include "idmap2/CommandLineOptions.h"
32#include "idmap2/Idmap.h"
33
Mårten Kongstad02751232018-04-27 13:16:32 +020034using ::testing::IsNull;
35using ::testing::NotNull;
36
Mårten Kongstad0eba72a2018-11-29 08:23:14 +010037namespace android::idmap2 {
Mårten Kongstad02751232018-04-27 13:16:32 +020038
39TEST(IdmapTests, TestCanonicalIdmapPathFor) {
40 ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
41 "/foo/vendor@overlay@bar.apk@idmap");
42}
43
44TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
45 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
46 std::istringstream stream(raw);
47 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
48 ASSERT_THAT(header, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010049 ASSERT_EQ(header->GetMagic(), 0x504d4449U);
50 ASSERT_EQ(header->GetVersion(), 0x01U);
51 ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
52 ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
Mårten Kongstad02751232018-04-27 13:16:32 +020053 ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
54 ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
55}
56
57TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
58 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
59 // overwrite the target path string, including the terminating null, with '.'
60 for (size_t i = 0x10; i < 0x110; i++) {
61 raw[i] = '.';
62 }
63 std::istringstream stream(raw);
64 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
65 ASSERT_THAT(header, IsNull());
66}
67
68TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
69 const size_t offset = 0x210;
70 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
71 idmap_raw_data_len - offset);
72 std::istringstream stream(raw);
73
74 std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
75 ASSERT_THAT(header, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010076 ASSERT_EQ(header->GetTargetPackageId(), 0x7fU);
77 ASSERT_EQ(header->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +020078}
79
80TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
81 const size_t offset = 0x214;
82 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
83 idmap_raw_data_len - offset);
84 std::istringstream stream(raw);
85
86 std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
87 ASSERT_THAT(data, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +010088 ASSERT_EQ(data->GetTargetTypeId(), 0x02U);
89 ASSERT_EQ(data->GetOverlayTypeId(), 0x02U);
90 ASSERT_EQ(data->GetEntryCount(), 1U);
91 ASSERT_EQ(data->GetEntryOffset(), 0U);
92 ASSERT_EQ(data->GetEntry(0), 0U);
Mårten Kongstad02751232018-04-27 13:16:32 +020093}
94
95TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
96 const size_t offset = 0x210;
97 std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
98 idmap_raw_data_len - offset);
99 std::istringstream stream(raw);
100
101 std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
102 ASSERT_THAT(data, NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100103 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
104 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200105 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100106 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200107
Mårten Kongstadb8779022018-11-29 09:53:17 +0100108 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
109 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
110 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
111 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
112 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200113
Mårten Kongstadb8779022018-11-29 09:53:17 +0100114 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
115 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
116 ASSERT_EQ(types[1]->GetEntryCount(), 3U);
117 ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
118 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200119 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100120 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200121}
122
123TEST(IdmapTests, CreateIdmapFromBinaryStream) {
124 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
125 std::istringstream stream(raw);
126
Mårten Kongstadce424902019-03-01 08:35:37 +0100127 auto result = Idmap::FromBinaryStream(stream);
128 ASSERT_TRUE(result);
129 const auto idmap = std::move(*result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200130
131 ASSERT_THAT(idmap->GetHeader(), NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100132 ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
133 ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
134 ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
135 ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200136 ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
137 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
138
139 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100140 ASSERT_EQ(dataBlocks.size(), 1U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200141
142 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
Mårten Kongstadb8779022018-11-29 09:53:17 +0100143 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
144 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200145 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100146 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200147
Mårten Kongstadb8779022018-11-29 09:53:17 +0100148 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
149 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
150 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
151 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
152 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200153
Mårten Kongstadb8779022018-11-29 09:53:17 +0100154 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
155 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
156 ASSERT_EQ(types[1]->GetEntryCount(), 3U);
157 ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
158 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200159 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100160 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200161}
162
163TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
164 std::string raw(reinterpret_cast<const char*>(idmap_raw_data),
165 10); // data too small
166 std::istringstream stream(raw);
167
Mårten Kongstadce424902019-03-01 08:35:37 +0100168 const auto result = Idmap::FromBinaryStream(stream);
169 ASSERT_FALSE(result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200170}
171
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800172void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
173 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
174 std::unique_ptr<const Idmap>* out_idmap) {
175 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
Mårten Kongstad02751232018-04-27 13:16:32 +0200176 ASSERT_THAT(target_apk, NotNull());
177
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800178 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
Mårten Kongstad02751232018-04-27 13:16:32 +0200179 ASSERT_THAT(overlay_apk, NotNull());
180
Mårten Kongstadce424902019-03-01 08:35:37 +0100181 auto result =
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800182 Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
Mårten Kongstadce424902019-03-01 08:35:37 +0100183 *overlay_apk, fulfilled_policies, enforce_overlayable);
184 *out_idmap = result ? std::move(*result) : nullptr;
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800185}
186
187TEST(IdmapTests, CreateIdmapFromApkAssets) {
188 std::unique_ptr<const Idmap> idmap;
189 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
190 std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
191 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
192 /* enforce_overlayable */ true, &idmap);
Mårten Kongstad02751232018-04-27 13:16:32 +0200193
194 ASSERT_THAT(idmap->GetHeader(), NotNull());
Mårten Kongstadb8779022018-11-29 09:53:17 +0100195 ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
196 ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700197 ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829);
Winsonb4100202019-02-06 12:05:32 -0800198 ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x8635c2ed);
Mårten Kongstad02751232018-04-27 13:16:32 +0200199 ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
200 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
201 ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
202
203 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100204 ASSERT_EQ(dataBlocks.size(), 1U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200205
206 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
207
Mårten Kongstadb8779022018-11-29 09:53:17 +0100208 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
209 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200210
211 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
Mårten Kongstadb8779022018-11-29 09:53:17 +0100212 ASSERT_EQ(types.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200213
Mårten Kongstadb8779022018-11-29 09:53:17 +0100214 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
215 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
216 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
217 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
218 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200219
Mårten Kongstadb8779022018-11-29 09:53:17 +0100220 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
221 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
222 ASSERT_EQ(types[1]->GetEntryCount(), 4U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700223 ASSERT_EQ(types[1]->GetEntryOffset(), 12U);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100224 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200225 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100226 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
227 ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
Mårten Kongstad02751232018-04-27 13:16:32 +0200228}
229
Ryan Mitchell19823452019-01-29 12:01:24 -0800230// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
231TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800232 std::unique_ptr<const Idmap> idmap;
233 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
234 std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
235 CreateIdmap(target_apk_path, overlay_apk_path,
236 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
237 /* enforce_overlayable */ true, &idmap);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800238 ASSERT_THAT(idmap, NotNull());
239
240 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
241 ASSERT_EQ(dataBlocks.size(), 1U);
242
243 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
244
245 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
246 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
247
248 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
249 ASSERT_EQ(types.size(), 1U);
250
251 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
252 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800253 ASSERT_EQ(types[0]->GetEntryCount(), 4U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700254 ASSERT_EQ(types[0]->GetEntryOffset(), 8U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100255 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public
256 ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
257 ASSERT_EQ(types[0]->GetEntry(2), 0x0001U); // string/policy_system
258 ASSERT_EQ(types[0]->GetEntry(3), 0x0002U); // string/policy_system_vendor
Winsonb4100202019-02-06 12:05:32 -0800259}
260
261TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800262 std::unique_ptr<const Idmap> idmap;
263 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
264 std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
265 CreateIdmap(target_apk_path, overlay_apk_path,
266 PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
267 /* enforce_overlayable */ true, &idmap);
Winsonb4100202019-02-06 12:05:32 -0800268 ASSERT_THAT(idmap, NotNull());
269
270 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
271 ASSERT_EQ(dataBlocks.size(), 1U);
272
273 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
274
275 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
276 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
277
278 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
279 ASSERT_EQ(types.size(), 1U);
280
281 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
282 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
283 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700284 ASSERT_EQ(types[0]->GetEntryOffset(), 9U);
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100285 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature
Winsonb4100202019-02-06 12:05:32 -0800286}
287
Ryan Mitchell19823452019-01-29 12:01:24 -0800288// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
289TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800290 std::unique_ptr<const Idmap> idmap;
291 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
292 std::string overlay_apk_path =
293 GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
294 CreateIdmap(target_apk_path, overlay_apk_path,
295 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
296 /* enforce_overlayable */ true, &idmap);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800297 ASSERT_THAT(idmap, NotNull());
298
299 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
300 ASSERT_EQ(dataBlocks.size(), 1U);
301
302 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
303
304 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
305 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
306
307 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
308 ASSERT_EQ(types.size(), 1U);
309
310 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
311 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Winsonb4100202019-02-06 12:05:32 -0800312 ASSERT_EQ(types[0]->GetEntryCount(), 4U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700313 ASSERT_EQ(types[0]->GetEntryOffset(), 8U);
314 ASSERT_EQ(types[0]->GetEntry(0), 0x0005U); // string/policy_public
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100315 ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
Ryan Mitchell939df092019-04-09 17:13:50 -0700316 ASSERT_EQ(types[0]->GetEntry(2), 0x0007U); // string/policy_system
317 ASSERT_EQ(types[0]->GetEntry(3), 0x0008U); // string/policy_system_vendor
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800318}
319
Ryan Mitchell19823452019-01-29 12:01:24 -0800320// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
321TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800322 std::unique_ptr<const Idmap> idmap;
323 std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
324 std::string overlay_apk_path =
325 GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
326 CreateIdmap(target_apk_path, overlay_apk_path,
327 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
328 /* enforce_overlayable */ false, &idmap);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800329 ASSERT_THAT(idmap, NotNull());
330
331 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
332 ASSERT_EQ(dataBlocks.size(), 1U);
333
334 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
335
336 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
337 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
338
339 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
340 ASSERT_EQ(types.size(), 1U);
341
342 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
343 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700344 ASSERT_EQ(types[0]->GetEntryCount(), 9U);
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800345 ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
346 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
Ryan Mitchell939df092019-04-09 17:13:50 -0700347 ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_odm
348 ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_oem
349 ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/other
350 ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_product
351 ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_public
352 ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_signature
353 ASSERT_EQ(types[0]->GetEntry(7), 0x0007U); // string/policy_system
354 ASSERT_EQ(types[0]->GetEntry(8), 0x0008U); // string/policy_system_vendor
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800355}
356
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800357// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
Ryan Mitchell19823452019-01-29 12:01:24 -0800358TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800359 std::unique_ptr<const Idmap> idmap;
360 std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
361 std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
362 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
363 /* enforce_overlayable */ false, &idmap);
Ryan Mitchell19823452019-01-29 12:01:24 -0800364 ASSERT_THAT(idmap, NotNull());
365
366 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
367 ASSERT_EQ(dataBlocks.size(), 1U);
368
369 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
370
371 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
372 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
373
374 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
375 ASSERT_EQ(types.size(), 2U);
376
377 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
378 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
379 ASSERT_EQ(types[0]->GetEntryCount(), 1U);
380 ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800381 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/int1
Ryan Mitchell19823452019-01-29 12:01:24 -0800382
383 ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
384 ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
385 ASSERT_EQ(types[1]->GetEntryCount(), 4U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700386 ASSERT_EQ(types[1]->GetEntryOffset(), 12U);
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800387 ASSERT_EQ(types[1]->GetEntry(0), 0x0000U); // string/str1
388 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry); // string/str2
389 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U); // string/str3
390 ASSERT_EQ(types[1]->GetEntry(3), 0x0002U); // string/str4
391}
392
393// Overlays that are not pre-installed and are not signed with the same signature as the target
394// cannot overlay packages that have not defined overlayable resources.
395TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
396 std::unique_ptr<const Idmap> idmap;
397 std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
398 std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
399 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
400 /* enforce_overlayable */ true, &idmap);
401 ASSERT_THAT(idmap, IsNull());
402}
403
404// Overlays that are pre-installed or are signed with the same signature as the target can overlay
405// packages that have not defined overlayable resources.
406TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
407 std::unique_ptr<const Idmap> idmap;
408 std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
409 std::string overlay_apk_path =
410 GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
411
412 auto CheckEntries = [&]() -> void {
413 const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
414 ASSERT_EQ(dataBlocks.size(), 1U);
415
416 const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800417 ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
418 ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
419
420 const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
421 ASSERT_EQ(types.size(), 1U);
422
423 ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
424 ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
Ryan Mitchell939df092019-04-09 17:13:50 -0700425 ASSERT_EQ(types[0]->GetEntryCount(), 9U);
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800426 ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
427 ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
Ryan Mitchell939df092019-04-09 17:13:50 -0700428 ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_odm
429 ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_oem
430 ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/other
431 ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_product
432 ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_public
433 ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_signature
434 ASSERT_EQ(types[0]->GetEntry(7), 0x0007U); // string/policy_system
435 ASSERT_EQ(types[0]->GetEntry(8), 0x0008U); // string/policy_system_vendor
Ryan Mitchellb863ca32019-03-07 14:31:54 -0800436 };
437
438 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
439 /* enforce_overlayable */ true, &idmap);
440 ASSERT_THAT(idmap, NotNull());
441 CheckEntries();
442
443 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
444 /* enforce_overlayable */ true, &idmap);
445 ASSERT_THAT(idmap, NotNull());
446 CheckEntries();
447
448 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
449 /* enforce_overlayable */ true, &idmap);
450 ASSERT_THAT(idmap, NotNull());
451 CheckEntries();
452
453 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
454 /* enforce_overlayable */ true, &idmap);
455 ASSERT_THAT(idmap, NotNull());
456 CheckEntries();
Ryan Mitchell939df092019-04-09 17:13:50 -0700457
458 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_ODM_PARTITION,
459 /* enforce_overlayable */ true, &idmap);
460 ASSERT_THAT(idmap, NotNull());
461 CheckEntries();
462
463 CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_OEM_PARTITION,
464 /* enforce_overlayable */ true, &idmap);
465 ASSERT_THAT(idmap, NotNull());
466 CheckEntries();
Ryan Mitchell19823452019-01-29 12:01:24 -0800467}
468
Mårten Kongstad02751232018-04-27 13:16:32 +0200469TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
470 std::string target_apk_path(GetTestDataPath());
471 for (int i = 0; i < 32; i++) {
472 target_apk_path += "/target/../";
473 }
474 target_apk_path += "/target/target.apk";
475 ASSERT_GT(target_apk_path.size(), kIdmapStringLength);
476 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
477 ASSERT_THAT(target_apk, NotNull());
478
479 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
480 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
481 ASSERT_THAT(overlay_apk, NotNull());
482
Mårten Kongstadce424902019-03-01 08:35:37 +0100483 const auto result =
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800484 Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
Mårten Kongstadce424902019-03-01 08:35:37 +0100485 PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
486 ASSERT_FALSE(result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200487}
488
489TEST(IdmapTests, IdmapHeaderIsUpToDate) {
490 fclose(stderr); // silence expected warnings from libandroidfw
491
492 const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
493 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
494 ASSERT_THAT(target_apk, NotNull());
495
496 const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
497 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
498 ASSERT_THAT(overlay_apk, NotNull());
499
Mårten Kongstadce424902019-03-01 08:35:37 +0100500 auto result = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
501 PolicyFlags::POLICY_PUBLIC,
502 /* enforce_overlayable */ true);
503 ASSERT_TRUE(result);
504 const auto idmap = std::move(*result);
Mårten Kongstad02751232018-04-27 13:16:32 +0200505
506 std::stringstream stream;
507 BinaryStreamVisitor visitor(stream);
508 idmap->accept(&visitor);
509
510 std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
511 ASSERT_THAT(header, NotNull());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100512 ASSERT_TRUE(header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200513
514 // magic: bytes (0x0, 0x03)
515 std::string bad_magic_string(stream.str());
516 bad_magic_string[0x0] = '.';
517 bad_magic_string[0x1] = '.';
518 bad_magic_string[0x2] = '.';
519 bad_magic_string[0x3] = '.';
520 std::stringstream bad_magic_stream(bad_magic_string);
521 std::unique_ptr<const IdmapHeader> bad_magic_header =
522 IdmapHeader::FromBinaryStream(bad_magic_stream);
523 ASSERT_THAT(bad_magic_header, NotNull());
524 ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100525 ASSERT_FALSE(bad_magic_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200526
527 // version: bytes (0x4, 0x07)
528 std::string bad_version_string(stream.str());
529 bad_version_string[0x4] = '.';
530 bad_version_string[0x5] = '.';
531 bad_version_string[0x6] = '.';
532 bad_version_string[0x7] = '.';
533 std::stringstream bad_version_stream(bad_version_string);
534 std::unique_ptr<const IdmapHeader> bad_version_header =
535 IdmapHeader::FromBinaryStream(bad_version_stream);
536 ASSERT_THAT(bad_version_header, NotNull());
537 ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100538 ASSERT_FALSE(bad_version_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200539
540 // target crc: bytes (0x8, 0xb)
541 std::string bad_target_crc_string(stream.str());
542 bad_target_crc_string[0x8] = '.';
543 bad_target_crc_string[0x9] = '.';
544 bad_target_crc_string[0xa] = '.';
545 bad_target_crc_string[0xb] = '.';
546 std::stringstream bad_target_crc_stream(bad_target_crc_string);
547 std::unique_ptr<const IdmapHeader> bad_target_crc_header =
548 IdmapHeader::FromBinaryStream(bad_target_crc_stream);
549 ASSERT_THAT(bad_target_crc_header, NotNull());
550 ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100551 ASSERT_FALSE(bad_target_crc_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200552
553 // overlay crc: bytes (0xc, 0xf)
554 std::string bad_overlay_crc_string(stream.str());
555 bad_overlay_crc_string[0xc] = '.';
556 bad_overlay_crc_string[0xd] = '.';
557 bad_overlay_crc_string[0xe] = '.';
558 bad_overlay_crc_string[0xf] = '.';
559 std::stringstream bad_overlay_crc_stream(bad_overlay_crc_string);
560 std::unique_ptr<const IdmapHeader> bad_overlay_crc_header =
561 IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
562 ASSERT_THAT(bad_overlay_crc_header, NotNull());
563 ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100564 ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200565
566 // target path: bytes (0x10, 0x10f)
567 std::string bad_target_path_string(stream.str());
568 bad_target_path_string[0x10] = '\0';
569 std::stringstream bad_target_path_stream(bad_target_path_string);
570 std::unique_ptr<const IdmapHeader> bad_target_path_header =
571 IdmapHeader::FromBinaryStream(bad_target_path_stream);
572 ASSERT_THAT(bad_target_path_header, NotNull());
573 ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100574 ASSERT_FALSE(bad_target_path_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200575
576 // overlay path: bytes (0x110, 0x20f)
577 std::string bad_overlay_path_string(stream.str());
578 bad_overlay_path_string[0x110] = '\0';
579 std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
580 std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
581 IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
582 ASSERT_THAT(bad_overlay_path_header, NotNull());
583 ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100584 ASSERT_FALSE(bad_overlay_path_header->IsUpToDate());
Mårten Kongstad02751232018-04-27 13:16:32 +0200585}
586
587class TestVisitor : public Visitor {
588 public:
589 explicit TestVisitor(std::ostream& stream) : stream_(stream) {
590 }
591
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100592 void visit(const Idmap& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200593 stream_ << "TestVisitor::visit(Idmap)" << std::endl;
594 }
595
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100596 void visit(const IdmapHeader& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200597 stream_ << "TestVisitor::visit(IdmapHeader)" << std::endl;
598 }
599
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100600 void visit(const IdmapData& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200601 stream_ << "TestVisitor::visit(IdmapData)" << std::endl;
602 }
603
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100604 void visit(const IdmapData::Header& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200605 stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
606 }
607
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100608 void visit(const IdmapData::TypeEntry& idmap ATTRIBUTE_UNUSED) override {
Mårten Kongstad02751232018-04-27 13:16:32 +0200609 stream_ << "TestVisitor::visit(IdmapData::TypeEntry)" << std::endl;
610 }
611
612 private:
613 std::ostream& stream_;
614};
615
616TEST(IdmapTests, TestVisitor) {
617 std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
618 std::istringstream stream(raw);
619
Mårten Kongstadce424902019-03-01 08:35:37 +0100620 const auto idmap = Idmap::FromBinaryStream(stream);
621 ASSERT_TRUE(idmap);
Mårten Kongstad02751232018-04-27 13:16:32 +0200622
623 std::stringstream test_stream;
624 TestVisitor visitor(test_stream);
Mårten Kongstadce424902019-03-01 08:35:37 +0100625 (*idmap)->accept(&visitor);
Mårten Kongstad02751232018-04-27 13:16:32 +0200626
627 ASSERT_EQ(test_stream.str(),
628 "TestVisitor::visit(Idmap)\n"
629 "TestVisitor::visit(IdmapHeader)\n"
630 "TestVisitor::visit(IdmapData)\n"
631 "TestVisitor::visit(IdmapData::Header)\n"
632 "TestVisitor::visit(IdmapData::TypeEntry)\n"
633 "TestVisitor::visit(IdmapData::TypeEntry)\n");
634}
635
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100636} // namespace android::idmap2