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