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 #include <filesystem>
36 #include <fstream>
37
38 #include <android/content/pm/IPackageManagerNative.h>
39 #include <binder/IServiceManager.h>
40 #include "InstalldNativeService.h"
41 #include "binder/Status.h"
42 #include "binder_test_utils.h"
43 #include "dexopt.h"
44 #include "globals.h"
45 #include "unique_file.h"
46 #include "utils.h"
47
48 using android::base::StringPrintf;
49 using android::base::unique_fd;
50 using android::os::ParcelFileDescriptor;
51 using std::filesystem::is_empty;
52
53 namespace android {
get_package_name(uid_t uid)54 std::string get_package_name(uid_t uid) {
55 sp<IServiceManager> sm = defaultServiceManager();
56 sp<content::pm::IPackageManagerNative> package_mgr;
57 if (sm.get() == nullptr) {
58 LOG(INFO) << "Cannot find service manager";
59 } else {
60 sp<IBinder> binder = sm->getService(String16("package_native"));
61 if (binder.get() == nullptr) {
62 LOG(INFO) << "Cannot find package_native";
63 } else {
64 package_mgr = interface_cast<content::pm::IPackageManagerNative>(binder);
65 }
66 }
67 // find package name
68 std::string pkg;
69 if (package_mgr != nullptr) {
70 std::vector<std::string> names;
71 binder::Status status = package_mgr->getNamesForUids({(int)uid}, &names);
72 if (!status.isOk()) {
73 LOG(INFO) << "getNamesForUids failed: %s", status.exceptionMessage().c_str();
74 } else {
75 if (!names[0].empty()) {
76 pkg = names[0].c_str();
77 }
78 }
79 }
80 return pkg;
81 }
82 namespace installd {
83
84 static constexpr const char* kTestUuid = "TEST";
85 static const std::string kTestPath = "/data/local/tmp";
86 static constexpr const uid_t kNobodyUid = 9999;
87 static constexpr const uid_t kSystemUid = 1000;
88 static constexpr const int32_t kTestUserId = 0;
89 static constexpr const uid_t kTestAppId = 19999;
90 static constexpr const int FLAG_STORAGE_SDK = InstalldNativeService::FLAG_STORAGE_SDK;
91 static constexpr const int FLAG_CLEAR_CACHE_ONLY = InstalldNativeService::FLAG_CLEAR_CACHE_ONLY;
92 static constexpr const int FLAG_CLEAR_CODE_CACHE_ONLY =
93 InstalldNativeService::FLAG_CLEAR_CODE_CACHE_ONLY;
94
95 const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
96 const gid_t kTestCacheGid = multiuser_get_cache_gid(kTestUserId, kTestAppId);
97 const uid_t kTestSdkSandboxUid = multiuser_get_sdk_sandbox_uid(kTestUserId, kTestAppId);
98
99 #define FLAG_FORCE InstalldNativeService::FLAG_FORCE
100
get_property(const char * key,char * value,const char * default_value)101 int get_property(const char *key, char *value, const char *default_value) {
102 return property_get(key, value, default_value);
103 }
104
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)105 bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
106 const char *instruction_set) {
107 return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
108 }
109
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)110 bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
111 const char *instruction_set) {
112 return calculate_odex_file_path_default(path, apk_path, instruction_set);
113 }
114
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)115 bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
116 return create_cache_path_default(path, src, instruction_set);
117 }
118
force_compile_without_image()119 bool force_compile_without_image() {
120 return false;
121 }
122
get_full_path(const std::string & path)123 static std::string get_full_path(const std::string& path) {
124 return StringPrintf("%s/%s", kTestPath.c_str(), path.c_str());
125 }
126
mkdir(const std::string & path,uid_t owner,gid_t group,mode_t mode)127 static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
128 const std::string fullPath = get_full_path(path);
129 EXPECT_EQ(::mkdir(fullPath.c_str(), mode), 0);
130 EXPECT_EQ(::chown(fullPath.c_str(), owner, group), 0);
131 EXPECT_EQ(::chmod(fullPath.c_str(), mode), 0);
132 }
133
create(const std::string & path,uid_t owner,gid_t group,mode_t mode)134 static int create(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
135 int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
136 EXPECT_NE(fd, -1);
137 EXPECT_EQ(::fchown(fd, owner, group), 0);
138 EXPECT_EQ(::fchmod(fd, mode), 0);
139 return fd;
140 }
141
create_with_content(const std::string & path,uid_t owner,gid_t group,mode_t mode,const std::string & content)142 static void create_with_content(const std::string& path, uid_t owner, gid_t group, mode_t mode,
143 const std::string& content) {
144 int fd = ::open(path.c_str(), O_RDWR | O_CREAT, mode);
145 EXPECT_NE(fd, -1);
146 EXPECT_TRUE(android::base::WriteStringToFd(content, fd));
147 EXPECT_EQ(::fchown(fd, owner, group), 0);
148 EXPECT_EQ(::fchmod(fd, mode), 0);
149 close(fd);
150 }
151
touch(const std::string & path,uid_t owner,gid_t group,mode_t mode)152 static void touch(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
153 EXPECT_EQ(::close(create(path.c_str(), owner, group, mode)), 0);
154 }
155
stat_gid(const char * path)156 static int stat_gid(const char* path) {
157 struct stat buf;
158 EXPECT_EQ(::stat(get_full_path(path).c_str(), &buf), 0);
159 return buf.st_gid;
160 }
161
stat_mode(const char * path)162 static int stat_mode(const char* path) {
163 struct stat buf;
164 EXPECT_EQ(::stat(get_full_path(path).c_str(), &buf), 0);
165 return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
166 }
167
exists(const std::string & path)168 static bool exists(const std::string& path) {
169 return ::access(get_full_path(path).c_str(), F_OK) == 0;
170 }
171
172 template <class Pred>
find_file(const char * path,Pred && pred)173 static bool find_file(const char* path, Pred&& pred) {
174 bool result = false;
175 auto d = opendir(path);
176 if (d == nullptr) {
177 return result;
178 }
179 struct dirent* de;
180 while ((de = readdir(d))) {
181 const char* name = de->d_name;
182 if (pred(name, de->d_type == DT_DIR)) {
183 result = true;
184 break;
185 }
186 }
187 closedir(d);
188 return result;
189 }
190
exists_renamed_deleted_dir(const std::string & rootDirectory)191 static bool exists_renamed_deleted_dir(const std::string& rootDirectory) {
192 return find_file((kTestPath + rootDirectory).c_str(), [](const std::string& name, bool is_dir) {
193 return is_dir && is_renamed_deleted_dir(name);
194 });
195 }
196
unlink_path(const std::string & path)197 static void unlink_path(const std::string& path) {
198 if (unlink(path.c_str()) < 0) {
199 PLOG(DEBUG) << "Failed to unlink " + path;
200 }
201 }
202
203 class ServiceTest : public testing::Test {
204 protected:
205 InstalldNativeService* service;
206 std::optional<std::string> testUuid;
207
SetUp()208 virtual void SetUp() {
209 setenv("ANDROID_LOG_TAGS", "*:v", 1);
210 android::base::InitLogging(nullptr);
211
212 service = new InstalldNativeService();
213 testUuid = kTestUuid;
214 system("rm -rf /data/local/tmp/user");
215 system("rm -rf /data/local/tmp/misc_ce");
216 system("rm -rf /data/local/tmp/misc_de");
217 system("mkdir -p /data/local/tmp/user/0");
218 system("mkdir -p /data/local/tmp/misc_ce/0/sdksandbox");
219 system("mkdir -p /data/local/tmp/misc_de/0/sdksandbox");
220 init_globals_from_data_and_root();
221 }
222
TearDown()223 virtual void TearDown() {
224 delete service;
225 system("rm -rf /data/local/tmp/user");
226 system("rm -rf /data/local/tmp/misc_ce");
227 system("rm -rf /data/local/tmp/misc_de");
228 }
229 };
230
TEST_F(ServiceTest,FixupAppData_Upgrade)231 TEST_F(ServiceTest, FixupAppData_Upgrade) {
232 LOG(INFO) << "FixupAppData_Upgrade";
233
234 mkdir("user/0/com.example", 10000, 10000, 0700);
235 mkdir("user/0/com.example/normal", 10000, 10000, 0700);
236 mkdir("user/0/com.example/cache", 10000, 10000, 0700);
237 touch("user/0/com.example/cache/file", 10000, 10000, 0700);
238
239 service->fixupAppData(testUuid, 0);
240
241 EXPECT_EQ(10000, stat_gid("user/0/com.example/normal"));
242 EXPECT_EQ(20000, stat_gid("user/0/com.example/cache"));
243 EXPECT_EQ(20000, stat_gid("user/0/com.example/cache/file"));
244
245 EXPECT_EQ(0700, stat_mode("user/0/com.example/normal"));
246 EXPECT_EQ(02771, stat_mode("user/0/com.example/cache"));
247 EXPECT_EQ(0700, stat_mode("user/0/com.example/cache/file"));
248 }
249
TEST_F(ServiceTest,FixupAppData_Moved)250 TEST_F(ServiceTest, FixupAppData_Moved) {
251 LOG(INFO) << "FixupAppData_Moved";
252
253 mkdir("user/0/com.example", 10000, 10000, 0700);
254 mkdir("user/0/com.example/foo", 10000, 10000, 0700);
255 touch("user/0/com.example/foo/file", 10000, 20000, 0700);
256 mkdir("user/0/com.example/bar", 10000, 20000, 0700);
257 touch("user/0/com.example/bar/file", 10000, 20000, 0700);
258
259 service->fixupAppData(testUuid, 0);
260
261 EXPECT_EQ(10000, stat_gid("user/0/com.example/foo"));
262 EXPECT_EQ(20000, stat_gid("user/0/com.example/foo/file"));
263 EXPECT_EQ(10000, stat_gid("user/0/com.example/bar"));
264 EXPECT_EQ(10000, stat_gid("user/0/com.example/bar/file"));
265
266 service->fixupAppData(testUuid, FLAG_FORCE);
267
268 EXPECT_EQ(10000, stat_gid("user/0/com.example/foo"));
269 EXPECT_EQ(10000, stat_gid("user/0/com.example/foo/file"));
270 EXPECT_EQ(10000, stat_gid("user/0/com.example/bar"));
271 EXPECT_EQ(10000, stat_gid("user/0/com.example/bar/file"));
272 }
273
TEST_F(ServiceTest,DestroyUserData)274 TEST_F(ServiceTest, DestroyUserData) {
275 LOG(INFO) << "DestroyUserData";
276
277 mkdir("user/0/com.example", 10000, 10000, 0700);
278 mkdir("user/0/com.example/foo", 10000, 10000, 0700);
279 touch("user/0/com.example/foo/file", 10000, 20000, 0700);
280 mkdir("user/0/com.example/bar", 10000, 20000, 0700);
281 touch("user/0/com.example/bar/file", 10000, 20000, 0700);
282
283 EXPECT_TRUE(exists("user/0/com.example/foo"));
284 EXPECT_TRUE(exists("user/0/com.example/foo/file"));
285 EXPECT_TRUE(exists("user/0/com.example/bar"));
286 EXPECT_TRUE(exists("user/0/com.example/bar/file"));
287
288 service->destroyUserData(testUuid, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE);
289
290 EXPECT_FALSE(exists("user/0/com.example/foo"));
291 EXPECT_FALSE(exists("user/0/com.example/foo/file"));
292 EXPECT_FALSE(exists("user/0/com.example/bar"));
293 EXPECT_FALSE(exists("user/0/com.example/bar/file"));
294
295 EXPECT_FALSE(exists_renamed_deleted_dir("/user/0"));
296 }
297
TEST_F(ServiceTest,DestroyAppData)298 TEST_F(ServiceTest, DestroyAppData) {
299 LOG(INFO) << "DestroyAppData";
300
301 mkdir("user/0/com.example", 10000, 10000, 0700);
302 mkdir("user/0/com.example/foo", 10000, 10000, 0700);
303 touch("user/0/com.example/foo/file", 10000, 20000, 0700);
304 mkdir("user/0/com.example/bar", 10000, 20000, 0700);
305 touch("user/0/com.example/bar/file", 10000, 20000, 0700);
306
307 EXPECT_TRUE(exists("user/0/com.example/foo"));
308 EXPECT_TRUE(exists("user/0/com.example/foo/file"));
309 EXPECT_TRUE(exists("user/0/com.example/bar"));
310 EXPECT_TRUE(exists("user/0/com.example/bar/file"));
311
312 service->destroyAppData(testUuid, "com.example", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, 0);
313
314 EXPECT_FALSE(exists("user/0/com.example/foo"));
315 EXPECT_FALSE(exists("user/0/com.example/foo/file"));
316 EXPECT_FALSE(exists("user/0/com.example/bar"));
317 EXPECT_FALSE(exists("user/0/com.example/bar/file"));
318
319 EXPECT_FALSE(exists_renamed_deleted_dir("/user/0"));
320 }
321
TEST_F(ServiceTest,CleanupInvalidPackageDirs)322 TEST_F(ServiceTest, CleanupInvalidPackageDirs) {
323 LOG(INFO) << "CleanupInvalidPackageDirs";
324
325 std::string rootDirectoryPrefix[] = {"user/0", "misc_ce/0/sdksandbox", "misc_de/0/sdksandbox"};
326 for (auto& prefix : rootDirectoryPrefix) {
327 mkdir(prefix + "/5b14b6458a44==deleted==", 10000, 10000, 0700);
328 mkdir(prefix + "/5b14b6458a44==deleted==/foo", 10000, 10000, 0700);
329 touch(prefix + "/5b14b6458a44==deleted==/foo/file", 10000, 20000, 0700);
330 mkdir(prefix + "/5b14b6458a44==deleted==/bar", 10000, 20000, 0700);
331 touch(prefix + "/5b14b6458a44==deleted==/bar/file", 10000, 20000, 0700);
332
333 auto fd = create(prefix + "/5b14b6458a44==deleted==/bar/opened_file", 10000, 20000, 0700);
334
335 mkdir(prefix + "/b14b6458a44NOTdeleted", 10000, 10000, 0700);
336 mkdir(prefix + "/b14b6458a44NOTdeleted/foo", 10000, 10000, 0700);
337 touch(prefix + "/b14b6458a44NOTdeleted/foo/file", 10000, 20000, 0700);
338 mkdir(prefix + "/b14b6458a44NOTdeleted/bar", 10000, 20000, 0700);
339 touch(prefix + "/b14b6458a44NOTdeleted/bar/file", 10000, 20000, 0700);
340
341 mkdir(prefix + "/com.example", 10000, 10000, 0700);
342 mkdir(prefix + "/com.example/foo", 10000, 10000, 0700);
343 touch(prefix + "/com.example/foo/file", 10000, 20000, 0700);
344 mkdir(prefix + "/com.example/bar", 10000, 20000, 0700);
345 touch(prefix + "/com.example/bar/file", 10000, 20000, 0700);
346
347 mkdir(prefix + "/==deleted==", 10000, 10000, 0700);
348 mkdir(prefix + "/==deleted==/foo", 10000, 10000, 0700);
349 touch(prefix + "/==deleted==/foo/file", 10000, 20000, 0700);
350 mkdir(prefix + "/==deleted==/bar", 10000, 20000, 0700);
351 touch(prefix + "/==deleted==/bar/file", 10000, 20000, 0700);
352
353 EXPECT_TRUE(exists(prefix + "/5b14b6458a44==deleted==/foo"));
354 EXPECT_TRUE(exists(prefix + "/5b14b6458a44==deleted==/foo/file"));
355 EXPECT_TRUE(exists(prefix + "/5b14b6458a44==deleted==/bar"));
356 EXPECT_TRUE(exists(prefix + "/5b14b6458a44==deleted==/bar/file"));
357 EXPECT_TRUE(exists(prefix + "/5b14b6458a44==deleted==/bar/opened_file"));
358
359 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/foo"));
360 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/foo/file"));
361 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/bar"));
362 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/bar/file"));
363
364 EXPECT_TRUE(exists(prefix + "/com.example/foo"));
365 EXPECT_TRUE(exists(prefix + "/com.example/foo/file"));
366 EXPECT_TRUE(exists(prefix + "/com.example/bar"));
367 EXPECT_TRUE(exists(prefix + "/com.example/bar/file"));
368
369 EXPECT_TRUE(exists(prefix + "/==deleted==/foo"));
370 EXPECT_TRUE(exists(prefix + "/==deleted==/foo/file"));
371 EXPECT_TRUE(exists(prefix + "/==deleted==/bar"));
372 EXPECT_TRUE(exists(prefix + "/==deleted==/bar/file"));
373
374 EXPECT_TRUE(exists_renamed_deleted_dir("/" + prefix));
375
376 service->cleanupInvalidPackageDirs(testUuid, 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE);
377
378 EXPECT_EQ(::close(fd), 0);
379
380 EXPECT_FALSE(exists(prefix + "/5b14b6458a44==deleted==/foo"));
381 EXPECT_FALSE(exists(prefix + "/5b14b6458a44==deleted==/foo/file"));
382 EXPECT_FALSE(exists(prefix + "/5b14b6458a44==deleted==/bar"));
383 EXPECT_FALSE(exists(prefix + "/5b14b6458a44==deleted==/bar/file"));
384 EXPECT_FALSE(exists(prefix + "/5b14b6458a44==deleted==/bar/opened_file"));
385
386 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/foo"));
387 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/foo/file"));
388 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/bar"));
389 EXPECT_TRUE(exists(prefix + "/b14b6458a44NOTdeleted/bar/file"));
390
391 EXPECT_TRUE(exists(prefix + "/com.example/foo"));
392 EXPECT_TRUE(exists(prefix + "/com.example/foo/file"));
393 EXPECT_TRUE(exists(prefix + "/com.example/bar"));
394 EXPECT_TRUE(exists(prefix + "/com.example/bar/file"));
395
396 EXPECT_FALSE(exists(prefix + "/==deleted==/foo"));
397 EXPECT_FALSE(exists(prefix + "/==deleted==/foo/file"));
398 EXPECT_FALSE(exists(prefix + "/==deleted==/bar"));
399 EXPECT_FALSE(exists(prefix + "/==deleted==/bar/file"));
400
401 EXPECT_FALSE(exists_renamed_deleted_dir(prefix));
402 }
403 }
404
TEST_F(ServiceTest,HashSecondaryDex)405 TEST_F(ServiceTest, HashSecondaryDex) {
406 LOG(INFO) << "HashSecondaryDex";
407
408 mkdir("user/0/com.example", 10000, 10000, 0700);
409 mkdir("user/0/com.example/foo", 10000, 10000, 0700);
410 touch("user/0/com.example/foo/file", 10000, 20000, 0700);
411
412 std::vector<uint8_t> result;
413 std::string dexPath = get_full_path("user/0/com.example/foo/file");
414 EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
415 dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
416
417 EXPECT_EQ(result.size(), 32U);
418
419 std::ostringstream output;
420 output << std::hex << std::setfill('0');
421 for (auto b : result) {
422 output << std::setw(2) << +b;
423 }
424
425 // This is the SHA256 of an empty string (sha256sum /dev/null)
426 EXPECT_EQ(output.str(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
427 }
428
TEST_F(ServiceTest,HashSecondaryDex_NoSuch)429 TEST_F(ServiceTest, HashSecondaryDex_NoSuch) {
430 LOG(INFO) << "HashSecondaryDex_NoSuch";
431
432 std::vector<uint8_t> result;
433 std::string dexPath = get_full_path("user/0/com.example/foo/file");
434 EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
435 dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
436
437 EXPECT_EQ(result.size(), 0U);
438 }
439
TEST_F(ServiceTest,HashSecondaryDex_Unreadable)440 TEST_F(ServiceTest, HashSecondaryDex_Unreadable) {
441 LOG(INFO) << "HashSecondaryDex_Unreadable";
442
443 mkdir("user/0/com.example", 10000, 10000, 0700);
444 mkdir("user/0/com.example/foo", 10000, 10000, 0700);
445 touch("user/0/com.example/foo/file", 10000, 20000, 0300);
446
447 std::vector<uint8_t> result;
448 std::string dexPath = get_full_path("user/0/com.example/foo/file");
449 EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
450 dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
451
452 EXPECT_EQ(result.size(), 0U);
453 }
454
TEST_F(ServiceTest,HashSecondaryDex_WrongApp)455 TEST_F(ServiceTest, HashSecondaryDex_WrongApp) {
456 LOG(INFO) << "HashSecondaryDex_WrongApp";
457
458 mkdir("user/0/com.example", 10000, 10000, 0700);
459 mkdir("user/0/com.example/foo", 10000, 10000, 0700);
460 touch("user/0/com.example/foo/file", 10000, 20000, 0700);
461
462 std::vector<uint8_t> result;
463 std::string dexPath = get_full_path("user/0/com.example/foo/file");
464 EXPECT_BINDER_FAIL(service->hashSecondaryDexFile(
465 dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result));
466 }
467
TEST_F(ServiceTest,CalculateOat)468 TEST_F(ServiceTest, CalculateOat) {
469 char buf[PKG_PATH_MAX];
470
471 EXPECT_TRUE(calculate_oat_file_path(buf, "/path/to/oat", "/path/to/file.apk", "isa"));
472 EXPECT_EQ("/path/to/oat/isa/file.odex", std::string(buf));
473
474 EXPECT_FALSE(calculate_oat_file_path(buf, "/path/to/oat", "/path/to/file", "isa"));
475 EXPECT_FALSE(calculate_oat_file_path(buf, "/path/to/oat", "file", "isa"));
476 }
477
TEST_F(ServiceTest,CalculateOdex)478 TEST_F(ServiceTest, CalculateOdex) {
479 char buf[PKG_PATH_MAX];
480
481 EXPECT_TRUE(calculate_odex_file_path(buf, "/path/to/file.apk", "isa"));
482 EXPECT_EQ("/path/to/oat/isa/file.odex", std::string(buf));
483 }
484
TEST_F(ServiceTest,CalculateCache)485 TEST_F(ServiceTest, CalculateCache) {
486 char buf[PKG_PATH_MAX];
487
488 EXPECT_TRUE(create_cache_path(buf, "/path/to/file.apk", "isa"));
489 EXPECT_EQ("/data/dalvik-cache/isa/path@[email protected]@classes.dex", std::string(buf));
490 }
TEST_F(ServiceTest,GetAppSizeManualForMedia)491 TEST_F(ServiceTest, GetAppSizeManualForMedia) {
492 struct stat s;
493
494 std::string externalPicDir =
495 StringPrintf("%s/Pictures", create_data_media_path(nullptr, 0).c_str());
496 if (stat(externalPicDir.c_str(), &s) == 0) {
497 // fetch the appId from the uid of the external storage owning app
498 int32_t externalStorageAppId = multiuser_get_app_id(s.st_uid);
499 // Fetch Package Name for the external storage owning app uid
500 std::string pkg = get_package_name(s.st_uid);
501
502 std::vector<int64_t> externalStorageSize, externalStorageSizeAfterAddingExternalFile;
503 std::vector<int64_t> ceDataInodes;
504
505 std::vector<std::string> codePaths;
506 std::vector<std::string> packageNames;
507 // set up parameters
508 packageNames.push_back(pkg);
509 ceDataInodes.push_back(0);
510 // initialise the mounts
511 service->invalidateMounts();
512 // call the getAppSize to get the current size of the external storage owning app
513 service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
514 externalStorageAppId, ceDataInodes, codePaths, &externalStorageSize);
515 // add a file with 20MB size to the external storage
516 std::string externalFileLocation =
517 StringPrintf("%s/Pictures/%s", getenv("EXTERNAL_STORAGE"), "External.jpg");
518 std::string externalFileContentCommand =
519 StringPrintf("dd if=/dev/zero of=%s bs=1M count=20", externalFileLocation.c_str());
520 system(externalFileContentCommand.c_str());
521 // call the getAppSize again to get the new size of the external storage owning app
522 service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
523 externalStorageAppId, ceDataInodes, codePaths,
524 &externalStorageSizeAfterAddingExternalFile);
525 // check that the size before adding the file and after should be the same, as the app size
526 // is not changed.
527 for (size_t i = 0; i < externalStorageSize.size(); i++) {
528 ASSERT_TRUE(externalStorageSize[i] == externalStorageSizeAfterAddingExternalFile[i]);
529 }
530 // remove the external file
531 std::string removeCommand = StringPrintf("rm -f %s", externalFileLocation.c_str());
532 system(removeCommand.c_str());
533 }
534 }
535
TEST_F(ServiceTest,GetAppSizeWrongSizes)536 TEST_F(ServiceTest, GetAppSizeWrongSizes) {
537 int32_t externalStorageAppId = -1;
538 std::vector<int64_t> externalStorageSize;
539
540 std::vector<std::string> codePaths;
541 std::vector<std::string> packageNames = {"package1", "package2"};
542 std::vector<int64_t> ceDataInodes = {0};
543
544 EXPECT_BINDER_FAIL(service->getAppSize(std::nullopt, packageNames, 0,
545 InstalldNativeService::FLAG_USE_QUOTA,
546 externalStorageAppId, ceDataInodes, codePaths,
547 &externalStorageSize));
548 }
549
550 class FsverityTest : public ServiceTest {
551 protected:
createFsveritySetupAuthToken(const std::string & path,int open_mode,sp<IFsveritySetupAuthToken> * _aidl_return)552 binder::Status createFsveritySetupAuthToken(const std::string& path, int open_mode,
553 sp<IFsveritySetupAuthToken>* _aidl_return) {
554 unique_fd ufd(open(path.c_str(), open_mode));
555 EXPECT_GE(ufd.get(), 0) << "open failed: " << strerror(errno);
556 ParcelFileDescriptor rfd(std::move(ufd));
557 return service->createFsveritySetupAuthToken(std::move(rfd), kTestAppId, _aidl_return);
558 }
559 };
560
TEST_F(FsverityTest,enableFsverity)561 TEST_F(FsverityTest, enableFsverity) {
562 const std::string path = kTestPath + "/foo";
563 create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
564 UniqueFile raii(/*fd=*/-1, path, &unlink_path);
565
566 // Expect to fs-verity setup to succeed
567 sp<IFsveritySetupAuthToken> authToken;
568 binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
569 EXPECT_TRUE(status.isOk());
570 EXPECT_TRUE(authToken != nullptr);
571
572 // Verity auth token works to enable fs-verity
573 int32_t errno_local;
574 status = service->enableFsverity(authToken, path, "fake.package.name", &errno_local);
575 EXPECT_TRUE(status.isOk());
576 EXPECT_EQ(errno_local, 0);
577 }
578
TEST_F(FsverityTest,enableFsverity_nullAuthToken)579 TEST_F(FsverityTest, enableFsverity_nullAuthToken) {
580 const std::string path = kTestPath + "/foo";
581 create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
582 UniqueFile raii(/*fd=*/-1, path, &unlink_path);
583
584 // Verity null auth token fails
585 sp<IFsveritySetupAuthToken> authToken;
586 int32_t errno_local;
587 binder::Status status =
588 service->enableFsverity(authToken, path, "fake.package.name", &errno_local);
589 EXPECT_FALSE(status.isOk());
590 }
591
TEST_F(FsverityTest,enableFsverity_differentFile)592 TEST_F(FsverityTest, enableFsverity_differentFile) {
593 const std::string path = kTestPath + "/foo";
594 create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
595 UniqueFile raii(/*fd=*/-1, path, &unlink_path);
596
597 // Expect to fs-verity setup to succeed
598 sp<IFsveritySetupAuthToken> authToken;
599 binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
600 EXPECT_TRUE(status.isOk());
601 EXPECT_TRUE(authToken != nullptr);
602
603 // Verity auth token does not work for a different file
604 const std::string anotherPath = kTestPath + "/bar";
605 ASSERT_TRUE(android::base::WriteStringToFile("content", anotherPath));
606 UniqueFile raii2(/*fd=*/-1, anotherPath, &unlink_path);
607 int32_t errno_local;
608 status = service->enableFsverity(authToken, anotherPath, "fake.package.name", &errno_local);
609 EXPECT_TRUE(status.isOk());
610 EXPECT_NE(errno_local, 0);
611 }
612
TEST_F(FsverityTest,enableFsverity_errnoBeforeAuthenticated)613 TEST_F(FsverityTest, enableFsverity_errnoBeforeAuthenticated) {
614 const std::string path = kTestPath + "/foo";
615 create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
616 UniqueFile raii(/*fd=*/-1, path, &unlink_path);
617
618 // Expect to fs-verity setup to succeed
619 sp<IFsveritySetupAuthToken> authToken;
620 binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
621 EXPECT_TRUE(status.isOk());
622 EXPECT_TRUE(authToken != nullptr);
623
624 // Verity errno before the fd authentication is constant (EPERM)
625 int32_t errno_local;
626 status = service->enableFsverity(authToken, path + "-non-exist", "fake.package.name",
627 &errno_local);
628 EXPECT_TRUE(status.isOk());
629 EXPECT_EQ(errno_local, EPERM);
630 }
631
TEST_F(FsverityTest,createFsveritySetupAuthToken_ReadonlyFdDoesNotAuthenticate)632 TEST_F(FsverityTest, createFsveritySetupAuthToken_ReadonlyFdDoesNotAuthenticate) {
633 const std::string path = kTestPath + "/foo";
634 create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
635 UniqueFile raii(/*fd=*/-1, path, &unlink_path);
636
637 // Expect the fs-verity setup to fail
638 sp<IFsveritySetupAuthToken> authToken;
639 binder::Status status = createFsveritySetupAuthToken(path, O_RDONLY, &authToken);
640 EXPECT_FALSE(status.isOk());
641 }
642
TEST_F(FsverityTest,createFsveritySetupAuthToken_UnownedFile)643 TEST_F(FsverityTest, createFsveritySetupAuthToken_UnownedFile) {
644 const std::string path = kTestPath + "/foo";
645 // Simulate world-writable file owned by another app
646 create_with_content(path, kTestAppUid + 1, kTestAppUid + 1, 0666, "content");
647 UniqueFile raii(/*fd=*/-1, path, &unlink_path);
648
649 // Expect the fs-verity setup to fail
650 sp<IFsveritySetupAuthToken> authToken;
651 binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
652 EXPECT_FALSE(status.isOk());
653 }
654
mkdirs(const std::string & path,mode_t mode)655 static bool mkdirs(const std::string& path, mode_t mode) {
656 struct stat sb;
657 if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
658 return true;
659 }
660
661 if (!mkdirs(android::base::Dirname(path), mode)) {
662 return false;
663 }
664
665 if (::mkdir(path.c_str(), mode) != 0) {
666 PLOG(DEBUG) << "Failed to create folder " << path;
667 return false;
668 }
669 return true;
670 }
671
672 class AppDataSnapshotTest : public testing::Test {
673 private:
674 std::string rollback_ce_base_dir;
675 std::string rollback_de_base_dir;
676
677 protected:
678 InstalldNativeService* service;
679
680 std::string fake_package_ce_path;
681 std::string fake_package_de_path;
682
SetUp()683 virtual void SetUp() {
684 setenv("ANDROID_LOG_TAGS", "*:v", 1);
685 android::base::InitLogging(nullptr);
686
687 service = new InstalldNativeService();
688 ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
689
690 init_globals_from_data_and_root();
691
692 rollback_ce_base_dir = create_data_misc_ce_rollback_base_path("TEST", 0);
693 rollback_de_base_dir = create_data_misc_de_rollback_base_path("TEST", 0);
694
695 fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
696 fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
697
698 ASSERT_TRUE(mkdirs(rollback_ce_base_dir, 0700));
699 ASSERT_TRUE(mkdirs(rollback_de_base_dir, 0700));
700 ASSERT_TRUE(mkdirs(fake_package_ce_path, 0700));
701 ASSERT_TRUE(mkdirs(fake_package_de_path, 0700));
702 }
703
TearDown()704 virtual void TearDown() {
705 ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_ce_base_dir, true));
706 ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_de_base_dir, true));
707 ASSERT_EQ(0, delete_dir_contents(fake_package_ce_path, true));
708 ASSERT_EQ(0, delete_dir_contents(fake_package_de_path, true));
709
710 delete service;
711 ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user/0", true));
712 }
713 };
714
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot)715 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot) {
716 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 37);
717 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 37);
718
719 ASSERT_TRUE(android::base::WriteStringToFile(
720 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
721 0700, 10000, 20000, false /* follow_symlinks */));
722 ASSERT_TRUE(android::base::WriteStringToFile(
723 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
724 0700, 10000, 20000, false /* follow_symlinks */));
725
726 // Request a snapshot of the CE content but not the DE content.
727 int64_t ce_snapshot_inode;
728 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
729 "com.foo", 0, 37, FLAG_STORAGE_CE, &ce_snapshot_inode));
730 struct stat buf;
731 memset(&buf, 0, sizeof(buf));
732 ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
733 ASSERT_EQ(ce_snapshot_inode, (int64_t) buf.st_ino);
734
735 std::string ce_content, de_content;
736 // At this point, we should have the CE content but not the DE content.
737 ASSERT_TRUE(android::base::ReadFileToString(
738 rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
739 ASSERT_FALSE(android::base::ReadFileToString(
740 rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
741 ASSERT_EQ("TEST_CONTENT_CE", ce_content);
742
743 // Modify the CE content, so we can assert later that it's reflected
744 // in the snapshot.
745 ASSERT_TRUE(android::base::WriteStringToFile(
746 "TEST_CONTENT_CE_MODIFIED", fake_package_ce_path + "/file1",
747 0700, 10000, 20000, false /* follow_symlinks */));
748
749 // Request a snapshot of the DE content but not the CE content.
750 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
751 "com.foo", 0, 37, FLAG_STORAGE_DE, &ce_snapshot_inode));
752 // Only DE content snapshot was requested.
753 ASSERT_EQ(ce_snapshot_inode, 0);
754
755 // At this point, both the CE as well as the DE content should be fully
756 // populated.
757 ASSERT_TRUE(android::base::ReadFileToString(
758 rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
759 ASSERT_TRUE(android::base::ReadFileToString(
760 rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
761 ASSERT_EQ("TEST_CONTENT_CE", ce_content);
762 ASSERT_EQ("TEST_CONTENT_DE", de_content);
763
764 // Modify the DE content, so we can assert later that it's reflected
765 // in our final snapshot.
766 ASSERT_TRUE(android::base::WriteStringToFile(
767 "TEST_CONTENT_DE_MODIFIED", fake_package_de_path + "/file1",
768 0700, 10000, 20000, false /* follow_symlinks */));
769
770 // Request a snapshot of both the CE as well as the DE content.
771 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
772 "com.foo", 0, 37, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
773
774 ASSERT_TRUE(android::base::ReadFileToString(
775 rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
776 ASSERT_TRUE(android::base::ReadFileToString(
777 rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
778 ASSERT_EQ("TEST_CONTENT_CE_MODIFIED", ce_content);
779 ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content);
780 }
781
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_TwoSnapshotsWithTheSameId)782 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_TwoSnapshotsWithTheSameId) {
783 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 67);
784 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 67);
785
786 auto another_fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.bar");
787 auto another_fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.bar");
788
789 // Since this test sets up data for another package, some bookkeeping is required.
790 auto deleter = [&]() {
791 ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_ce_path, true));
792 ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_de_path, true));
793 };
794 auto scope_guard = android::base::make_scope_guard(deleter);
795
796 ASSERT_TRUE(mkdirs(another_fake_package_ce_path, 0700));
797 ASSERT_TRUE(mkdirs(another_fake_package_de_path, 0700));
798
799 ASSERT_TRUE(android::base::WriteStringToFile(
800 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
801 0700, 10000, 20000, false /* follow_symlinks */));
802 ASSERT_TRUE(android::base::WriteStringToFile(
803 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
804 0700, 10000, 20000, false /* follow_symlinks */));
805 ASSERT_TRUE(android::base::WriteStringToFile(
806 "ANOTHER_TEST_CONTENT_CE", another_fake_package_ce_path + "/file1",
807 0700, 10000, 20000, false /* follow_symlinks */));
808 ASSERT_TRUE(android::base::WriteStringToFile(
809 "ANOTHER_TEST_CONTENT_DE", another_fake_package_de_path + "/file1",
810 0700, 10000, 20000, false /* follow_symlinks */));
811
812 // Request snapshot for the package com.foo.
813 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
814 "com.foo", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
815 // Now request snapshot with the same id for the package com.bar
816 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
817 "com.bar", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
818
819 // Check that both snapshots have correct data in them.
820 std::string com_foo_ce_content, com_foo_de_content;
821 std::string com_bar_ce_content, com_bar_de_content;
822 ASSERT_TRUE(android::base::ReadFileToString(
823 rollback_ce_dir + "/com.foo/file1", &com_foo_ce_content, false /* follow_symlinks */));
824 ASSERT_TRUE(android::base::ReadFileToString(
825 rollback_de_dir + "/com.foo/file1", &com_foo_de_content, false /* follow_symlinks */));
826 ASSERT_TRUE(android::base::ReadFileToString(
827 rollback_ce_dir + "/com.bar/file1", &com_bar_ce_content, false /* follow_symlinks */));
828 ASSERT_TRUE(android::base::ReadFileToString(
829 rollback_de_dir + "/com.bar/file1", &com_bar_de_content, false /* follow_symlinks */));
830 ASSERT_EQ("TEST_CONTENT_CE", com_foo_ce_content);
831 ASSERT_EQ("TEST_CONTENT_DE", com_foo_de_content);
832 ASSERT_EQ("ANOTHER_TEST_CONTENT_CE", com_bar_ce_content);
833 ASSERT_EQ("ANOTHER_TEST_CONTENT_DE", com_bar_de_content);
834 }
835
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_AppDataAbsent)836 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_AppDataAbsent) {
837 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 73);
838 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 73);
839
840 // Similuating app data absence.
841 ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_ce_path, true));
842 ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_de_path, true));
843
844 int64_t ce_snapshot_inode;
845 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
846 "com.foo", 0, 73, FLAG_STORAGE_CE, &ce_snapshot_inode));
847 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
848 "com.foo", 0, 73, FLAG_STORAGE_DE, nullptr));
849 // No CE content snapshot was performed.
850 ASSERT_EQ(ce_snapshot_inode, 0);
851
852 // The snapshot calls must succeed but there should be no snapshot
853 // created.
854 struct stat sb;
855 ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
856 ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
857 }
858
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_ClearsExistingSnapshot)859 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
860 auto rollback_ce_dir = create_data_misc_ce_rollback_package_path("TEST", 0, 13, "com.foo");
861 auto rollback_de_dir = create_data_misc_de_rollback_package_path("TEST", 0, 13, "com.foo");
862
863 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
864 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
865
866 // Simulate presence of an existing snapshot
867 ASSERT_TRUE(android::base::WriteStringToFile(
868 "TEST_CONTENT_CE", rollback_ce_dir + "/file1",
869 0700, 10000, 20000, false /* follow_symlinks */));
870 ASSERT_TRUE(android::base::WriteStringToFile(
871 "TEST_CONTENT_DE", rollback_de_dir + "/file1",
872 0700, 10000, 20000, false /* follow_symlinks */));
873
874 // Create app data.
875 ASSERT_TRUE(android::base::WriteStringToFile(
876 "TEST_CONTENT_2_CE", fake_package_ce_path + "/file2",
877 0700, 10000, 20000, false /* follow_symlinks */));
878 ASSERT_TRUE(android::base::WriteStringToFile(
879 "TEST_CONTENT_2_DE", fake_package_de_path + "/file2",
880 0700, 10000, 20000, false /* follow_symlinks */));
881
882 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
883 "com.foo", 0, 13, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
884
885 // Previous snapshot (with data for file1) must be cleared.
886 struct stat sb;
887 ASSERT_EQ(-1, stat((rollback_ce_dir + "/file1").c_str(), &sb));
888 ASSERT_EQ(-1, stat((rollback_de_dir + "/file1").c_str(), &sb));
889 // New snapshot (with data for file2) must be present.
890 ASSERT_NE(-1, stat((rollback_ce_dir + "/file2").c_str(), &sb));
891 ASSERT_NE(-1, stat((rollback_de_dir + "/file2").c_str(), &sb));
892 }
893
TEST_F(AppDataSnapshotTest,SnapshotAppData_WrongVolumeUuid)894 TEST_F(AppDataSnapshotTest, SnapshotAppData_WrongVolumeUuid) {
895 // Setup rollback folders to make sure that fails due to wrong volumeUuid being
896 // passed, not because of some other reason.
897 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 17);
898 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 17);
899
900 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
901 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
902
903 EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_optional<std::string>("FOO"),
904 "com.foo", 0, 17, FLAG_STORAGE_DE, nullptr));
905 }
906
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_ClearsCache)907 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsCache) {
908 auto fake_package_ce_cache_path = fake_package_ce_path + "/cache";
909 auto fake_package_ce_code_cache_path = fake_package_ce_path + "/code_cache";
910 auto fake_package_de_cache_path = fake_package_de_path + "/cache";
911 auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
912
913 ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 0700));
914 ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 0700));
915 ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 0700));
916 ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 0700));
917
918 ASSERT_TRUE(android::base::WriteStringToFile(
919 "TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
920 0700, 10000, 20000, false /* follow_symlinks */));
921 ASSERT_TRUE(android::base::WriteStringToFile(
922 "TEST_CONTENT_CE", fake_package_ce_code_cache_path + "/file1",
923 0700, 10000, 20000, false /* follow_symlinks */));
924 ASSERT_TRUE(android::base::WriteStringToFile(
925 "TEST_CONTENT_DE", fake_package_de_cache_path + "/file1",
926 0700, 10000, 20000, false /* follow_symlinks */));
927 ASSERT_TRUE(android::base::WriteStringToFile(
928 "TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
929 0700, 10000, 20000, false /* follow_symlinks */));
930 ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_optional<std::string>("TEST"),
931 "com.foo", 0, 23, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
932 // The snapshot call must clear cache.
933 struct stat sb;
934 ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
935 ASSERT_EQ(-1, stat((fake_package_ce_code_cache_path + "/file1").c_str(), &sb));
936 ASSERT_EQ(-1, stat((fake_package_de_cache_path + "/file1").c_str(), &sb));
937 ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
938 }
939
TEST_F(AppDataSnapshotTest,RestoreAppDataSnapshot)940 TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot) {
941 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 239);
942 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 239);
943
944 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
945 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
946
947 // Write contents to the rollback location. We'll write the same files to the
948 // app data location and make sure the restore has overwritten them.
949 ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
950 ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
951 ASSERT_TRUE(android::base::WriteStringToFile(
952 "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
953 0700, 10000, 20000, false /* follow_symlinks */));
954 ASSERT_TRUE(android::base::WriteStringToFile(
955 "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
956 0700, 10000, 20000, false /* follow_symlinks */));
957 ASSERT_TRUE(android::base::WriteStringToFile(
958 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
959 0700, 10000, 20000, false /* follow_symlinks */));
960 ASSERT_TRUE(android::base::WriteStringToFile(
961 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
962 0700, 10000, 20000, false /* follow_symlinks */));
963
964 ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_optional<std::string>("TEST"),
965 "com.foo", 10000, "", 0, 239, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
966
967 std::string ce_content, de_content;
968 ASSERT_TRUE(android::base::ReadFileToString(
969 fake_package_ce_path + "/file1", &ce_content, false /* follow_symlinks */));
970 ASSERT_TRUE(android::base::ReadFileToString(
971 fake_package_de_path + "/file1", &de_content, false /* follow_symlinks */));
972 ASSERT_EQ("CE_RESTORE_CONTENT", ce_content);
973 ASSERT_EQ("DE_RESTORE_CONTENT", de_content);
974 }
975
TEST_F(AppDataSnapshotTest,CreateSnapshotThenDestroyIt)976 TEST_F(AppDataSnapshotTest, CreateSnapshotThenDestroyIt) {
977 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 57);
978 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 57);
979
980 // Prepare data for snapshot.
981 ASSERT_TRUE(android::base::WriteStringToFile(
982 "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
983 0700, 10000, 20000, false /* follow_symlinks */));
984 ASSERT_TRUE(android::base::WriteStringToFile(
985 "TEST_CONTENT_DE", fake_package_de_path + "/file1",
986 0700, 10000, 20000, false /* follow_symlinks */));
987
988 int64_t ce_snapshot_inode;
989 // Request a snapshot of both the CE as well as the DE content.
990 ASSERT_TRUE(service->snapshotAppData(std::make_optional<std::string>("TEST"),
991 "com.foo", 0, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
992 // Because CE data snapshot was requested, ce_snapshot_inode can't be null.
993 ASSERT_NE(0, ce_snapshot_inode);
994 // Check snapshot is there.
995 struct stat sb;
996 ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
997 ASSERT_EQ(0, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
998
999
1000 ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_optional<std::string>("TEST"),
1001 "com.foo", 0, ce_snapshot_inode, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
1002 // Check snapshot is deleted.
1003 ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
1004 ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
1005 }
1006
TEST_F(AppDataSnapshotTest,DestroyAppDataSnapshot_CeSnapshotInodeIsZero)1007 TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
1008 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 1543);
1009 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 1543);
1010
1011 // Create a snapshot
1012 ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
1013 ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
1014 ASSERT_TRUE(android::base::WriteStringToFile(
1015 "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
1016 0700, 10000, 20000, false /* follow_symlinks */));
1017 ASSERT_TRUE(android::base::WriteStringToFile(
1018 "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
1019 0700, 10000, 20000, false /* follow_symlinks */));
1020
1021 ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_optional<std::string>("TEST"),
1022 "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
1023
1024 // Check snapshot is deleted.
1025 struct stat sb;
1026 ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
1027 ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
1028
1029 // Check that deleting already deleted snapshot is no-op.
1030 ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_optional<std::string>("TEST"),
1031 "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
1032 }
1033
TEST_F(AppDataSnapshotTest,DestroyAppDataSnapshot_WrongVolumeUuid)1034 TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
1035 // Setup rollback data to make sure that test fails due to wrong volumeUuid
1036 // being passed, not because of some other reason.
1037 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 43);
1038 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 43);
1039
1040 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
1041 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
1042
1043 ASSERT_FALSE(service->destroyAppDataSnapshot(std::make_optional<std::string>("BAR"),
1044 "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk());
1045 }
1046
TEST_F(AppDataSnapshotTest,DestroyCeSnapshotsNotSpecified)1047 TEST_F(AppDataSnapshotTest, DestroyCeSnapshotsNotSpecified) {
1048 auto rollback_ce_dir_in_1 = create_data_misc_ce_rollback_path("TEST", 0, 1543);
1049 auto rollback_ce_dir_in_2 = create_data_misc_ce_rollback_path("TEST", 0, 77);
1050 auto rollback_ce_dir_out_1 = create_data_misc_ce_rollback_path("TEST", 0, 1500);
1051 auto rollback_ce_dir_out_2 = create_data_misc_ce_rollback_path("TEST", 0, 2);
1052
1053 // Create snapshots
1054 ASSERT_TRUE(mkdirs(rollback_ce_dir_in_1 + "/com.foo/", 0700));
1055 ASSERT_TRUE(android::base::WriteStringToFile(
1056 "CE_RESTORE_CONTENT", rollback_ce_dir_in_1 + "/com.foo/file1",
1057 0700, 10000, 20000, false /* follow_symlinks */));
1058
1059 ASSERT_TRUE(mkdirs(rollback_ce_dir_in_2 + "/com.foo/", 0700));
1060 ASSERT_TRUE(android::base::WriteStringToFile(
1061 "CE_RESTORE_CONTENT", rollback_ce_dir_in_2 + "/com.foo/file1",
1062 0700, 10000, 20000, false /* follow_symlinks */));
1063
1064 ASSERT_TRUE(mkdirs(rollback_ce_dir_out_1 + "/com.foo/", 0700));
1065 ASSERT_TRUE(android::base::WriteStringToFile(
1066 "CE_RESTORE_CONTENT", rollback_ce_dir_out_1 + "/com.foo/file1",
1067 0700, 10000, 20000, false /* follow_symlinks */));
1068
1069 ASSERT_TRUE(mkdirs(rollback_ce_dir_out_2 + "/com.foo/", 0700));
1070 ASSERT_TRUE(android::base::WriteStringToFile(
1071 "CE_RESTORE_CONTENT", rollback_ce_dir_out_2 + "/com.foo/file1",
1072 0700, 10000, 20000, false /* follow_symlinks */));
1073
1074 ASSERT_TRUE(service->destroyCeSnapshotsNotSpecified(
1075 std::make_optional<std::string>("TEST"), 0, { 1543, 77 }).isOk());
1076
1077 // Check only snapshots not specified are deleted.
1078 struct stat sb;
1079 ASSERT_EQ(0, stat((rollback_ce_dir_in_1 + "/com.foo").c_str(), &sb));
1080 ASSERT_EQ(0, stat((rollback_ce_dir_in_2 + "/com.foo").c_str(), &sb));
1081 ASSERT_EQ(-1, stat((rollback_ce_dir_out_1 + "/com.foo").c_str(), &sb));
1082 ASSERT_EQ(ENOENT, errno);
1083 ASSERT_EQ(-1, stat((rollback_ce_dir_out_2 + "/com.foo").c_str(), &sb));
1084 ASSERT_EQ(ENOENT, errno);
1085 }
1086
TEST_F(AppDataSnapshotTest,RestoreAppDataSnapshot_WrongVolumeUuid)1087 TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
1088 // Setup rollback data to make sure that fails due to wrong volumeUuid being
1089 // passed, not because of some other reason.
1090 auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 41);
1091 auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 41);
1092
1093 ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
1094 ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
1095
1096 EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_optional<std::string>("BAR"),
1097 "com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
1098 }
1099
1100 class SdkSandboxDataTest : public testing::Test {
1101 public:
CheckFileAccess(const std::string & path,uid_t uid,gid_t gid,mode_t mode)1102 void CheckFileAccess(const std::string& path, uid_t uid, gid_t gid, mode_t mode) {
1103 const auto fullPath = "/data/local/tmp/" + path;
1104 ASSERT_TRUE(exists(fullPath.c_str())) << "For path: " << fullPath;
1105 struct stat st;
1106 ASSERT_EQ(0, stat(fullPath.c_str(), &st));
1107 ASSERT_EQ(uid, st.st_uid) << "For path: " << fullPath;
1108 ASSERT_EQ(gid, st.st_gid) << "For path: " << fullPath;
1109 ASSERT_EQ(mode, st.st_mode) << "For path: " << fullPath;
1110 }
1111
exists(const char * path)1112 bool exists(const char* path) { return ::access(path, F_OK) == 0; }
1113
1114 // Creates a default CreateAppDataArgs object
createAppDataArgs(const std::string & packageName)1115 android::os::CreateAppDataArgs createAppDataArgs(const std::string& packageName) {
1116 android::os::CreateAppDataArgs args;
1117 args.uuid = kTestUuid;
1118 args.packageName = packageName;
1119 args.userId = kTestUserId;
1120 args.appId = kTestAppId;
1121 args.seInfo = "default";
1122 args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE | FLAG_STORAGE_SDK;
1123 return args;
1124 }
1125
reconcileSdkDataArgs(const std::string & packageName,const std::vector<std::string> & subDirNames)1126 android::os::ReconcileSdkDataArgs reconcileSdkDataArgs(
1127 const std::string& packageName, const std::vector<std::string>& subDirNames) {
1128 android::os::ReconcileSdkDataArgs args;
1129 args.uuid = kTestUuid;
1130 args.packageName = packageName;
1131 for (const auto& subDirName : subDirNames) {
1132 args.subDirNames.push_back(subDirName);
1133 }
1134 args.userId = kTestUserId;
1135 args.appId = kTestAppId;
1136 args.previousAppId = -1;
1137 args.seInfo = "default";
1138 args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
1139 return args;
1140 }
1141
1142 protected:
1143 InstalldNativeService* service;
1144
SetUp()1145 virtual void SetUp() {
1146 setenv("ANDROID_LOG_TAGS", "*:v", 1);
1147 android::base::InitLogging(nullptr);
1148
1149 service = new InstalldNativeService();
1150 clearAppData();
1151 ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
1152 ASSERT_TRUE(mkdirs("/data/local/tmp/user_de/0", 0700));
1153 ASSERT_TRUE(mkdirs("/data/local/tmp/misc_ce/0/sdksandbox", 0700));
1154 ASSERT_TRUE(mkdirs("/data/local/tmp/misc_de/0/sdksandbox", 0700));
1155
1156 init_globals_from_data_and_root();
1157 }
1158
TearDown()1159 virtual void TearDown() {
1160 delete service;
1161 clearAppData();
1162 }
1163
1164 private:
clearAppData()1165 void clearAppData() {
1166 ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user", true));
1167 ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user_de", true));
1168 ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/misc_ce", true));
1169 ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/misc_de", true));
1170 }
1171 };
1172
TEST_F(SdkSandboxDataTest,CreateAppData_CreatesSdkPackageData)1173 TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData) {
1174 android::os::CreateAppDataResult result;
1175 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1176
1177 // Create the app user data.
1178 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1179
1180 const std::string fooCePath = "misc_ce/0/sdksandbox/com.foo";
1181 CheckFileAccess(fooCePath, kSystemUid, kSystemUid, S_IFDIR | 0751);
1182
1183 const std::string fooDePath = "misc_de/0/sdksandbox/com.foo";
1184 CheckFileAccess(fooDePath, kSystemUid, kSystemUid, S_IFDIR | 0751);
1185 }
1186
TEST_F(SdkSandboxDataTest,CreateAppData_CreatesSdkPackageData_WithoutSdkFlag)1187 TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutSdkFlag) {
1188 android::os::CreateAppDataResult result;
1189 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1190 args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
1191
1192 // Create the app user data.
1193 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1194
1195 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1196 ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1197 }
1198
TEST_F(SdkSandboxDataTest,CreateAppData_CreatesSdkPackageData_WithoutSdkFlagDeletesExisting)1199 TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutSdkFlagDeletesExisting) {
1200 android::os::CreateAppDataResult result;
1201 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1202 // Create the app user data.
1203 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1204 ASSERT_TRUE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1205 ASSERT_TRUE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1206
1207 args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
1208 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1209 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1210 ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1211 }
1212
TEST_F(SdkSandboxDataTest,CreateAppData_CreatesSdkPackageData_WithoutDeFlag)1213 TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutDeFlag) {
1214 android::os::CreateAppDataResult result;
1215 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1216 args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_SDK;
1217
1218 // Create the app user data.
1219 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1220
1221 // Only CE paths should exist
1222 CheckFileAccess("misc_ce/0/sdksandbox/com.foo", kSystemUid, kSystemUid, S_IFDIR | 0751);
1223
1224 // DE paths should not exist
1225 ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1226 }
1227
TEST_F(SdkSandboxDataTest,CreateAppData_CreatesSdkPackageData_WithoutCeFlag)1228 TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutCeFlag) {
1229 android::os::CreateAppDataResult result;
1230 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1231 args.flags = FLAG_STORAGE_DE | FLAG_STORAGE_SDK;
1232
1233 // Create the app user data.
1234 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1235
1236 // CE paths should not exist
1237 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1238
1239 // Only DE paths should exist
1240 CheckFileAccess("misc_de/0/sdksandbox/com.foo", kSystemUid, kSystemUid, S_IFDIR | 0751);
1241 }
1242
TEST_F(SdkSandboxDataTest,ReconcileSdkData)1243 TEST_F(SdkSandboxDataTest, ReconcileSdkData) {
1244 android::os::ReconcileSdkDataArgs args =
1245 reconcileSdkDataArgs("com.foo", {"bar@random1", "baz@random2"});
1246
1247 // Create the sdk data.
1248 ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
1249
1250 const std::string barCePath = "misc_ce/0/sdksandbox/com.foo/bar@random1";
1251 CheckFileAccess(barCePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
1252 CheckFileAccess(barCePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
1253 S_IFDIR | S_ISGID | 0771);
1254 CheckFileAccess(barCePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
1255 S_IFDIR | S_ISGID | 0771);
1256
1257 const std::string bazCePath = "misc_ce/0/sdksandbox/com.foo/baz@random2";
1258 CheckFileAccess(bazCePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
1259 CheckFileAccess(bazCePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
1260 S_IFDIR | S_ISGID | 0771);
1261 CheckFileAccess(bazCePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
1262 S_IFDIR | S_ISGID | 0771);
1263
1264 const std::string barDePath = "misc_de/0/sdksandbox/com.foo/bar@random1";
1265 CheckFileAccess(barDePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
1266 CheckFileAccess(barDePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
1267 S_IFDIR | S_ISGID | 0771);
1268 CheckFileAccess(barDePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
1269 S_IFDIR | S_ISGID | 0771);
1270
1271 const std::string bazDePath = "misc_de/0/sdksandbox/com.foo/baz@random2";
1272 CheckFileAccess(bazDePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
1273 CheckFileAccess(bazDePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
1274 S_IFDIR | S_ISGID | 0771);
1275 CheckFileAccess(bazDePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
1276 S_IFDIR | S_ISGID | 0771);
1277 }
1278
TEST_F(SdkSandboxDataTest,ReconcileSdkData_ExtraCodeDirectoriesAreDeleted)1279 TEST_F(SdkSandboxDataTest, ReconcileSdkData_ExtraCodeDirectoriesAreDeleted) {
1280 android::os::ReconcileSdkDataArgs args =
1281 reconcileSdkDataArgs("com.foo", {"bar@random1", "baz@random2"});
1282
1283 // Create the sdksandbox data.
1284 ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
1285
1286 // Retry with different package name
1287 args.subDirNames[0] = "bar.diff@random1";
1288
1289 // Create the sdksandbox data again
1290 ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
1291
1292 // New directoris should exist
1293 CheckFileAccess("misc_ce/0/sdksandbox/com.foo/bar.diff@random1", kTestSdkSandboxUid, kNobodyUid,
1294 S_IFDIR | S_ISGID | 0700);
1295 CheckFileAccess("misc_ce/0/sdksandbox/com.foo/baz@random2", kTestSdkSandboxUid, kNobodyUid,
1296 S_IFDIR | S_ISGID | 0700);
1297 // Directory for old unreferred sdksandbox package name should be removed
1298 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/bar@random1"));
1299 }
1300
1301 class DestroyAppDataTest : public SdkSandboxDataTest {};
1302
TEST_F(DestroyAppDataTest,DestroySdkSandboxDataDirectories_WithCeAndDeFlag)1303 TEST_F(DestroyAppDataTest, DestroySdkSandboxDataDirectories_WithCeAndDeFlag) {
1304 android::os::CreateAppDataResult result;
1305 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1306 args.packageName = "com.foo";
1307 // Create the app user data.
1308 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1309 // Destroy the app user data.
1310 ASSERT_BINDER_SUCCESS(service->destroyAppData(args.uuid, args.packageName, args.userId,
1311 args.flags, result.ceDataInode));
1312 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1313 ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1314 }
1315
TEST_F(DestroyAppDataTest,DestroySdkSandboxDataDirectories_WithoutDeFlag)1316 TEST_F(DestroyAppDataTest, DestroySdkSandboxDataDirectories_WithoutDeFlag) {
1317 android::os::CreateAppDataResult result;
1318 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1319 args.packageName = "com.foo";
1320 // Create the app user data.
1321 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1322 // Destroy the app user data.
1323 ASSERT_BINDER_SUCCESS(service->destroyAppData(args.uuid, args.packageName, args.userId,
1324 FLAG_STORAGE_CE, result.ceDataInode));
1325 ASSERT_TRUE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1326 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1327 }
1328
TEST_F(DestroyAppDataTest,DestroySdkSandboxDataDirectories_WithoutCeFlag)1329 TEST_F(DestroyAppDataTest, DestroySdkSandboxDataDirectories_WithoutCeFlag) {
1330 android::os::CreateAppDataResult result;
1331 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1332 args.packageName = "com.foo";
1333 // Create the app user data.
1334 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1335 // Destroy the app user data.
1336 ASSERT_BINDER_SUCCESS(service->destroyAppData(args.uuid, args.packageName, args.userId,
1337 FLAG_STORAGE_DE, result.ceDataInode));
1338 ASSERT_TRUE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
1339 ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
1340 }
1341
1342 class ClearAppDataTest : public SdkSandboxDataTest {
1343 public:
createTestSdkData(const std::string & packageName,std::vector<std::string> sdkNames)1344 void createTestSdkData(const std::string& packageName, std::vector<std::string> sdkNames) {
1345 const auto& cePackagePath = "/data/local/tmp/misc_ce/0/sdksandbox/" + packageName;
1346 const auto& dePackagePath = "/data/local/tmp/misc_de/0/sdksandbox/" + packageName;
1347 ASSERT_TRUE(mkdirs(cePackagePath, 0700));
1348 ASSERT_TRUE(mkdirs(dePackagePath, 0700));
1349 const std::vector<std::string> packagePaths = {cePackagePath, dePackagePath};
1350 for (const auto& packagePath : packagePaths) {
1351 for (auto sdkName : sdkNames) {
1352 ASSERT_TRUE(mkdirs(packagePath + "/" + sdkName + "/cache", 0700));
1353 ASSERT_TRUE(mkdirs(packagePath + "/" + sdkName + "/code_cache", 0700));
1354 std::ofstream{packagePath + "/" + sdkName + "/cache/cachedTestData.txt"};
1355 std::ofstream{packagePath + "/" + sdkName + "/code_cache/cachedTestData.txt"};
1356 }
1357 }
1358 }
1359 };
1360
TEST_F(ClearAppDataTest,ClearSdkSandboxDataDirectories_WithCeAndClearCacheFlag)1361 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithCeAndClearCacheFlag) {
1362 createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
1363 // Clear the app user data.
1364 ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0,
1365 FLAG_STORAGE_CE | FLAG_CLEAR_CACHE_ONLY, -1));
1366
1367 const std::string packagePath = kTestPath + "/misc_ce/0/sdksandbox/com.foo";
1368 ASSERT_TRUE(is_empty(packagePath + "/shared/cache"));
1369 ASSERT_TRUE(is_empty(packagePath + "/sdk1/cache"));
1370 ASSERT_TRUE(is_empty(packagePath + "/sdk2/cache"));
1371 }
1372
TEST_F(ClearAppDataTest,ClearSdkSandboxDataDirectories_WithCeAndClearCodeCacheFlag)1373 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithCeAndClearCodeCacheFlag) {
1374 createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
1375 // Clear the app user data.
1376 ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0,
1377 FLAG_STORAGE_CE | FLAG_CLEAR_CODE_CACHE_ONLY, -1));
1378
1379 const std::string packagePath = kTestPath + "/misc_ce/0/sdksandbox/com.foo";
1380 ASSERT_TRUE(is_empty(packagePath + "/shared/code_cache"));
1381 ASSERT_TRUE(is_empty(packagePath + "/sdk1/code_cache"));
1382 ASSERT_TRUE(is_empty(packagePath + "/sdk2/code_cache"));
1383 }
1384
TEST_F(ClearAppDataTest,ClearSdkSandboxDataDirectories_WithDeAndClearCacheFlag)1385 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithDeAndClearCacheFlag) {
1386 createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
1387 // Clear the app user data
1388 ASSERT_BINDER_SUCCESS(
1389 service->clearAppData(kTestUuid, "com.foo", 0,
1390 FLAG_STORAGE_DE | (InstalldNativeService::FLAG_CLEAR_CACHE_ONLY),
1391 -1));
1392
1393 const std::string packagePath = kTestPath + "/misc_de/0/sdksandbox/com.foo";
1394 ASSERT_TRUE(is_empty(packagePath + "/shared/cache"));
1395 ASSERT_TRUE(is_empty(packagePath + "/sdk1/cache"));
1396 ASSERT_TRUE(is_empty(packagePath + "/sdk2/cache"));
1397 }
1398
TEST_F(ClearAppDataTest,ClearSdkSandboxDataDirectories_WithDeAndClearCodeCacheFlag)1399 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithDeAndClearCodeCacheFlag) {
1400 createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
1401 // Clear the app user data.
1402 ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0,
1403 FLAG_STORAGE_DE | FLAG_CLEAR_CODE_CACHE_ONLY, -1));
1404
1405 const std::string packagePath = kTestPath + "/misc_de/0/sdksandbox/com.foo";
1406 ASSERT_TRUE(is_empty(packagePath + "/shared/code_cache"));
1407 ASSERT_TRUE(is_empty(packagePath + "/sdk1/code_cache"));
1408 ASSERT_TRUE(is_empty(packagePath + "/sdk2/code_cache"));
1409 }
1410
TEST_F(ClearAppDataTest,ClearSdkSandboxDataDirectories_WithCeAndWithoutAnyCacheFlag)1411 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithCeAndWithoutAnyCacheFlag) {
1412 createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
1413 // Clear the app user data.
1414 ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0, FLAG_STORAGE_CE, -1));
1415
1416 const std::string packagePath = kTestPath + "/misc_ce/0/sdksandbox/com.foo";
1417 ASSERT_TRUE(is_empty(packagePath + "/shared"));
1418 ASSERT_TRUE(is_empty(packagePath + "/sdk1"));
1419 ASSERT_TRUE(is_empty(packagePath + "/sdk2"));
1420 }
1421
TEST_F(ClearAppDataTest,ClearSdkSandboxDataDirectories_WithDeAndWithoutAnyCacheFlag)1422 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithDeAndWithoutAnyCacheFlag) {
1423 createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
1424 // Clear the app user data.
1425 ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0, FLAG_STORAGE_DE, -1));
1426
1427 const std::string packagePath = kTestPath + "/misc_de/0/sdksandbox/com.foo";
1428 ASSERT_TRUE(is_empty(packagePath + "/shared"));
1429 ASSERT_TRUE(is_empty(packagePath + "/sdk1"));
1430 ASSERT_TRUE(is_empty(packagePath + "/sdk2"));
1431 }
1432
1433 class DestroyUserDataTest : public SdkSandboxDataTest {};
1434
TEST_F(DestroyUserDataTest,DestroySdkData_WithCeFlag)1435 TEST_F(DestroyUserDataTest, DestroySdkData_WithCeFlag) {
1436 android::os::CreateAppDataResult result;
1437 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1438 args.packageName = "com.foo";
1439 // Create the app user data.
1440 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1441 // Destroy user data
1442 ASSERT_BINDER_SUCCESS(service->destroyUserData(args.uuid, args.userId, FLAG_STORAGE_CE));
1443 ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox"));
1444 ASSERT_TRUE(exists("/data/local/tmp/misc_de/0/sdksandbox"));
1445 }
1446
TEST_F(DestroyUserDataTest,DestroySdkData_WithDeFlag)1447 TEST_F(DestroyUserDataTest, DestroySdkData_WithDeFlag) {
1448 android::os::CreateAppDataResult result;
1449 android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
1450 args.packageName = "com.foo";
1451 // Create the app user data.
1452 ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
1453 // Destroy user data
1454 ASSERT_BINDER_SUCCESS(service->destroyUserData(args.uuid, args.userId, FLAG_STORAGE_DE));
1455 ASSERT_TRUE(exists("/data/local/tmp/misc_ce/0/sdksandbox"));
1456 ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox"));
1457 }
1458
1459 } // namespace installd
1460 } // namespace android
1461