1 /*
2 * Copyright (C) 2017 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 <sstream>
18 #include <string>
19
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/statvfs.h>
24 #include <sys/stat.h>
25 #include <sys/xattr.h>
26
27 #include <android-base/file.h>
28 #include <android-base/logging.h>
29 #include <android-base/properties.h>
30 #include <android-base/scopeguard.h>
31 #include <android-base/stringprintf.h>
32 #include <cutils/properties.h>
33 #include <gtest/gtest.h>
34
35 #include "binder_test_utils.h"
36 #include "InstalldNativeService.h"
37 #include "dexopt.h"
38 #include "globals.h"
39 #include "utils.h"
40
41 using android::base::StringPrintf;
42
43 namespace android {
44 namespace installd {
45
46 constexpr const char* kTestUuid = "TEST";
47
48 #define FLAG_FORCE InstalldNativeService::FLAG_FORCE
49
get_property(const char * key,char * value,const char * default_value)50 int get_property(const char *key, char *value, const char *default_value) {
51 return property_get(key, value, default_value);
52 }
53
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)54 bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
55 const char *instruction_set) {
56 return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
57 }
58
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)59 bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
60 const char *instruction_set) {
61 return calculate_odex_file_path_default(path, apk_path, instruction_set);
62 }
63
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)64 bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
65 return create_cache_path_default(path, src, instruction_set);
66 }
67
get_full_path(const char * path)68 static std::string get_full_path(const char* path) {
69 return StringPrintf("/data/local/tmp/user/0/%s", path);
70 }
71
mkdir(const char * path,uid_t owner,gid_t group,mode_t mode)72 static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
73 const std::string fullPath = get_full_path(path);
74 EXPECT_EQ(::mkdir(fullPath.c_str(), mode), 0);
75 EXPECT_EQ(::chown(fullPath.c_str(), owner, group), 0);
76 EXPECT_EQ(::chmod(fullPath.c_str(), mode), 0);
77 }
78
touch(const char * path,uid_t owner,gid_t group,mode_t mode)79 static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
80 int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
81 EXPECT_NE(fd, -1);
82 EXPECT_EQ(::fchown(fd, owner, group), 0);
83 EXPECT_EQ(::fchmod(fd, mode), 0);
84 EXPECT_EQ(::close(fd), 0);
85 }
86
stat_gid(const char * path)87 static int stat_gid(const char* path) {
88 struct stat buf;
89 EXPECT_EQ(::stat(get_full_path(path).c_str(), &buf), 0);
90 return buf.st_gid;
91 }
92
stat_mode(const char * path)93 static int stat_mode(const char* path) {
94 struct stat buf;
95 EXPECT_EQ(::stat(get_full_path(path).c_str(), &buf), 0);
96 return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
97 }
98
99 class ServiceTest : public testing::Test {
100 protected:
101 InstalldNativeService* service;
102 std::unique_ptr<std::string> testUuid;
103
SetUp()104 virtual void SetUp() {
105 setenv("ANDROID_LOG_TAGS", "*:v", 1);
106 android::base::InitLogging(nullptr);
107
108 service = new InstalldNativeService();
109 testUuid = std::make_unique<std::string>();
110 *testUuid = std::string(kTestUuid);
111 system("mkdir -p /data/local/tmp/user/0");
112
113 init_globals_from_data_and_root();
114 }
115
TearDown()116 virtual void TearDown() {
117 delete service;
118 system("rm -rf /data/local/tmp/user");
119 }
120 };
121
TEST_F(ServiceTest,FixupAppData_Upgrade)122 TEST_F(ServiceTest, FixupAppData_Upgrade) {
123 LOG(INFO) << "FixupAppData_Upgrade";
124
125 mkdir("com.example", 10000, 10000, 0700);
126 mkdir("com.example/normal", 10000, 10000, 0700);
127 mkdir("com.example/cache", 10000, 10000, 0700);
128 touch("com.example/cache/file", 10000, 10000, 0700);
129
130 service->fixupAppData(testUuid, 0);
131
132 EXPECT_EQ(10000, stat_gid("com.example/normal"));
133 EXPECT_EQ(20000, stat_gid("com.example/cache"));
134 EXPECT_EQ(20000, stat_gid("com.example/cache/file"));
135
136 EXPECT_EQ(0700, stat_mode("com.example/normal"));
137 EXPECT_EQ(02771, stat_mode("com.example/cache"));
138 EXPECT_EQ(0700, stat_mode("com.example/cache/file"));
139 }
140
TEST_F(ServiceTest,FixupAppData_Moved)141 TEST_F(ServiceTest, FixupAppData_Moved) {
142 LOG(INFO) << "FixupAppData_Moved";
143
144 mkdir("com.example", 10000, 10000, 0700);
145 mkdir("com.example/foo", 10000, 10000, 0700);
146 touch("com.example/foo/file", 10000, 20000, 0700);
147 mkdir("com.example/bar", 10000, 20000, 0700);
148 touch("com.example/bar/file", 10000, 20000, 0700);
149
150 service->fixupAppData(testUuid, 0);
151
152 EXPECT_EQ(10000, stat_gid("com.example/foo"));
153 EXPECT_EQ(20000, stat_gid("com.example/foo/file"));
154 EXPECT_EQ(10000, stat_gid("com.example/bar"));
155 EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
156
157 service->fixupAppData(testUuid, FLAG_FORCE);
158
159 EXPECT_EQ(10000, stat_gid("com.example/foo"));
160 EXPECT_EQ(10000, stat_gid("com.example/foo/file"));
161 EXPECT_EQ(10000, stat_gid("com.example/bar"));
162 EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
163 }
164
TEST_F(ServiceTest,HashSecondaryDex)165 TEST_F(ServiceTest, HashSecondaryDex) {
166 LOG(INFO) << "HashSecondaryDex";
167
168 mkdir("com.example", 10000, 10000, 0700);
169 mkdir("com.example/foo", 10000, 10000, 0700);
170 touch("com.example/foo/file", 10000, 20000, 0700);
171
172 std::vector<uint8_t> result;
173 std::string dexPath = get_full_path("com.example/foo/file");
174 EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
175 dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
176
177 EXPECT_EQ(result.size(), 32U);
178
179 std::ostringstream output;
180 output << std::hex << std::setfill('0');
181 for (auto b : result) {
182 output << std::setw(2) << +b;
183 }
184
185 // This is the SHA256 of an empty string (sha256sum /dev/null)
186 EXPECT_EQ(output.str(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
187 }
188
TEST_F(ServiceTest,HashSecondaryDex_NoSuch)189 TEST_F(ServiceTest, HashSecondaryDex_NoSuch) {
190 LOG(INFO) << "HashSecondaryDex_NoSuch";
191
192 std::vector<uint8_t> result;
193 std::string dexPath = get_full_path("com.example/foo/file");
194 EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
195 dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
196
197 EXPECT_EQ(result.size(), 0U);
198 }
199
TEST_F(ServiceTest,HashSecondaryDex_Unreadable)200 TEST_F(ServiceTest, HashSecondaryDex_Unreadable) {
201 LOG(INFO) << "HashSecondaryDex_Unreadable";
202
203 mkdir("com.example", 10000, 10000, 0700);
204 mkdir("com.example/foo", 10000, 10000, 0700);
205 touch("com.example/foo/file", 10000, 20000, 0300);
206
207 std::vector<uint8_t> result;
208 std::string dexPath = get_full_path("com.example/foo/file");
209 EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
210 dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
211
212 EXPECT_EQ(result.size(), 0U);
213 }
214
TEST_F(ServiceTest,HashSecondaryDex_WrongApp)215 TEST_F(ServiceTest, HashSecondaryDex_WrongApp) {
216 LOG(INFO) << "HashSecondaryDex_WrongApp";
217
218 mkdir("com.example", 10000, 10000, 0700);
219 mkdir("com.example/foo", 10000, 10000, 0700);
220 touch("com.example/foo/file", 10000, 20000, 0700);
221
222 std::vector<uint8_t> result;
223 std::string dexPath = get_full_path("com.example/foo/file");
224 EXPECT_BINDER_FAIL(service->hashSecondaryDexFile(
225 dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result));
226 }
227
TEST_F(ServiceTest,CalculateOat)228 TEST_F(ServiceTest, CalculateOat) {
229 char buf[PKG_PATH_MAX];
230
231 EXPECT_TRUE(calculate_oat_file_path(buf, "/path/to/oat", "/path/to/file.apk", "isa"));
232 EXPECT_EQ("/path/to/oat/isa/file.odex", std::string(buf));
233
234 EXPECT_FALSE(calculate_oat_file_path(buf, "/path/to/oat", "/path/to/file", "isa"));
235 EXPECT_FALSE(calculate_oat_file_path(buf, "/path/to/oat", "file", "isa"));
236 }
237
TEST_F(ServiceTest,CalculateOdex)238 TEST_F(ServiceTest, CalculateOdex) {
239 char buf[PKG_PATH_MAX];
240
241 EXPECT_TRUE(calculate_odex_file_path(buf, "/path/to/file.apk", "isa"));
242 EXPECT_EQ("/path/to/oat/isa/file.odex", std::string(buf));
243 }
244
TEST_F(ServiceTest,CalculateCache)245 TEST_F(ServiceTest, CalculateCache) {
246 char buf[PKG_PATH_MAX];
247
248 EXPECT_TRUE(create_cache_path(buf, "/path/to/file.apk", "isa"));
249 EXPECT_EQ("/data/dalvik-cache/isa/path@to@file.apk@classes.dex", std::string(buf));
250 }
251
mkdirs(const std::string & path,mode_t mode)252 static bool mkdirs(const std::string& path, mode_t mode) {
253 struct stat sb;
254 if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
255 return true;
256 }
257
258 if (!mkdirs(android::base::Dirname(path), mode)) {
259 return false;
260 }
261
262 if (::mkdir(path.c_str(), mode) != 0) {
263 PLOG(DEBUG) << "Failed to create folder " << path;
264 return false;
265 }
266 return true;
267 }
268
269 class AppDataSnapshotTest : public testing::Test {
270 private:
271 std::string rollback_ce_base_dir;
272 std::string rollback_de_base_dir;
273
274 protected:
275 InstalldNativeService* service;
276
277 std::string fake_package_ce_path;
278 std::string fake_package_de_path;
279
SetUp()280 virtual void SetUp() {
281 setenv("ANDROID_LOG_TAGS", "*:v", 1);
282 android::base::InitLogging(nullptr);
283
284 service = new InstalldNativeService();
285 ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
286
287 init_globals_from_data_and_root();
288
289 rollback_ce_base_dir = create_data_misc_ce_rollback_base_path("TEST", 0);
290 rollback_de_base_dir = create_data_misc_de_rollback_base_path("TEST", 0);
291
292 fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
293 fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
294
295 ASSERT_TRUE(mkdirs(rollback_ce_base_dir, 0700));
296 ASSERT_TRUE(mkdirs(rollback_de_base_dir, 0700));
297 ASSERT_TRUE(mkdirs(fake_package_ce_path, 0700));
298 ASSERT_TRUE(mkdirs(fake_package_de_path, 0700));
299 }
300
TearDown()301 virtual void TearDown() {
302 ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_ce_base_dir, true));
303 ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_de_base_dir, true));
304 ASSERT_EQ(0, delete_dir_contents(fake_package_ce_path, true));
305 ASSERT_EQ(0, delete_dir_contents(fake_package_de_path, true));
306
307 delete service;
308 ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user/0", true));
309 }
310 };
311
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot)312 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot) {
313 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 37);
314 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 37);
315
316 ASSERT_TRUE(android::base::WriteStringToFile(
317 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
318 0700, 10000, 20000, false /* follow_symlinks */));
319 ASSERT_TRUE(android::base::WriteStringToFile(
320 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
321 0700, 10000, 20000, false /* follow_symlinks */));
322
323 // Request a snapshot of the CE content but not the DE content.
324 int64_t ce_snapshot_inode;
325 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
326 "com.foo", 0, 37, FLAG_STORAGE_CE, &ce_snapshot_inode));
327 struct stat buf;
328 memset(&buf, 0, sizeof(buf));
329 ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
330 ASSERT_EQ(ce_snapshot_inode, (int64_t) buf.st_ino);
331
332 std::string ce_content, de_content;
333 // At this point, we should have the CE content but not the DE content.
334 ASSERT_TRUE(android::base::ReadFileToString(
335 rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
336 ASSERT_FALSE(android::base::ReadFileToString(
337 rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
338 ASSERT_EQ("TEST_CONTENT_CE", ce_content);
339
340 // Modify the CE content, so we can assert later that it's reflected
341 // in the snapshot.
342 ASSERT_TRUE(android::base::WriteStringToFile(
343 "TEST_CONTENT_CE_MODIFIED", fake_package_ce_path + "/file1",
344 0700, 10000, 20000, false /* follow_symlinks */));
345
346 // Request a snapshot of the DE content but not the CE content.
347 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
348 "com.foo", 0, 37, FLAG_STORAGE_DE, &ce_snapshot_inode));
349 // Only DE content snapshot was requested.
350 ASSERT_EQ(ce_snapshot_inode, 0);
351
352 // At this point, both the CE as well as the DE content should be fully
353 // populated.
354 ASSERT_TRUE(android::base::ReadFileToString(
355 rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
356 ASSERT_TRUE(android::base::ReadFileToString(
357 rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
358 ASSERT_EQ("TEST_CONTENT_CE", ce_content);
359 ASSERT_EQ("TEST_CONTENT_DE", de_content);
360
361 // Modify the DE content, so we can assert later that it's reflected
362 // in our final snapshot.
363 ASSERT_TRUE(android::base::WriteStringToFile(
364 "TEST_CONTENT_DE_MODIFIED", fake_package_de_path + "/file1",
365 0700, 10000, 20000, false /* follow_symlinks */));
366
367 // Request a snapshot of both the CE as well as the DE content.
368 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
369 "com.foo", 0, 37, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
370
371 ASSERT_TRUE(android::base::ReadFileToString(
372 rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
373 ASSERT_TRUE(android::base::ReadFileToString(
374 rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
375 ASSERT_EQ("TEST_CONTENT_CE_MODIFIED", ce_content);
376 ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content);
377 }
378
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_TwoSnapshotsWithTheSameId)379 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_TwoSnapshotsWithTheSameId) {
380 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 67);
381 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 67);
382
383 auto another_fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.bar");
384 auto another_fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.bar");
385
386 // Since this test sets up data for another package, some bookkeeping is required.
387 auto deleter = [&]() {
388 ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_ce_path, true));
389 ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_de_path, true));
390 };
391 auto scope_guard = android::base::make_scope_guard(deleter);
392
393 ASSERT_TRUE(mkdirs(another_fake_package_ce_path, 0700));
394 ASSERT_TRUE(mkdirs(another_fake_package_de_path, 0700));
395
396 ASSERT_TRUE(android::base::WriteStringToFile(
397 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
398 0700, 10000, 20000, false /* follow_symlinks */));
399 ASSERT_TRUE(android::base::WriteStringToFile(
400 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
401 0700, 10000, 20000, false /* follow_symlinks */));
402 ASSERT_TRUE(android::base::WriteStringToFile(
403 "ANOTHER_TEST_CONTENT_CE", another_fake_package_ce_path + "/file1",
404 0700, 10000, 20000, false /* follow_symlinks */));
405 ASSERT_TRUE(android::base::WriteStringToFile(
406 "ANOTHER_TEST_CONTENT_DE", another_fake_package_de_path + "/file1",
407 0700, 10000, 20000, false /* follow_symlinks */));
408
409 // Request snapshot for the package com.foo.
410 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
411 "com.foo", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
412 // Now request snapshot with the same id for the package com.bar
413 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
414 "com.bar", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
415
416 // Check that both snapshots have correct data in them.
417 std::string com_foo_ce_content, com_foo_de_content;
418 std::string com_bar_ce_content, com_bar_de_content;
419 ASSERT_TRUE(android::base::ReadFileToString(
420 rollback_ce_dir + "/com.foo/file1", &com_foo_ce_content, false /* follow_symlinks */));
421 ASSERT_TRUE(android::base::ReadFileToString(
422 rollback_de_dir + "/com.foo/file1", &com_foo_de_content, false /* follow_symlinks */));
423 ASSERT_TRUE(android::base::ReadFileToString(
424 rollback_ce_dir + "/com.bar/file1", &com_bar_ce_content, false /* follow_symlinks */));
425 ASSERT_TRUE(android::base::ReadFileToString(
426 rollback_de_dir + "/com.bar/file1", &com_bar_de_content, false /* follow_symlinks */));
427 ASSERT_EQ("TEST_CONTENT_CE", com_foo_ce_content);
428 ASSERT_EQ("TEST_CONTENT_DE", com_foo_de_content);
429 ASSERT_EQ("ANOTHER_TEST_CONTENT_CE", com_bar_ce_content);
430 ASSERT_EQ("ANOTHER_TEST_CONTENT_DE", com_bar_de_content);
431 }
432
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_AppDataAbsent)433 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_AppDataAbsent) {
434 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 73);
435 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 73);
436
437 // Similuating app data absence.
438 ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_ce_path, true));
439 ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_de_path, true));
440
441 int64_t ce_snapshot_inode;
442 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
443 "com.foo", 0, 73, FLAG_STORAGE_CE, &ce_snapshot_inode));
444 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
445 "com.foo", 0, 73, FLAG_STORAGE_DE, nullptr));
446 // No CE content snapshot was performed.
447 ASSERT_EQ(ce_snapshot_inode, 0);
448
449 // The snapshot calls must succeed but there should be no snapshot
450 // created.
451 struct stat sb;
452 ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
453 ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
454 }
455
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_ClearsExistingSnapshot)456 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
457 auto rollback_ce_dir = create_data_misc_ce_rollback_package_path("TEST", 0, 13, "com.foo");
458 auto rollback_de_dir = create_data_misc_de_rollback_package_path("TEST", 0, 13, "com.foo");
459
460 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
461 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
462
463 // Simulate presence of an existing snapshot
464 ASSERT_TRUE(android::base::WriteStringToFile(
465 "TEST_CONTENT_CE", rollback_ce_dir + "/file1",
466 0700, 10000, 20000, false /* follow_symlinks */));
467 ASSERT_TRUE(android::base::WriteStringToFile(
468 "TEST_CONTENT_DE", rollback_de_dir + "/file1",
469 0700, 10000, 20000, false /* follow_symlinks */));
470
471 // Create app data.
472 ASSERT_TRUE(android::base::WriteStringToFile(
473 "TEST_CONTENT_2_CE", fake_package_ce_path + "/file2",
474 0700, 10000, 20000, false /* follow_symlinks */));
475 ASSERT_TRUE(android::base::WriteStringToFile(
476 "TEST_CONTENT_2_DE", fake_package_de_path + "/file2",
477 0700, 10000, 20000, false /* follow_symlinks */));
478
479 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
480 "com.foo", 0, 13, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
481
482 // Previous snapshot (with data for file1) must be cleared.
483 struct stat sb;
484 ASSERT_EQ(-1, stat((rollback_ce_dir + "/file1").c_str(), &sb));
485 ASSERT_EQ(-1, stat((rollback_de_dir + "/file1").c_str(), &sb));
486 // New snapshot (with data for file2) must be present.
487 ASSERT_NE(-1, stat((rollback_ce_dir + "/file2").c_str(), &sb));
488 ASSERT_NE(-1, stat((rollback_de_dir + "/file2").c_str(), &sb));
489 }
490
TEST_F(AppDataSnapshotTest,SnapshotAppData_WrongVolumeUuid)491 TEST_F(AppDataSnapshotTest, SnapshotAppData_WrongVolumeUuid) {
492 // Setup rollback folders to make sure that fails due to wrong volumeUuid being
493 // passed, not because of some other reason.
494 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 17);
495 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 17);
496
497 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
498 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
499
500 EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_unique<std::string>("FOO"),
501 "com.foo", 0, 17, FLAG_STORAGE_DE, nullptr));
502 }
503
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_ClearsCache)504 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsCache) {
505 auto fake_package_ce_cache_path = fake_package_ce_path + "/cache";
506 auto fake_package_ce_code_cache_path = fake_package_ce_path + "/code_cache";
507 auto fake_package_de_cache_path = fake_package_de_path + "/cache";
508 auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
509
510 ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 0700));
511 ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 0700));
512 ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 0700));
513 ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 0700));
514
515 ASSERT_TRUE(android::base::WriteStringToFile(
516 "TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
517 0700, 10000, 20000, false /* follow_symlinks */));
518 ASSERT_TRUE(android::base::WriteStringToFile(
519 "TEST_CONTENT_CE", fake_package_ce_code_cache_path + "/file1",
520 0700, 10000, 20000, false /* follow_symlinks */));
521 ASSERT_TRUE(android::base::WriteStringToFile(
522 "TEST_CONTENT_DE", fake_package_de_cache_path + "/file1",
523 0700, 10000, 20000, false /* follow_symlinks */));
524 ASSERT_TRUE(android::base::WriteStringToFile(
525 "TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
526 0700, 10000, 20000, false /* follow_symlinks */));
527 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
528 "com.foo", 0, 23, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
529 // The snapshot call must clear cache.
530 struct stat sb;
531 ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
532 ASSERT_EQ(-1, stat((fake_package_ce_code_cache_path + "/file1").c_str(), &sb));
533 ASSERT_EQ(-1, stat((fake_package_de_cache_path + "/file1").c_str(), &sb));
534 ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
535 }
536
TEST_F(AppDataSnapshotTest,RestoreAppDataSnapshot)537 TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot) {
538 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 239);
539 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 239);
540
541 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
542 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
543
544 // Write contents to the rollback location. We'll write the same files to the
545 // app data location and make sure the restore has overwritten them.
546 ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
547 ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
548 ASSERT_TRUE(android::base::WriteStringToFile(
549 "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
550 0700, 10000, 20000, false /* follow_symlinks */));
551 ASSERT_TRUE(android::base::WriteStringToFile(
552 "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
553 0700, 10000, 20000, false /* follow_symlinks */));
554 ASSERT_TRUE(android::base::WriteStringToFile(
555 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
556 0700, 10000, 20000, false /* follow_symlinks */));
557 ASSERT_TRUE(android::base::WriteStringToFile(
558 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
559 0700, 10000, 20000, false /* follow_symlinks */));
560
561 ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
562 "com.foo", 10000, "", 0, 239, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
563
564 std::string ce_content, de_content;
565 ASSERT_TRUE(android::base::ReadFileToString(
566 fake_package_ce_path + "/file1", &ce_content, false /* follow_symlinks */));
567 ASSERT_TRUE(android::base::ReadFileToString(
568 fake_package_de_path + "/file1", &de_content, false /* follow_symlinks */));
569 ASSERT_EQ("CE_RESTORE_CONTENT", ce_content);
570 ASSERT_EQ("DE_RESTORE_CONTENT", de_content);
571 }
572
TEST_F(AppDataSnapshotTest,CreateSnapshotThenDestroyIt)573 TEST_F(AppDataSnapshotTest, CreateSnapshotThenDestroyIt) {
574 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 57);
575 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 57);
576
577 // Prepare data for snapshot.
578 ASSERT_TRUE(android::base::WriteStringToFile(
579 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
580 0700, 10000, 20000, false /* follow_symlinks */));
581 ASSERT_TRUE(android::base::WriteStringToFile(
582 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
583 0700, 10000, 20000, false /* follow_symlinks */));
584
585 int64_t ce_snapshot_inode;
586 // Request a snapshot of both the CE as well as the DE content.
587 ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
588 "com.foo", 0, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
589 // Because CE data snapshot was requested, ce_snapshot_inode can't be null.
590 ASSERT_NE(0, ce_snapshot_inode);
591 // Check snapshot is there.
592 struct stat sb;
593 ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
594 ASSERT_EQ(0, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
595
596
597 ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
598 "com.foo", 0, ce_snapshot_inode, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
599 // Check snapshot is deleted.
600 ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
601 ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
602 }
603
TEST_F(AppDataSnapshotTest,DestroyAppDataSnapshot_CeSnapshotInodeIsZero)604 TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
605 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 1543);
606 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 1543);
607
608 // Create a snapshot
609 ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
610 ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
611 ASSERT_TRUE(android::base::WriteStringToFile(
612 "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
613 0700, 10000, 20000, false /* follow_symlinks */));
614 ASSERT_TRUE(android::base::WriteStringToFile(
615 "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
616 0700, 10000, 20000, false /* follow_symlinks */));
617
618 ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
619 "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
620
621 // Check snapshot is deleted.
622 struct stat sb;
623 ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
624 ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
625
626 // Check that deleting already deleted snapshot is no-op.
627 ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
628 "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
629 }
630
TEST_F(AppDataSnapshotTest,DestroyAppDataSnapshot_WrongVolumeUuid)631 TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
632 // Setup rollback data to make sure that test fails due to wrong volumeUuid
633 // being passed, not because of some other reason.
634 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 43);
635 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 43);
636
637 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
638 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
639
640 ASSERT_FALSE(service->destroyAppDataSnapshot(std::make_unique<std::string>("BAR"),
641 "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk());
642 }
643
TEST_F(AppDataSnapshotTest,RestoreAppDataSnapshot_WrongVolumeUuid)644 TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
645 // Setup rollback data to make sure that fails due to wrong volumeUuid being
646 // passed, not because of some other reason.
647 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 41);
648 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 41);
649
650 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
651 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
652
653 EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
654 "com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
655 }
656
657 } // namespace installd
658 } // namespace android
659