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