From c03de09173f98506e73e7cf7df21fe11795d4b24 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 7 Apr 2015 18:14:05 -0700 Subject: [PATCH] Plumb through volume UUID when building paths. Since app data paths can live on expanded storage devices, accept the target volume UUID when building paths. The null UUID indicates the default internal storage. To improve readability, start using std::string in several places, which throws when allocations fail. For now, perform last-second sanity checks on incoming path arguments, but we'll eventually want to check arguments as they come through installd.cpp, instead of crashing the entire daemon. Also remove "lib" symlink code from install() and make_user_data(), since we're no longer supporting /data/app-lib. The framework already uses linklib() to create the right symlink for the selected ISA-specific library dir. Bug: 19993667 Change-Id: Ib9343575ffb62bf3981e19375de8f3822fc31e28 --- cmds/installd/Android.mk | 8 +- cmds/installd/commands.cpp | 175 +++++--------------- cmds/installd/installd.cpp | 20 +-- cmds/installd/installd.h | 27 ++- cmds/installd/tests/Android.mk | 1 + cmds/installd/tests/installd_utils_test.cpp | 25 ++- cmds/installd/utils.cpp | 119 ++++++------- 7 files changed, 132 insertions(+), 243 deletions(-) diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk index 2d90ff377..c66414801 100644 --- a/cmds/installd/Android.mk +++ b/cmds/installd/Android.mk @@ -12,6 +12,7 @@ LOCAL_MODULE := libinstalld LOCAL_MODULE_TAGS := eng tests LOCAL_SRC_FILES := $(common_src_files) LOCAL_CFLAGS := $(common_cflags) +LOCAL_SHARED_LIBRARIES := libbase LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk include $(BUILD_STATIC_LIBRARY) @@ -24,7 +25,12 @@ LOCAL_MODULE := installd LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(common_cflags) LOCAL_SRC_FILES := installd.cpp $(common_src_files) -LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + liblog \ + libselinux \ + LOCAL_STATIC_LIBRARIES := libdiskusage LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk include $(BUILD_EXECUTABLE) diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp index 5f72ae4cb..0bc139373 100644 --- a/cmds/installd/commands.cpp +++ b/cmds/installd/commands.cpp @@ -33,11 +33,8 @@ dir_rec_t android_media_dir; dir_rec_t android_mnt_expand_dir; dir_rec_array_t android_system_dirs; -int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) +int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) { - char pkgdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; - char applibdir[PKG_PATH_MAX]; struct stat libStat; if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { @@ -45,20 +42,8 @@ int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) return -1; } - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { - ALOGE("cannot create package path\n"); - return -1; - } - - if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) { - ALOGE("cannot create package lib symlink origin path\n"); - return -1; - } - - if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { - ALOGE("cannot create package lib symlink dest path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, 0)); + const char* pkgdir = _pkgdir.c_str(); if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -70,42 +55,14 @@ int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) return -1; } - if (lstat(libsymlink, &libStat) < 0) { - if (errno != ENOENT) { - ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); - return -1; - } - } else { - if (S_ISDIR(libStat.st_mode)) { - if (delete_dir_contents(libsymlink, 1, NULL) < 0) { - ALOGE("couldn't delete lib directory during install for: %s", libsymlink); - return -1; - } - } else if (S_ISLNK(libStat.st_mode)) { - if (unlink(libsymlink) < 0) { - ALOGE("couldn't unlink lib directory during install for: %s", libsymlink); - return -1; - } - } - } - if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -errno; } - if (symlink(applibdir, libsymlink) < 0) { - ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir, - strerror(errno)); - unlink(pkgdir); - return -1; - } - if (chown(pkgdir, uid, gid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -1; } @@ -113,12 +70,10 @@ int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) return 0; } -int uninstall(const char *pkgname, userid_t userid) +int uninstall(const char *uuid, const char *pkgname, userid_t userid) { - char pkgdir[PKG_PATH_MAX]; - - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) - return -1; + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); remove_profile_file(pkgname); @@ -143,9 +98,8 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } -int fix_uid(const char *pkgname, uid_t uid, gid_t gid) +int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid) { - char pkgdir[PKG_PATH_MAX]; struct stat s; if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { @@ -153,10 +107,8 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid) return -1; } - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { - ALOGE("cannot create package path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, 0)); + const char* pkgdir = _pkgdir.c_str(); if (stat(pkgdir, &s) < 0) return -1; @@ -179,35 +131,20 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid) return 0; } -int delete_user_data(const char *pkgname, userid_t userid) +int delete_user_data(const char *uuid, const char *pkgname, userid_t userid) { - char pkgdir[PKG_PATH_MAX]; - - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) - return -1; + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); return delete_dir_contents(pkgdir, 0, NULL); } -int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) +int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) { - char pkgdir[PKG_PATH_MAX]; - char applibdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; struct stat libStat; - // Create the data dir for the package - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) { - return -1; - } - if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) { - ALOGE("cannot create package lib symlink origin path\n"); - return -1; - } - if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { - ALOGE("cannot create package lib symlink dest path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -219,47 +156,14 @@ int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* return -errno; } - if (lstat(libsymlink, &libStat) < 0) { - if (errno != ENOENT) { - ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno)); - unlink(pkgdir); - return -1; - } - } else { - if (S_ISDIR(libStat.st_mode)) { - if (delete_dir_contents(libsymlink, 1, NULL) < 0) { - ALOGE("couldn't delete lib directory during install for non-primary: %s", - libsymlink); - unlink(pkgdir); - return -1; - } - } else if (S_ISLNK(libStat.st_mode)) { - if (unlink(libsymlink) < 0) { - ALOGE("couldn't unlink lib directory during install for non-primary: %s", - libsymlink); - unlink(pkgdir); - return -1; - } - } - } - if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -errno; } - if (symlink(applibdir, libsymlink) < 0) { - ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink, - applibdir, strerror(errno)); - unlink(pkgdir); - return -1; - } - if (chown(pkgdir, uid, uid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -errno; } @@ -301,24 +205,23 @@ int delete_user(userid_t userid) return status; } -int delete_cache(const char *pkgname, userid_t userid) +int delete_cache(const char *uuid, const char *pkgname, userid_t userid) { - char cachedir[PKG_PATH_MAX]; - - if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid)) - return -1; + std::string _cachedir( + create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); + const char* cachedir = _cachedir.c_str(); /* delete contents, not the directory, no exceptions */ return delete_dir_contents(cachedir, 0, NULL); } -int delete_code_cache(const char *pkgname, userid_t userid) +int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid) { - char codecachedir[PKG_PATH_MAX]; - struct stat s; + std::string _codecachedir( + create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); + const char* codecachedir = _codecachedir.c_str(); - if (create_pkg_path(codecachedir, pkgname, CODE_CACHE_DIR_POSTFIX, userid)) - return -1; + struct stat s; /* it's okay if code cache is missing */ if (lstat(codecachedir, &s) == -1 && errno == ENOENT) { @@ -336,6 +239,7 @@ int delete_code_cache(const char *pkgname, userid_t userid) * also require that apps constantly modify file metadata even * when just reading from the cache, which is pretty awful. */ +// TODO: extend to know about other volumes int free_cache(int64_t free_size) { cache_t* cache; @@ -467,7 +371,7 @@ int rm_dex(const char *path, const char *instruction_set) } } -int get_size(const char *pkgname, userid_t userid, const char *apkpath, +int get_size(const char *uuid, const char *pkgname, userid_t userid, 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) @@ -524,11 +428,10 @@ int get_size(const char *pkgname, userid_t userid, const char *apkpath, } } - if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) { - goto done; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); - d = opendir(path); + d = opendir(pkgdir); if (d == NULL) { goto done; } @@ -1441,21 +1344,16 @@ done: return 0; } -int linklib(const char* pkgname, const char* asecLibDir, int userId) +int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId) { - char pkgdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; struct stat s, libStat; int rc = 0; - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) { - ALOGE("cannot create package path\n"); - return -1; - } - if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) { - ALOGE("cannot create package lib symlink origin path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, userId)); + std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); + + const char* pkgdir = _pkgdir.c_str(); + const char* libsymlink = _libsymlink.c_str(); if (stat(pkgdir, &s) < 0) return -1; @@ -1624,7 +1522,8 @@ fail: return -1; } -int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) +// TODO: extend to know about other volumes +int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid) { struct dirent *entry; DIR *d; diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp index ad2478bbf..39893bbcf 100644 --- a/cmds/installd/installd.cpp +++ b/cmds/installd/installd.cpp @@ -33,7 +33,7 @@ static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused) static int do_install(char **arg, char reply[REPLY_MAX] __unused) { - return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */ + return install(nullptr, arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */ } static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused) @@ -61,7 +61,7 @@ static int do_rm_dex(char **arg, char reply[REPLY_MAX] __unused) static int do_remove(char **arg, char reply[REPLY_MAX] __unused) { - return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */ + return uninstall(nullptr, arg[0], atoi(arg[1])); /* pkgname, userid */ } static int do_rename(char **arg, char reply[REPLY_MAX] __unused) @@ -71,7 +71,7 @@ static int do_rename(char **arg, char reply[REPLY_MAX] __unused) static int do_fixuid(char **arg, char reply[REPLY_MAX] __unused) { - return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ + return fix_uid(nullptr, arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ } static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int:free_size */ @@ -81,12 +81,12 @@ static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int static int do_rm_cache(char **arg, char reply[REPLY_MAX] __unused) { - return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */ + return delete_cache(nullptr, arg[0], atoi(arg[1])); /* pkgname, userid */ } static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] __unused) { - return delete_code_cache(arg[0], atoi(arg[1])); /* pkgname, userid */ + return delete_code_cache(nullptr, arg[0], atoi(arg[1])); /* pkgname, userid */ } static int do_get_size(char **arg, char reply[REPLY_MAX]) @@ -98,7 +98,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int res = 0; /* pkgdir, userid, apkpath */ - res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5], + res = get_size(nullptr, arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5], arg[6], &codesize, &datasize, &cachesize, &asecsize); /* @@ -112,12 +112,12 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused) { - return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */ + return delete_user_data(nullptr, arg[0], atoi(arg[1])); /* pkgname, userid */ } static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused) { - return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); + return make_user_data(nullptr, arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, userid, seinfo */ } @@ -138,7 +138,7 @@ static int do_movefiles(char **arg __unused, char reply[REPLY_MAX] __unused) static int do_linklib(char **arg, char reply[REPLY_MAX] __unused) { - return linklib(arg[0], arg[1], atoi(arg[2])); + return linklib(nullptr, arg[0], arg[1], atoi(arg[2])); } static int do_idmap(char **arg, char reply[REPLY_MAX] __unused) @@ -148,7 +148,7 @@ static int do_idmap(char **arg, char reply[REPLY_MAX] __unused) static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused))) { - return restorecon_data(arg[0], arg[1], atoi(arg[2])); + return restorecon_data(nullptr, arg[0], arg[1], atoi(arg[2])); /* pkgName, seinfo, uid*/ } diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 0ebc0ba85..15fc2d98b 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -133,10 +134,8 @@ typedef struct { /* util.c */ -int create_pkg_path_in_dir(char path[PKG_PATH_MAX], - const dir_rec_t* dir, - const char* pkgname, - const char* postfix); +std::string create_package_data_path(const char* volume_uuid, + const char* package_name, userid_t user); int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, @@ -203,20 +202,20 @@ void remove_profile_file(const char *pkgname); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo); -int uninstall(const char *pkgname, userid_t userid); +int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo); +int uninstall(const char *uuid, const char *pkgname, userid_t userid); int renamepkg(const char *oldpkgname, const char *newpkgname); -int fix_uid(const char *pkgname, uid_t uid, gid_t gid); -int delete_user_data(const char *pkgname, userid_t userid); -int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo); +int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid); +int delete_user_data(const char *uuid, const char *pkgname, userid_t userid); +int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo); int make_user_config(userid_t userid); int delete_user(userid_t userid); -int delete_cache(const char *pkgname, userid_t userid); -int delete_code_cache(const char *pkgname, userid_t userid); +int delete_cache(const char *uuid, const char *pkgname, userid_t userid); +int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid); int move_dex(const char *src, const char *dst, const char *instruction_set); int rm_dex(const char *path, const char *instruction_set); int protect(char *pkgname, gid_t gid); -int get_size(const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath, +int get_size(const char *uuid, const char *pkgname, userid_t userid, 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 free_cache(int64_t free_size); @@ -225,9 +224,9 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName, const char* outputPath); int mark_boot_complete(const char *instruction_set); int movefiles(); -int linklib(const char* target, const char* source, int userId); +int linklib(const char *uuid, const char* target, const char* source, int userId); int idmap(const char *target_path, const char *overlay_path, uid_t uid); -int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid); +int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid); int create_oat_dir(const char* oat_dir, const char *instruction_set); int rm_package_dir(const char* apk_path); int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk index 7300b298f..c16375ae3 100644 --- a/cmds/installd/tests/Android.mk +++ b/cmds/installd/tests/Android.mk @@ -8,6 +8,7 @@ test_src_files := \ installd_utils_test.cpp shared_libraries := \ + libbase \ libutils \ libcutils \ diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index 68d150b76..ebf705324 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -321,6 +321,7 @@ TEST_F(UtilsTest, CreatePkgPath_LongPkgNameSuccess) { const char *prefix = TEST_DATA_DIR PRIMARY_USER_PREFIX; size_t offset = strlen(prefix); + EXPECT_STREQ(pkgname, path + offset) << "Package path should be a really long string of a's"; } @@ -371,20 +372,6 @@ TEST_F(UtilsTest, CreatePkgPath_SecondaryUser) { << "Package path should be in /data/user/"; } -TEST_F(UtilsTest, CreatePkgPathInDir_ProtectedDir) { - char path[PKG_PATH_MAX]; - - dir_rec_t dir; - dir.path = (char*) "/data/app-private/"; - dir.len = strlen(dir.path); - - EXPECT_EQ(0, create_pkg_path_in_dir(path, &dir, "com.example.package", ".apk")) - << "Should successfully create package path."; - - EXPECT_STREQ("/data/app-private/com.example.package.apk", path) - << "Package path should be in /data/app-private/"; -} - TEST_F(UtilsTest, CreatePersonaPath_Primary) { char path[PKG_PATH_MAX]; @@ -482,4 +469,14 @@ TEST_F(UtilsTest, AppendAndIncrement_TooBig) { << "String should fail because it's too large to fit"; } +TEST_F(UtilsTest, CreatePackageDataPath) { + EXPECT_EQ("/data/data/com.example", create_package_data_path(nullptr, "com.example", 0)); + EXPECT_EQ("/data/user/10/com.example", create_package_data_path(nullptr, "com.example", 10)); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example", + create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 0)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example", + create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 10)); +} + } diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index df2bbced8..763cb4283 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -16,86 +16,69 @@ #include "installd.h" +#include +#include + #define CACHE_NOISY(x) //x -int create_pkg_path_in_dir(char path[PKG_PATH_MAX], - const dir_rec_t* dir, - const char* pkgname, - const char* postfix) -{ - const size_t postfix_len = strlen(postfix); +using android::base::StringPrintf; - const size_t pkgname_len = strlen(pkgname); - if (pkgname_len > PKG_NAME_MAX) { - return -1; - } - - if (is_valid_package_name(pkgname) < 0) { - return -1; - } - - if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) { - return -1; - } - - char *dst = path; - size_t dst_size = PKG_PATH_MAX; - - if (append_and_increment(&dst, dir->path, &dst_size) < 0 - || append_and_increment(&dst, pkgname, &dst_size) < 0 - || append_and_increment(&dst, postfix, &dst_size) < 0) { - ALOGE("Error building APK path"); - return -1; - } - - return 0; +/** + * Check that given string is valid filename, and that it attempts no + * parent or child directory traversal. + */ +static bool is_valid_filename(const std::string& name) { + if (name.empty() || (name == ".") || (name == "..") + || (name.find('/') != std::string::npos)) { + return false; + } else { + return true; + } } /** - * Create the package path name for a given package name with a postfix for - * a certain userid. Returns 0 on success, and -1 on failure. + * Create the path name where package data should be stored for the given + * volume UUID, package name, and user ID. An empty UUID is assumed to be + * internal storage. */ -int create_pkg_path(char path[PKG_PATH_MAX], - const char *pkgname, - const char *postfix, - userid_t userid) -{ - size_t userid_len; - const char* userid_prefix; - if (userid == 0) { - userid_prefix = PRIMARY_USER_PREFIX; - userid_len = 0; +std::string create_package_data_path(const char* volume_uuid, + const char* package_name, userid_t user) { + CHECK(is_valid_filename(package_name)); + CHECK(is_valid_package_name(package_name) == 0); + + if (volume_uuid == nullptr) { + if (user == 0) { + // /data/data/com.example + return StringPrintf("%sdata/%s", android_data_dir.path, package_name); + } else { + // /data/user/0/com.example + return StringPrintf("%suser/%u/%s", android_data_dir.path, user, package_name); + } } else { - userid_prefix = SECONDARY_USER_PREFIX; - userid_len = snprintf(NULL, 0, "%d", userid); + CHECK(is_valid_filename(volume_uuid)); + + // /mnt/expand/uuid/user/0/com.example + return StringPrintf("%s%s/user/%u/%s", android_mnt_expand_dir.path, + volume_uuid, user, package_name); } +} - const size_t prefix_len = android_data_dir.len + strlen(userid_prefix) - + userid_len + 1 /*slash*/; - char prefix[prefix_len + 1]; - - char *dst = prefix; - size_t dst_size = sizeof(prefix); - - if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 - || append_and_increment(&dst, userid_prefix, &dst_size) < 0) { - ALOGE("Error building prefix for APK path"); +int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, + const char *postfix, userid_t userid) { + if (is_valid_package_name(pkgname) != 0) { + path[0] = '\0'; return -1; } - if (userid != 0) { - int ret = snprintf(dst, dst_size, "%d/", userid); - if (ret < 0 || (size_t) ret != userid_len + 1) { - ALOGW("Error appending UID to APK path"); - return -1; - } + std::string _tmp(create_package_data_path(nullptr, pkgname, userid) + postfix); + const char* tmp = _tmp.c_str(); + if (strlen(tmp) >= PKG_PATH_MAX) { + path[0] = '\0'; + return -1; + } else { + strcpy(path, tmp); + return 0; } - - dir_rec_t dir; - dir.path = prefix; - dir.len = prefix_len; - - return create_pkg_path_in_dir(path, &dir, pkgname, postfix); } /** @@ -182,6 +165,10 @@ int is_valid_package_name(const char* pkgname) { const char *x = pkgname; int alpha = -1; + if (strlen(pkgname) > PKG_NAME_MAX) { + return -1; + } + while (*x) { if (isalnum(*x) || (*x == '_')) { /* alphanumeric or underscore are fine */