Loading cmds/installd/commands.cpp +85 −129 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int uid_t uid = multiuser_get_uid(userid, appid); int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_package_path(uuid, userid, pkgname); auto path = create_data_user_ce_package_path(uuid, userid, pkgname); if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << path; return -1; Loading Loading @@ -124,7 +124,7 @@ int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int // consistent location. This only works on non-FBE devices, since we // never want to risk exposing data on a device with real CE/DE storage. auto ce_path = create_data_user_package_path(uuid, userid, pkgname); auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname); auto de_path = create_data_user_de_package_path(uuid, userid, pkgname); // If neither directory is marked as default, assume CE is default Loading Loading @@ -234,7 +234,8 @@ int clear_app_profiles(const char* pkgname) { return success ? 0 : -1; } int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) { int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode) { std::string suffix = ""; bool only_cache = false; if (flags & FLAG_CLEAR_CACHE_ONLY) { Loading @@ -247,7 +248,7 @@ int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int f int res = 0; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_package_path(uuid, userid, pkgname) + suffix; auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix; if (access(path.c_str(), F_OK) == 0) { res |= delete_dir_contents(path); } Loading Loading @@ -289,11 +290,12 @@ int destroy_app_profiles(const char *pkgname) { return result; } int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) { int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode) { int res = 0; if (flags & FLAG_STORAGE_CE) { res |= delete_dir_contents_and_dir( create_data_user_package_path(uuid, userid, pkgname)); create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode)); } if (flags & FLAG_STORAGE_DE) { res |= delete_dir_contents_and_dir( Loading Loading @@ -346,9 +348,9 @@ int move_complete_app(const char *from_uuid, const char *to_uuid, const char *pa // Copy private data for all known users // TODO: handle user_de paths for (auto user : users) { std::string from(create_data_user_package_path(from_uuid, user, package_name)); std::string to(create_data_user_package_path(to_uuid, user, package_name)); std::string to_parent(create_data_user_path(to_uuid, user)); std::string from(create_data_user_ce_package_path(from_uuid, user, package_name)); std::string to(create_data_user_ce_package_path(to_uuid, user, package_name)); std::string to_parent(create_data_user_ce_path(to_uuid, user)); // Data source may not exist for all users; that's okay if (access(from.c_str(), F_OK) != 0) { Loading @@ -356,7 +358,7 @@ int move_complete_app(const char *from_uuid, const char *to_uuid, const char *pa continue; } std::string user_path(create_data_user_path(to_uuid, user)); std::string user_path(create_data_user_ce_path(to_uuid, user)); if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) { LOG(ERROR) << "Failed to prepare user target " << user_path; goto fail; Loading Loading @@ -409,7 +411,7 @@ fail: } } for (auto user : users) { std::string to(create_data_user_package_path(to_uuid, user, package_name)); std::string to(create_data_user_ce_package_path(to_uuid, user, package_name)); if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { LOG(WARNING) << "Failed to rollback " << to; } Loading @@ -429,7 +431,7 @@ int make_user_config(userid_t userid) int delete_user(const char *uuid, userid_t userid) { int res = 0; std::string data_path(create_data_user_path(uuid, userid)); std::string data_path(create_data_user_ce_path(uuid, userid)); std::string data_de_path(create_data_user_de_path(uuid, userid)); std::string media_path(create_data_media_path(uuid, userid)); std::string profiles_path(create_data_user_profiles_path(userid)); Loading Loading @@ -480,7 +482,7 @@ int free_cache(const char *uuid, int64_t free_size) // Special case for owner on internal storage if (uuid == nullptr) { std::string _tmpdir(create_data_user_path(nullptr, 0)); std::string _tmpdir(create_data_user_ce_path(nullptr, 0)); add_cache_files(cache, _tmpdir.c_str(), "cache"); } Loading Loading @@ -567,141 +569,95 @@ int rm_dex(const char *path, const char *instruction_set) } } int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int64_t* _asecsize) { static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize, int64_t *cachesize) { DIR *d; int dfd; struct dirent *de; struct stat s; char path[PKG_PATH_MAX]; int64_t codesize = 0; int64_t datasize = 0; int64_t cachesize = 0; int64_t asecsize = 0; /* count the source apk as code -- but only if it's not * on the /system partition and its not on the sdcard. */ if (validate_system_app_path(apkpath) && strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { if (stat(apkpath, &s) == 0) { codesize += stat_size(&s); if (S_ISDIR(s.st_mode)) { d = opendir(apkpath); if (d != NULL) { dfd = dirfd(d); codesize += calculate_dir_size(dfd); closedir(d); } } } } /* count the forward locked apk as code if it is given */ if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { if (stat(fwdlock_apkpath, &s) == 0) { codesize += stat_size(&s); } } /* count the cached dexfile as code */ if (create_cache_path(path, apkpath, instruction_set)) { if (stat(path, &s) == 0) { codesize += stat_size(&s); } } /* add in size of any libraries */ if (libdirpath != NULL && libdirpath[0] != '!') { d = opendir(libdirpath); if (d != NULL) { dfd = dirfd(d); codesize += calculate_dir_size(dfd); closedir(d); } } /* compute asec size if it is given */ if (asecpath != NULL && asecpath[0] != '!') { if (stat(asecpath, &s) == 0) { asecsize += stat_size(&s); } } std::vector<userid_t> users; if (userid == -1) { users = get_known_users(uuid); } else { users.push_back(userid); } for (auto user : users) { // TODO: handle user_de directories if (!(flags & FLAG_STORAGE_CE)) continue; std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname)); const char* pkgdir = _pkgdir.c_str(); d = opendir(pkgdir); if (d == NULL) { PLOG(WARNING) << "Failed to open " << pkgdir; continue; d = opendir(path.c_str()); if (d == nullptr) { PLOG(WARNING) << "Failed to open " << path; return; } dfd = dirfd(d); /* most stuff in the pkgdir is data, except for the "cache" * directory and below, which is cache, and the "lib" directory * and below, which is code... */ while ((de = readdir(d))) { const char *name = de->d_name; int64_t statsize = 0; if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { statsize = stat_size(&s); } if (de->d_type == DT_DIR) { int subfd; int64_t statsize = 0; int64_t dirsize = 0; /* always skip "." and ".." */ if (name[0] == '.') { if (name[1] == 0) continue; if ((name[1] == '.') && (name[2] == 0)) continue; } if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { statsize = stat_size(&s); } subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); if (subfd >= 0) { dirsize = calculate_dir_size(subfd); close(subfd); } if(!strcmp(name,"lib")) { codesize += dirsize + statsize; } else if(!strcmp(name,"cache")) { cachesize += dirsize + statsize; // TODO: check xattrs! if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) { *datasize += statsize; *cachesize += dirsize; } else { datasize += dirsize + statsize; *datasize += dirsize + statsize; } } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) { // This is the symbolic link to the application's library // code. We'll count this as code instead of data, since // it is not something that the app creates. if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { codesize += stat_size(&s); } *codesize += statsize; } else { if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { datasize += stat_size(&s); *datasize += statsize; } } closedir(d); } int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t* asecsize) { DIR *d; int dfd; d = opendir(code_path); if (d != nullptr) { dfd = dirfd(d); *codesize += calculate_dir_size(dfd); closedir(d); } *_codesize = codesize; *_datasize = datasize; *_cachesize = cachesize; *_asecsize = asecsize; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode); add_app_data_size(path, codesize, datasize, cachesize); } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid, userid, pkgname); add_app_data_size(path, codesize, datasize, cachesize); } *asecsize = 0; return 0; } int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) { struct stat buf; memset(&buf, 0, sizeof(buf)); if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname); if (stat(path.c_str(), &buf) == 0) { *inode = buf.st_ino; return 0; } } return -1; } static int split_count(const char *str) { Loading Loading @@ -1617,7 +1573,7 @@ int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int u struct stat s, libStat; int rc = 0; std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname)); std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname)); std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); const char* pkgdir = _pkgdir.c_str(); Loading Loading @@ -1804,7 +1760,7 @@ int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, uid_t uid = multiuser_get_uid(userid, appid); if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_package_path(uuid, userid, pkgName); auto path = create_data_user_ce_package_path(uuid, userid, pkgName); if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) { PLOG(ERROR) << "restorecon failed for " << path; res = -1; Loading cmds/installd/commands.h +8 −6 Original line number Diff line number Diff line Loading @@ -33,16 +33,18 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags, appid_t appid, const char* seinfo); int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags); int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags); int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags); int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode); int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode); int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name, const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version); int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode); int make_user_config(userid_t userid); int delete_user(const char *uuid, userid_t userid); Loading cmds/installd/installd.cpp +23 −12 Original line number Diff line number Diff line Loading @@ -207,13 +207,13 @@ static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSE } static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { /* const char *uuid, const char *pkgname, userid_t userid, int flags */ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); } static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { /* const char *uuid, const char *pkgname, userid_t userid, int flags */ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); } // We use otapreopt_chroot to get into the chroot. Loading Loading @@ -303,11 +303,10 @@ static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { int64_t asecsize = 0; int res = 0; /* const char *uuid, const char *pkgname, userid_t userid, int flags, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set */ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5], arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize); /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, const char* code_path */ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]), arg[5], &codesize, &datasize, &cachesize, &asecsize); /* * Each int64_t can take up 22 characters printed out. Make sure it Loading @@ -318,6 +317,17 @@ static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { return res; } static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) { ino_t inode = 0; int res = 0; /* const char *uuid, const char *pkgname, int userid, int flags */ res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode); snprintf(reply, REPLY_MAX, "%" PRId64, inode); return res; } static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { /* const char* from_uuid, const char *to_uuid, const char *package_name, const char *data_app_name, appid_t appid, const char* seinfo, Loading Loading @@ -393,10 +403,11 @@ struct cmdinfo cmds[] = { { "create_app_data", 7, do_create_app_data }, { "restorecon_app_data", 6, do_restorecon_app_data }, { "migrate_app_data", 4, do_migrate_app_data }, { "clear_app_data", 4, do_clear_app_data }, { "destroy_app_data", 4, do_destroy_app_data }, { "clear_app_data", 5, do_clear_app_data }, { "destroy_app_data", 5, do_destroy_app_data }, { "move_complete_app", 7, do_move_complete_app }, { "get_app_size", 9, do_get_app_size }, { "get_app_size", 6, do_get_app_size }, { "get_app_data_inode", 4, do_get_app_data_inode }, { "dexopt", 9, do_dexopt }, { "markbootcomplete", 1, do_mark_boot_complete }, Loading cmds/installd/tests/installd_utils_test.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -472,13 +472,13 @@ TEST_F(UtilsTest, CreateDataAppPath) { } TEST_F(UtilsTest, CreateDataUserPath) { EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0)); EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10)); EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0)); EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10)); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0", create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10", create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); } TEST_F(UtilsTest, CreateDataMediaPath) { Loading @@ -499,13 +499,13 @@ TEST_F(UtilsTest, CreateDataAppPackagePath) { } TEST_F(UtilsTest, CreateDataUserPackagePath) { EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example")); EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example")); EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example")); EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example", create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example", create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example")); create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example")); } } // namespace installd Loading cmds/installd/utils.cpp +32 −4 Original line number Diff line number Diff line Loading @@ -81,11 +81,39 @@ std::string create_data_app_package_path(const char* volume_uuid, * volume UUID, package name, and user ID. An empty UUID is assumed to be * internal storage. */ std::string create_data_user_package_path(const char* volume_uuid, std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, const char* package_name) { check_package_name(package_name); return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name); create_data_user_ce_path(volume_uuid, user).c_str(), package_name); } std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, const char* package_name, ino_t ce_data_inode) { // For testing purposes, rely on the inode when defined; this could be // optimized to use access() in the future. auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name); if (ce_data_inode != 0) { auto user_path = create_data_user_ce_path(volume_uuid, user); DIR* dir = opendir(user_path.c_str()); if (dir == nullptr) { PLOG(ERROR) << "Failed to opendir " << user_path; return fallback; } struct dirent* ent; while ((ent = readdir(dir))) { if (ent->d_ino == ce_data_inode) { closedir(dir); return StringPrintf("%s/%s", user_path.c_str(), ent->d_name); } } LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name; closedir(dir); return fallback; } else { return fallback; } } std::string create_data_user_de_package_path(const char* volume_uuid, Loading @@ -102,7 +130,7 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, return -1; } std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix); std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix); const char* tmp = _tmp.c_str(); if (strlen(tmp) >= PKG_PATH_MAX) { path[0] = '\0'; Loading Loading @@ -132,7 +160,7 @@ std::string create_data_app_path(const char* volume_uuid) { /** * Create the path name for user data for a certain userid. */ std::string create_data_user_path(const char* volume_uuid, userid_t userid) { std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) { std::string data(create_data_path(volume_uuid)); if (volume_uuid == nullptr) { if (userid == 0) { Loading Loading
cmds/installd/commands.cpp +85 −129 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int uid_t uid = multiuser_get_uid(userid, appid); int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_package_path(uuid, userid, pkgname); auto path = create_data_user_ce_package_path(uuid, userid, pkgname); if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << path; return -1; Loading Loading @@ -124,7 +124,7 @@ int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int // consistent location. This only works on non-FBE devices, since we // never want to risk exposing data on a device with real CE/DE storage. auto ce_path = create_data_user_package_path(uuid, userid, pkgname); auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname); auto de_path = create_data_user_de_package_path(uuid, userid, pkgname); // If neither directory is marked as default, assume CE is default Loading Loading @@ -234,7 +234,8 @@ int clear_app_profiles(const char* pkgname) { return success ? 0 : -1; } int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) { int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode) { std::string suffix = ""; bool only_cache = false; if (flags & FLAG_CLEAR_CACHE_ONLY) { Loading @@ -247,7 +248,7 @@ int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int f int res = 0; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_package_path(uuid, userid, pkgname) + suffix; auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix; if (access(path.c_str(), F_OK) == 0) { res |= delete_dir_contents(path); } Loading Loading @@ -289,11 +290,12 @@ int destroy_app_profiles(const char *pkgname) { return result; } int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) { int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode) { int res = 0; if (flags & FLAG_STORAGE_CE) { res |= delete_dir_contents_and_dir( create_data_user_package_path(uuid, userid, pkgname)); create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode)); } if (flags & FLAG_STORAGE_DE) { res |= delete_dir_contents_and_dir( Loading Loading @@ -346,9 +348,9 @@ int move_complete_app(const char *from_uuid, const char *to_uuid, const char *pa // Copy private data for all known users // TODO: handle user_de paths for (auto user : users) { std::string from(create_data_user_package_path(from_uuid, user, package_name)); std::string to(create_data_user_package_path(to_uuid, user, package_name)); std::string to_parent(create_data_user_path(to_uuid, user)); std::string from(create_data_user_ce_package_path(from_uuid, user, package_name)); std::string to(create_data_user_ce_package_path(to_uuid, user, package_name)); std::string to_parent(create_data_user_ce_path(to_uuid, user)); // Data source may not exist for all users; that's okay if (access(from.c_str(), F_OK) != 0) { Loading @@ -356,7 +358,7 @@ int move_complete_app(const char *from_uuid, const char *to_uuid, const char *pa continue; } std::string user_path(create_data_user_path(to_uuid, user)); std::string user_path(create_data_user_ce_path(to_uuid, user)); if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) { LOG(ERROR) << "Failed to prepare user target " << user_path; goto fail; Loading Loading @@ -409,7 +411,7 @@ fail: } } for (auto user : users) { std::string to(create_data_user_package_path(to_uuid, user, package_name)); std::string to(create_data_user_ce_package_path(to_uuid, user, package_name)); if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { LOG(WARNING) << "Failed to rollback " << to; } Loading @@ -429,7 +431,7 @@ int make_user_config(userid_t userid) int delete_user(const char *uuid, userid_t userid) { int res = 0; std::string data_path(create_data_user_path(uuid, userid)); std::string data_path(create_data_user_ce_path(uuid, userid)); std::string data_de_path(create_data_user_de_path(uuid, userid)); std::string media_path(create_data_media_path(uuid, userid)); std::string profiles_path(create_data_user_profiles_path(userid)); Loading Loading @@ -480,7 +482,7 @@ int free_cache(const char *uuid, int64_t free_size) // Special case for owner on internal storage if (uuid == nullptr) { std::string _tmpdir(create_data_user_path(nullptr, 0)); std::string _tmpdir(create_data_user_ce_path(nullptr, 0)); add_cache_files(cache, _tmpdir.c_str(), "cache"); } Loading Loading @@ -567,141 +569,95 @@ int rm_dex(const char *path, const char *instruction_set) } } int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int64_t* _asecsize) { static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize, int64_t *cachesize) { DIR *d; int dfd; struct dirent *de; struct stat s; char path[PKG_PATH_MAX]; int64_t codesize = 0; int64_t datasize = 0; int64_t cachesize = 0; int64_t asecsize = 0; /* count the source apk as code -- but only if it's not * on the /system partition and its not on the sdcard. */ if (validate_system_app_path(apkpath) && strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { if (stat(apkpath, &s) == 0) { codesize += stat_size(&s); if (S_ISDIR(s.st_mode)) { d = opendir(apkpath); if (d != NULL) { dfd = dirfd(d); codesize += calculate_dir_size(dfd); closedir(d); } } } } /* count the forward locked apk as code if it is given */ if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { if (stat(fwdlock_apkpath, &s) == 0) { codesize += stat_size(&s); } } /* count the cached dexfile as code */ if (create_cache_path(path, apkpath, instruction_set)) { if (stat(path, &s) == 0) { codesize += stat_size(&s); } } /* add in size of any libraries */ if (libdirpath != NULL && libdirpath[0] != '!') { d = opendir(libdirpath); if (d != NULL) { dfd = dirfd(d); codesize += calculate_dir_size(dfd); closedir(d); } } /* compute asec size if it is given */ if (asecpath != NULL && asecpath[0] != '!') { if (stat(asecpath, &s) == 0) { asecsize += stat_size(&s); } } std::vector<userid_t> users; if (userid == -1) { users = get_known_users(uuid); } else { users.push_back(userid); } for (auto user : users) { // TODO: handle user_de directories if (!(flags & FLAG_STORAGE_CE)) continue; std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname)); const char* pkgdir = _pkgdir.c_str(); d = opendir(pkgdir); if (d == NULL) { PLOG(WARNING) << "Failed to open " << pkgdir; continue; d = opendir(path.c_str()); if (d == nullptr) { PLOG(WARNING) << "Failed to open " << path; return; } dfd = dirfd(d); /* most stuff in the pkgdir is data, except for the "cache" * directory and below, which is cache, and the "lib" directory * and below, which is code... */ while ((de = readdir(d))) { const char *name = de->d_name; int64_t statsize = 0; if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { statsize = stat_size(&s); } if (de->d_type == DT_DIR) { int subfd; int64_t statsize = 0; int64_t dirsize = 0; /* always skip "." and ".." */ if (name[0] == '.') { if (name[1] == 0) continue; if ((name[1] == '.') && (name[2] == 0)) continue; } if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { statsize = stat_size(&s); } subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); if (subfd >= 0) { dirsize = calculate_dir_size(subfd); close(subfd); } if(!strcmp(name,"lib")) { codesize += dirsize + statsize; } else if(!strcmp(name,"cache")) { cachesize += dirsize + statsize; // TODO: check xattrs! if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) { *datasize += statsize; *cachesize += dirsize; } else { datasize += dirsize + statsize; *datasize += dirsize + statsize; } } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) { // This is the symbolic link to the application's library // code. We'll count this as code instead of data, since // it is not something that the app creates. if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { codesize += stat_size(&s); } *codesize += statsize; } else { if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { datasize += stat_size(&s); *datasize += statsize; } } closedir(d); } int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t* asecsize) { DIR *d; int dfd; d = opendir(code_path); if (d != nullptr) { dfd = dirfd(d); *codesize += calculate_dir_size(dfd); closedir(d); } *_codesize = codesize; *_datasize = datasize; *_cachesize = cachesize; *_asecsize = asecsize; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode); add_app_data_size(path, codesize, datasize, cachesize); } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid, userid, pkgname); add_app_data_size(path, codesize, datasize, cachesize); } *asecsize = 0; return 0; } int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) { struct stat buf; memset(&buf, 0, sizeof(buf)); if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname); if (stat(path.c_str(), &buf) == 0) { *inode = buf.st_ino; return 0; } } return -1; } static int split_count(const char *str) { Loading Loading @@ -1617,7 +1573,7 @@ int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int u struct stat s, libStat; int rc = 0; std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname)); std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname)); std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); const char* pkgdir = _pkgdir.c_str(); Loading Loading @@ -1804,7 +1760,7 @@ int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, uid_t uid = multiuser_get_uid(userid, appid); if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_package_path(uuid, userid, pkgName); auto path = create_data_user_ce_package_path(uuid, userid, pkgName); if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) { PLOG(ERROR) << "restorecon failed for " << path; res = -1; Loading
cmds/installd/commands.h +8 −6 Original line number Diff line number Diff line Loading @@ -33,16 +33,18 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags, appid_t appid, const char* seinfo); int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags); int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags); int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags); int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode); int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode); int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name, const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version); int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode); int make_user_config(userid_t userid); int delete_user(const char *uuid, userid_t userid); Loading
cmds/installd/installd.cpp +23 −12 Original line number Diff line number Diff line Loading @@ -207,13 +207,13 @@ static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSE } static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { /* const char *uuid, const char *pkgname, userid_t userid, int flags */ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); } static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { /* const char *uuid, const char *pkgname, userid_t userid, int flags */ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); } // We use otapreopt_chroot to get into the chroot. Loading Loading @@ -303,11 +303,10 @@ static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { int64_t asecsize = 0; int res = 0; /* const char *uuid, const char *pkgname, userid_t userid, int flags, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set */ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5], arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize); /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, const char* code_path */ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]), arg[5], &codesize, &datasize, &cachesize, &asecsize); /* * Each int64_t can take up 22 characters printed out. Make sure it Loading @@ -318,6 +317,17 @@ static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { return res; } static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) { ino_t inode = 0; int res = 0; /* const char *uuid, const char *pkgname, int userid, int flags */ res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode); snprintf(reply, REPLY_MAX, "%" PRId64, inode); return res; } static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { /* const char* from_uuid, const char *to_uuid, const char *package_name, const char *data_app_name, appid_t appid, const char* seinfo, Loading Loading @@ -393,10 +403,11 @@ struct cmdinfo cmds[] = { { "create_app_data", 7, do_create_app_data }, { "restorecon_app_data", 6, do_restorecon_app_data }, { "migrate_app_data", 4, do_migrate_app_data }, { "clear_app_data", 4, do_clear_app_data }, { "destroy_app_data", 4, do_destroy_app_data }, { "clear_app_data", 5, do_clear_app_data }, { "destroy_app_data", 5, do_destroy_app_data }, { "move_complete_app", 7, do_move_complete_app }, { "get_app_size", 9, do_get_app_size }, { "get_app_size", 6, do_get_app_size }, { "get_app_data_inode", 4, do_get_app_data_inode }, { "dexopt", 9, do_dexopt }, { "markbootcomplete", 1, do_mark_boot_complete }, Loading
cmds/installd/tests/installd_utils_test.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -472,13 +472,13 @@ TEST_F(UtilsTest, CreateDataAppPath) { } TEST_F(UtilsTest, CreateDataUserPath) { EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0)); EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10)); EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0)); EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10)); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0", create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10", create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); } TEST_F(UtilsTest, CreateDataMediaPath) { Loading @@ -499,13 +499,13 @@ TEST_F(UtilsTest, CreateDataAppPackagePath) { } TEST_F(UtilsTest, CreateDataUserPackagePath) { EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example")); EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example")); EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example")); EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example", create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example", create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example")); create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example")); } } // namespace installd Loading
cmds/installd/utils.cpp +32 −4 Original line number Diff line number Diff line Loading @@ -81,11 +81,39 @@ std::string create_data_app_package_path(const char* volume_uuid, * volume UUID, package name, and user ID. An empty UUID is assumed to be * internal storage. */ std::string create_data_user_package_path(const char* volume_uuid, std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, const char* package_name) { check_package_name(package_name); return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name); create_data_user_ce_path(volume_uuid, user).c_str(), package_name); } std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, const char* package_name, ino_t ce_data_inode) { // For testing purposes, rely on the inode when defined; this could be // optimized to use access() in the future. auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name); if (ce_data_inode != 0) { auto user_path = create_data_user_ce_path(volume_uuid, user); DIR* dir = opendir(user_path.c_str()); if (dir == nullptr) { PLOG(ERROR) << "Failed to opendir " << user_path; return fallback; } struct dirent* ent; while ((ent = readdir(dir))) { if (ent->d_ino == ce_data_inode) { closedir(dir); return StringPrintf("%s/%s", user_path.c_str(), ent->d_name); } } LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name; closedir(dir); return fallback; } else { return fallback; } } std::string create_data_user_de_package_path(const char* volume_uuid, Loading @@ -102,7 +130,7 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, return -1; } std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix); std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix); const char* tmp = _tmp.c_str(); if (strlen(tmp) >= PKG_PATH_MAX) { path[0] = '\0'; Loading Loading @@ -132,7 +160,7 @@ std::string create_data_app_path(const char* volume_uuid) { /** * Create the path name for user data for a certain userid. */ std::string create_data_user_path(const char* volume_uuid, userid_t userid) { std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) { std::string data(create_data_path(volume_uuid)); if (volume_uuid == nullptr) { if (userid == 0) { Loading