diff options
| -rw-r--r-- | cmds/dumpstate/dumpstate.c | 3 | ||||
| -rw-r--r-- | cmds/installd/Android.mk | 18 | ||||
| -rw-r--r-- | cmds/installd/commands.cpp (renamed from cmds/installd/commands.c) | 413 | ||||
| -rw-r--r-- | cmds/installd/installd.cpp (renamed from cmds/installd/installd.c) | 175 | ||||
| -rw-r--r-- | cmds/installd/installd.h | 71 | ||||
| -rw-r--r-- | cmds/installd/tests/Android.mk | 2 | ||||
| -rw-r--r-- | cmds/installd/tests/installd_utils_test.cpp | 97 | ||||
| -rw-r--r-- | cmds/installd/utils.cpp (renamed from cmds/installd/utils.c) | 231 | ||||
| -rw-r--r-- | include/gui/ConsumerBase.h | 3 | ||||
| -rw-r--r-- | libs/gui/ConsumerBase.cpp | 15 |
10 files changed, 507 insertions, 521 deletions
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index f69a72df40..a33dcf35f8 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -238,9 +238,6 @@ static void dumpstate() { dump_file("LAST KMSG", "/proc/last_kmsg"); } - dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console"); - dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads"); - /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */ run_command("LAST LOGCAT", 10, "logcat", "-L", "-v", "threadtime", "-b", "all", "-d", "*:v", NULL); diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk index 8224e94b39..6dec7f6895 100644 --- a/cmds/installd/Android.mk +++ b/cmds/installd/Android.mk @@ -1,6 +1,6 @@ LOCAL_PATH := $(call my-dir) -common_src_files := commands.c utils.c +common_src_files := commands.cpp utils.cpp common_cflags := -Wall -Werror # @@ -12,7 +12,12 @@ LOCAL_MODULE := libinstalld LOCAL_MODULE_TAGS := eng tests LOCAL_SRC_FILES := $(common_src_files) LOCAL_CFLAGS := $(common_cflags) +LOCAL_SHARED_LIBRARIES := \ + libbase \ + liblogwrap \ + LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk +LOCAL_CLANG := true include $(BUILD_STATIC_LIBRARY) # @@ -23,8 +28,15 @@ include $(CLEAR_VARS) LOCAL_MODULE := installd LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(common_cflags) -LOCAL_SRC_FILES := installd.c $(common_src_files) -LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux +LOCAL_SRC_FILES := installd.cpp $(common_src_files) +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + liblog \ + liblogwrap \ + libselinux \ + LOCAL_STATIC_LIBRARIES := libdiskusage LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk +LOCAL_CLANG := true include $(BUILD_EXECUTABLE) diff --git a/cmds/installd/commands.c b/cmds/installd/commands.cpp index 48bccc3da2..de6fd960f9 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.cpp @@ -14,14 +14,22 @@ ** limitations under the License. */ -#include <inttypes.h> -#include <sys/capability.h> -#include <sys/file.h> #include "installd.h" + +#include <base/stringprintf.h> +#include <base/logging.h> #include <cutils/sched_policy.h> #include <diskusage/dirsize.h> -#include <selinux/android.h> +#include <logwrap/logwrap.h> #include <system/thread_defs.h> +#include <selinux/android.h> + +#include <inttypes.h> +#include <sys/capability.h> +#include <sys/file.h> +#include <unistd.h> + +using android::base::StringPrintf; /* Directory records that are used in execution of commands. */ dir_rec_t android_data_dir; @@ -30,34 +38,20 @@ dir_rec_t android_app_dir; dir_rec_t android_app_private_dir; dir_rec_t android_app_lib_dir; 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) -{ - char pkgdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; - char applibdir[PKG_PATH_MAX]; - struct stat libStat; +static const char* kCpPath = "/system/bin/cp"; +int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) +{ if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %d\n", uid, gid); 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)); @@ -69,42 +63,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; } @@ -112,12 +78,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); @@ -142,9 +106,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)) { @@ -152,10 +115,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; @@ -178,35 +139,18 @@ 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)); @@ -218,47 +162,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; } @@ -266,6 +177,80 @@ int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* return 0; } +int move_user_data(const char *from_uuid, const char *to_uuid, + const char *package_name, appid_t appid, const char* seinfo) { + std::vector<userid_t> users = get_known_users(from_uuid); + + // Copy package private data for all known users + for (auto user : users) { + std::string from(create_package_data_path(from_uuid, package_name, user)); + std::string to(create_package_data_path(to_uuid, package_name, user)); + std::string to_user(create_data_user_path(to_uuid, user)); + + // Data source may not exist for all users; that's okay + if (access(from.c_str(), F_OK) != 0) { + LOG(INFO) << "Missing source " << from; + continue; + } + + std::string user_path(create_data_user_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; + } + + uid_t uid = multiuser_get_uid(user, appid); + if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) { + LOG(ERROR) << "Failed to create package target " << to; + goto fail; + } + + char *argv[] = { + (char*) kCpPath, + (char*) "-F", /* delete any existing destination file first (--remove-destination) */ + (char*) "-p", /* preserve timestamps, ownership, and permissions */ + (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ + (char*) "-P", /* Do not follow symlinks [default] */ + (char*) "-d", /* don't dereference symlinks */ + (char*) from.c_str(), + (char*) to_user.c_str() + }; + + LOG(DEBUG) << "Copying " << from << " to " << to; + int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); + + if (rc != 0) { + LOG(ERROR) << "Failed copying " << from << " to " << to + << ": status " << rc; + goto fail; + } + + if (restorecon_data(to_uuid, package_name, seinfo, uid) != 0) { + LOG(ERROR) << "Failed to restorecon " << to; + goto fail; + } + } + + // Copy successful, so delete old data + for (auto user : users) { + std::string from(create_package_data_path(from_uuid, package_name, user)); + if (delete_dir_contents(from.c_str(), 1, NULL) != 0) { + LOG(WARNING) << "Failed to delete " << from; + } + } + return 0; + +fail: + // Nuke everything we might have already copied + for (auto user : users) { + std::string to(create_package_data_path(to_uuid, package_name, user)); + if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { + LOG(WARNING) << "Failed to rollback " << to; + } + } + return -1; +} + int make_user_config(userid_t userid) { if (ensure_config_user_dirs(userid) == -1) { @@ -275,49 +260,49 @@ int make_user_config(userid_t userid) return 0; } -int delete_user(userid_t userid) +int delete_user(const char *uuid, userid_t userid) { int status = 0; - char data_path[PKG_PATH_MAX]; - if ((create_user_path(data_path, userid) != 0) - || (delete_dir_contents(data_path, 1, NULL) != 0)) { + std::string data_path(create_data_user_path(uuid, userid)); + if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) { status = -1; } - char media_path[PATH_MAX]; - if ((create_user_media_path(media_path, userid) != 0) - || (delete_dir_contents(media_path, 1, NULL) != 0)) { + std::string media_path(create_data_media_path(uuid, userid)); + if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) { status = -1; } - char config_path[PATH_MAX]; - if ((create_user_config_path(config_path, userid) != 0) - || (delete_dir_contents(config_path, 1, NULL) != 0)) { - status = -1; + // Config paths only exist on internal storage + if (uuid == nullptr) { + char config_path[PATH_MAX]; + if ((create_user_config_path(config_path, userid) != 0) + || (delete_dir_contents(config_path, 1, NULL) != 0)) { + status = -1; + } } 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) { @@ -335,7 +320,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. */ -int free_cache(int64_t free_size) +int free_cache(const char *uuid, int64_t free_size) { cache_t* cache; int64_t avail; @@ -344,7 +329,9 @@ int free_cache(int64_t free_size) char tmpdir[PATH_MAX]; char *dirpos; - avail = data_disk_free(); + std::string data_path(create_data_path(uuid)); + + avail = data_disk_free(data_path); if (avail < 0) return -1; ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail); @@ -352,15 +339,16 @@ int free_cache(int64_t free_size) cache = start_cache_collection(); - // Collect cache files for primary user. - if (create_user_path(tmpdir, 0) == 0) { - //ALOGI("adding cache files from %s\n", tmpdir); - add_cache_files(cache, tmpdir, "cache"); + // Special case for owner on internal storage + if (uuid == nullptr) { + std::string _tmpdir(create_data_user_path(nullptr, 0)); + add_cache_files(cache, _tmpdir.c_str(), "cache"); } // Search for other users and add any cache files from them. - snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path, - SECONDARY_USER_PREFIX); + std::string _tmpdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); + strcpy(tmpdir, _tmpdir.c_str()); + dirpos = tmpdir + strlen(tmpdir); d = opendir(tmpdir); if (d != NULL) { @@ -412,10 +400,10 @@ int free_cache(int64_t free_size) closedir(d); } - clear_cache_files(cache, free_size); + clear_cache_files(data_path, cache, free_size); finish_cache_collection(cache); - return data_disk_free() >= free_size ? 0 : -1; + return data_disk_free(data_path) >= free_size ? 0 : -1; } int move_dex(const char *src, const char *dst, const char *instruction_set) @@ -466,7 +454,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) @@ -523,11 +511,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; } @@ -987,8 +974,8 @@ static bool calculate_odex_file_path(char path[PKG_PATH_MAX], } int dexopt(const char *apk_path, uid_t uid, bool is_public, - const char *pkgname, const char *instruction_set, - bool vm_safe_mode, bool is_patchoat, bool debuggable, const char* oat_dir) + const char *pkgname, const char *instruction_set, int dexopt_needed, + bool vm_safe_mode, bool debuggable, const char* oat_dir) { struct utimbuf ut; struct stat input_stat; @@ -1020,13 +1007,25 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, } } - if (is_patchoat) { - if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { - return -1; - } - input_file = in_odex_path; - } else { - input_file = apk_path; + switch (dexopt_needed) { + case DEXOPT_DEX2OAT_NEEDED: + input_file = apk_path; + break; + + case DEXOPT_PATCHOAT_NEEDED: + if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { + return -1; + } + input_file = in_odex_path; + break; + + case DEXOPT_SELF_PATCHOAT_NEEDED: + input_file = out_path; + break; + + default: + ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); + exit(72); } memset(&input_stat, 0, sizeof(input_stat)); @@ -1061,7 +1060,7 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, } // Create a swap file if necessary. - if (!is_patchoat && ShouldUseSwapFileForDexopt()) { + if (ShouldUseSwapFileForDexopt()) { // Make sure there really is enough space. size_t out_len = strlen(out_path); if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) { @@ -1120,9 +1119,10 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, exit(67); } - if (is_patchoat) { + if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED + || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); - } else { + } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) { const char *input_file_name = strrchr(input_file, '/'); if (input_file_name == NULL) { input_file_name = input_file; @@ -1131,6 +1131,9 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, } run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname, instruction_set, vm_safe_mode, debuggable); + } else { + ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); + exit(73); } exit(68); /* only get here on exec failure */ } else { @@ -1440,21 +1443,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; @@ -1623,14 +1621,12 @@ fail: return -1; } -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) { struct dirent *entry; DIR *d; struct stat s; - char *userdir; - char *primarydir; - char *pkgdir; int ret = 0; // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. @@ -1641,26 +1637,20 @@ int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) return -1; } - if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) { - return -1; - } - - // Relabel for primary user. - if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno)); - ret |= -1; - } + // Special case for owner on internal storage + if (uuid == nullptr) { + std::string path(create_package_data_path(nullptr, pkgName, 0)); - if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) { - free(primarydir); - return -1; + if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) { + PLOG(ERROR) << "restorecon failed for " << path; + ret |= -1; + } } // Relabel package directory for all secondary users. - d = opendir(userdir); + std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); + d = opendir(userdir.c_str()); if (d == NULL) { - free(primarydir); - free(userdir); return -1; } @@ -1681,25 +1671,18 @@ int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) continue; } - if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) { - continue; - } - - if (stat(pkgdir, &s) < 0) { - free(pkgdir); + std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName)); + if (stat(pkgdir.c_str(), &s) < 0) { continue; } - if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, s.st_uid, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno)); + if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) { + PLOG(ERROR) << "restorecon failed for " << pkgdir; ret |= -1; } - free(pkgdir); } closedir(d); - free(primarydir); - free(userdir); return ret; } @@ -1711,12 +1694,7 @@ int create_oat_dir(const char* oat_dir, const char* instruction_set) ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir); return -1; } - if ((mkdir(oat_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) && (errno != EEXIST)) { - ALOGE("cannot create dir '%s': %s\n", oat_dir, strerror(errno)); - return -1; - } - if (chmod(oat_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) { - ALOGE("cannot chmod dir '%s': %s\n", oat_dir, strerror(errno)); + if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { return -1; } if (selinux_android_restorecon(oat_dir, 0)) { @@ -1724,12 +1702,7 @@ int create_oat_dir(const char* oat_dir, const char* instruction_set) return -1; } snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set); - if ((mkdir(oat_instr_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) && (errno != EEXIST)) { - ALOGE("cannot create dir '%s': %s\n", oat_instr_dir, strerror(errno)); - return -1; - } - if (chmod(oat_instr_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) { - ALOGE("cannot chmod dir '%s': %s\n", oat_dir, strerror(errno)); + if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { return -1; } return 0; diff --git a/cmds/installd/installd.c b/cmds/installd/installd.cpp index 5b71175143..3a861812f4 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.cpp @@ -1,31 +1,40 @@ /* ** Copyright 2008, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ +#include "installd.h" + +#include <base/logging.h> + #include <sys/capability.h> #include <sys/prctl.h> #include <selinux/android.h> #include <selinux/avc.h> -#include "installd.h" - - #define BUFFER_MAX 1024 /* input buffer for commands */ #define TOKEN_MAX 16 /* max number of arguments in buffer */ #define REPLY_MAX 256 /* largest reply allowed */ +static char* parse_null(char* arg) { + if (strcmp(arg, "!") == 0) { + return nullptr; + } else { + return arg; + } +} + static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused) { return 0; @@ -33,15 +42,15 @@ 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(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); /* uuid, pkgname, uid, gid, seinfo */ } static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused) { - /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate - debuggable, outputPath */ - return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), 0, - atoi(arg[6]), arg[7]); + /* apk_path, uid, is_public, pkgname, instruction_set, + * dexopt_needed, vm_safe_mode, debuggable, oat_dir */ + return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), + atoi(arg[6]), atoi(arg[7]), arg[8]); } static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused) @@ -61,7 +70,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(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } static int do_rename(char **arg, char reply[REPLY_MAX] __unused) @@ -71,22 +80,22 @@ 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(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */ } static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int:free_size */ { - return free_cache((int64_t)atoll(arg[0])); /* free_size */ + return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */ } 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(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, 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(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } static int do_get_size(char **arg, char reply[REPLY_MAX]) @@ -97,9 +106,9 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int64_t asecsize = 0; int res = 0; - /* pkgdir, userid, apkpath */ - res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5], - arg[6], &codesize, &datasize, &cachesize, &asecsize); + /* uuid, pkgdir, userid, apkpath */ + res = get_size(parse_null(arg[0]), arg[1], atoi(arg[2]), arg[3], arg[4], arg[5], arg[6], + arg[7], &codesize, &datasize, &cachesize, &asecsize); /* * Each int64_t can take up 22 characters printed out. Make sure it @@ -112,13 +121,19 @@ 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(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ +} + +static int do_mv_user_data(char **arg, char reply[REPLY_MAX] __unused) +{ + // from_uuid, to_uuid, pkgname, appid, seinfo + return move_user_data(parse_null(arg[0]), parse_null(arg[1]), arg[2], atoi(arg[3]), arg[4]); } 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]); - /* pkgname, uid, userid, seinfo */ + return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); + /* uuid, pkgname, uid, userid, seinfo */ } static int do_mk_user_config(char **arg, char reply[REPLY_MAX] __unused) @@ -128,7 +143,7 @@ static int do_mk_user_config(char **arg, char reply[REPLY_MAX] __unused) static int do_rm_user(char **arg, char reply[REPLY_MAX] __unused) { - return delete_user(atoi(arg[0])); /* userid */ + return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */ } static int do_movefiles(char **arg __unused, char reply[REPLY_MAX] __unused) @@ -138,7 +153,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(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); } static int do_idmap(char **arg, char reply[REPLY_MAX] __unused) @@ -148,14 +163,8 @@ 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])); - /* pkgName, seinfo, uid*/ -} - -static int do_patchoat(char **arg, char reply[REPLY_MAX] __unused) { - /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate, - debuggable, outputPath */ - return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0, 1, 0, "!"); + return restorecon_data(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); + /* uuid, pkgName, seinfo, uid*/ } static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] __unused) @@ -178,34 +187,34 @@ struct cmdinfo { struct cmdinfo cmds[] = { { "ping", 0, do_ping }, - { "install", 4, do_install }, - { "dexopt", 8, do_dexopt }, + { "install", 5, do_install }, + { "dexopt", 9, do_dexopt }, { "markbootcomplete", 1, do_mark_boot_complete }, { "movedex", 3, do_move_dex }, { "rmdex", 2, do_rm_dex }, - { "remove", 2, do_remove }, + { "remove", 3, do_remove }, { "rename", 2, do_rename }, - { "fixuid", 3, do_fixuid }, - { "freecache", 1, do_free_cache }, - { "rmcache", 2, do_rm_cache }, - { "rmcodecache", 2, do_rm_code_cache }, - { "getsize", 7, do_get_size }, - { "rmuserdata", 2, do_rm_user_data }, + { "fixuid", 4, do_fixuid }, + { "freecache", 2, do_free_cache }, + { "rmcache", 3, do_rm_cache }, + { "rmcodecache", 3, do_rm_code_cache }, + { "getsize", 8, do_get_size }, + { "rmuserdata", 3, do_rm_user_data }, + { "mvuserdata", 5, do_mv_user_data }, { "movefiles", 0, do_movefiles }, - { "linklib", 3, do_linklib }, - { "mkuserdata", 4, do_mk_user_data }, + { "linklib", 4, do_linklib }, + { "mkuserdata", 5, do_mk_user_data }, { "mkuserconfig", 1, do_mk_user_config }, - { "rmuser", 1, do_rm_user }, + { "rmuser", 2, do_rm_user }, { "idmap", 3, do_idmap }, - { "restorecondata", 3, do_restorecon_data }, - { "patchoat", 5, do_patchoat }, + { "restorecondata", 4, do_restorecon_data }, { "createoatdir", 2, do_create_oat_dir }, { "rmpackagedir", 1, do_rm_package_dir}, }; static int readx(int s, void *_buf, int count) { - char *buf = _buf; + char *buf = (char *) _buf; int n = 0, r; if (count < 0) return -1; while (n < count) { @@ -226,7 +235,7 @@ static int readx(int s, void *_buf, int count) static int writex(int s, const void *_buf, int count) { - const char *buf = _buf; + const char *buf = (const char *) _buf; int n = 0, r; if (count < 0) return -1; while (n < count) { @@ -352,10 +361,15 @@ int initialize_globals() { return -1; } + // Get the android external app directory. + if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) { + return -1; + } + // Take note of the system and vendor directories. android_system_dirs.count = 4; - android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t)); + android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t)); if (android_system_dirs.dirs == NULL) { ALOGE("Couldn't allocate array for dirs; aborting\n"); return -1; @@ -373,10 +387,10 @@ int initialize_globals() { android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR); android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path); - android_system_dirs.dirs[2].path = "/vendor/app/"; + android_system_dirs.dirs[2].path = strdup("/vendor/app/"); android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path); - android_system_dirs.dirs[3].path = "/oem/app/"; + android_system_dirs.dirs[3].path = strdup("/oem/app/"); android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path); return 0; @@ -520,7 +534,7 @@ int initialize_directories() { version = 2; } - if (ensure_media_user_dirs(0) == -1) { + if (ensure_media_user_dirs(nullptr, 0) == -1) { ALOGE("Failed to setup media for user 0"); goto fail; } @@ -615,46 +629,6 @@ fail: return res; } -static void drop_privileges() { - if (prctl(PR_SET_KEEPCAPS, 1) < 0) { - ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); - exit(1); - } - - if (setgid(AID_INSTALL) < 0) { - ALOGE("setgid() can't drop privileges; exiting.\n"); - exit(1); - } - - if (setuid(AID_INSTALL) < 0) { - ALOGE("setuid() can't drop privileges; exiting.\n"); - exit(1); - } - - struct __user_cap_header_struct capheader; - struct __user_cap_data_struct capdata[2]; - memset(&capheader, 0, sizeof(capheader)); - memset(&capdata, 0, sizeof(capdata)); - capheader.version = _LINUX_CAPABILITY_VERSION_3; - capheader.pid = 0; - - capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE); - capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN); - capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID); - capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); - capdata[CAP_TO_INDEX(CAP_FOWNER)].permitted |= CAP_TO_MASK(CAP_FOWNER); - - capdata[0].effective = capdata[0].permitted; - capdata[1].effective = capdata[1].permitted; - capdata[0].inheritable = 0; - capdata[1].inheritable = 0; - - if (capset(&capheader, &capdata[0]) < 0) { - ALOGE("capset failed: %s\n", strerror(errno)); - exit(1); - } -} - static int log_callback(int type, const char *fmt, ...) { va_list ap; int priority; @@ -676,13 +650,16 @@ static int log_callback(int type, const char *fmt, ...) { return 0; } -int main(const int argc __unused, const char *argv[] __unused) { +int main(const int argc __unused, char *argv[]) { char buf[BUFFER_MAX]; struct sockaddr addr; socklen_t alen; int lsocket, s; int selinux_enabled = (is_selinux_enabled() > 0); + setenv("ANDROID_LOG_TAGS", "*:v", 1); + android::base::InitLogging(argv); + ALOGI("installd firing up\n"); union selinux_callback cb; @@ -704,8 +681,6 @@ int main(const int argc __unused, const char *argv[] __unused) { exit(1); } - drop_privileges(); - lsocket = android_get_control_socket(SOCKET_PATH); if (lsocket < 0) { ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 9c30a3592a..f31bf4f2a5 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -31,6 +31,8 @@ #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> +#include <string> +#include <vector> #include <cutils/fs.h> #include <cutils/sockets.h> @@ -83,6 +85,13 @@ #define PKG_NAME_MAX 128 /* largest allowed package name */ #define PKG_PATH_MAX 256 /* max size of any path we use */ +/* dexopt needed flags matching those in dalvik.system.DexFile */ +#define DEXOPT_DEX2OAT_NEEDED 1 +#define DEXOPT_PATCHOAT_NEEDED 2 +#define DEXOPT_SELF_PATCHOAT_NEEDED 3 + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) + /* data structures */ typedef struct { @@ -101,6 +110,7 @@ extern dir_rec_t android_app_lib_dir; extern dir_rec_t android_data_dir; extern dir_rec_t android_asec_dir; extern dir_rec_t android_media_dir; +extern dir_rec_t android_mnt_expand_dir; extern dir_rec_array_t android_system_dirs; typedef struct cache_dir_struct { @@ -132,20 +142,22 @@ 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); +// TODO: rename to create_data_user_package_path +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, const char *postfix, userid_t userid); -int create_user_path(char path[PKG_PATH_MAX], - userid_t userid); +std::string create_data_path(const char* volume_uuid); + +std::string create_data_user_path(const char* volume_uuid, userid_t userid); + +std::string create_data_media_path(const char* volume_uuid, userid_t userid); -int create_user_media_path(char path[PKG_PATH_MAX], userid_t userid); +std::vector<userid_t> get_known_users(const char* volume_uuid); int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid); @@ -169,13 +181,13 @@ int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t int lookup_media_dir(char basepath[PATH_MAX], const char *dir); -int64_t data_disk_free(); +int64_t data_disk_free(const std::string& data_path); cache_t* start_cache_collection(); void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir); -void clear_cache_files(cache_t* cache, int64_t free_size); +void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size); void finish_cache_collection(cache_t* cache); @@ -191,43 +203,48 @@ int validate_apk_path(const char *path); int append_and_increment(char** dst, const char* src, size_t* dst_size); -char *build_string2(char *s1, char *s2); -char *build_string3(char *s1, char *s2, char *s3); +char *build_string2(const char *s1, const char *s2); +char *build_string3(const char *s1, const char *s2, const char *s3); int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); -int ensure_media_user_dirs(userid_t userid); +int ensure_media_user_dirs(const char* uuid, userid_t userid); int ensure_config_user_dirs(userid_t userid); int create_profile_file(const char *pkgname, gid_t gid); 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 move_user_data(const char* from_uuid, const char *to_uuid, + const char *package_name, appid_t appid, 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_user(const char *uuid, 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); +int free_cache(const char *uuid, int64_t free_size); int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName, - const char *instruction_set, bool vm_safe_mode, bool should_relocate, bool debuggable, - const char* outputPath); + const char *instruction_set, int dexopt_needed, bool vm_safe_mode, + bool debuggable, const char* oat_dir); 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* pkgname, const char* asecLibDir, int userId); int idmap(const char *target_path, const char *overlay_path, uid_t uid); -int restorecon_data(); +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, - const char *instruction_set);
\ No newline at end of file + const char *instruction_set); +int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, + const char *instruction_set); diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk index 7300b298f0..38a9f69964 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 \ @@ -25,5 +26,6 @@ $(foreach file,$(test_src_files), \ $(eval LOCAL_SRC_FILES := $(file)) \ $(eval LOCAL_C_INCLUDES := $(c_includes)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ + $(eval LOCAL_CLANG := true) \ $(eval include $(BUILD_NATIVE_TEST)) \ ) diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index 94e4792826..4ce559d3c8 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -17,19 +17,18 @@ #include <stdlib.h> #include <string.h> -#define LOG_TAG "utils_test" -#include <utils/Log.h> - #include <gtest/gtest.h> -extern "C" { #include "installd.h" -} + +#undef LOG_TAG +#define LOG_TAG "utils_test" #define TEST_DATA_DIR "/data/" #define TEST_APP_DIR "/data/app/" #define TEST_APP_PRIVATE_DIR "/data/app-private/" #define TEST_ASEC_DIR "/mnt/asec/" +#define TEST_EXPAND_DIR "/mnt/expand/" #define TEST_SYSTEM_DIR1 "/system/app/" #define TEST_SYSTEM_DIR2 "/vendor/app/" @@ -49,25 +48,28 @@ namespace android { class UtilsTest : public testing::Test { protected: virtual void SetUp() { - android_app_dir.path = TEST_APP_DIR; + android_app_dir.path = (char*) TEST_APP_DIR; android_app_dir.len = strlen(TEST_APP_DIR); - android_app_private_dir.path = TEST_APP_PRIVATE_DIR; + android_app_private_dir.path = (char*) TEST_APP_PRIVATE_DIR; android_app_private_dir.len = strlen(TEST_APP_PRIVATE_DIR); - android_data_dir.path = TEST_DATA_DIR; + android_data_dir.path = (char*) TEST_DATA_DIR; android_data_dir.len = strlen(TEST_DATA_DIR); - android_asec_dir.path = TEST_ASEC_DIR; + android_asec_dir.path = (char*) TEST_ASEC_DIR; android_asec_dir.len = strlen(TEST_ASEC_DIR); + android_mnt_expand_dir.path = (char*) TEST_EXPAND_DIR; + android_mnt_expand_dir.len = strlen(TEST_EXPAND_DIR); + android_system_dirs.count = 2; android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t)); - android_system_dirs.dirs[0].path = TEST_SYSTEM_DIR1; + android_system_dirs.dirs[0].path = (char*) TEST_SYSTEM_DIR1; android_system_dirs.dirs[0].len = strlen(TEST_SYSTEM_DIR1); - android_system_dirs.dirs[1].path = TEST_SYSTEM_DIR2; + android_system_dirs.dirs[1].path = (char*) TEST_SYSTEM_DIR2; android_system_dirs.dirs[1].len = strlen(TEST_SYSTEM_DIR2); } @@ -319,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"; } @@ -369,40 +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 = "/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]; - - EXPECT_EQ(0, create_user_path(path, 0)) - << "Should successfully build primary user path."; - - EXPECT_STREQ("/data/data/", path) - << "Primary user should have correct path"; -} - -TEST_F(UtilsTest, CreatePersonaPath_Secondary) { - char path[PKG_PATH_MAX]; - - EXPECT_EQ(0, create_user_path(path, 1)) - << "Should successfully build primary user path."; - - EXPECT_STREQ("/data/user/1/", path) - << "Primary user should have correct path"; -} - TEST_F(UtilsTest, CreateMovePath_Primary) { char path[PKG_PATH_MAX]; @@ -432,7 +401,7 @@ TEST_F(UtilsTest, CopyAndAppend_Normal) { dir_rec_t dst; dir_rec_t src; - src.path = "/data/"; + src.path = (char*) "/data/"; src.len = strlen(src.path); EXPECT_EQ(0, copy_and_append(&dst, &src, "app/")) @@ -480,4 +449,40 @@ TEST_F(UtilsTest, AppendAndIncrement_TooBig) { << "String should fail because it's too large to fit"; } +TEST_F(UtilsTest, CreateDataPath) { + EXPECT_EQ("/data", create_data_path(nullptr)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b", + create_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b")); +} + +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("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0", + create_data_user_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)); +} + +TEST_F(UtilsTest, CreateDataMediaPath) { + EXPECT_EQ("/data/media/0", create_data_media_path(nullptr, 0)); + EXPECT_EQ("/data/media/10", create_data_media_path(nullptr, 10)); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/media/0", + create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/media/10", + create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); +} + +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.c b/cmds/installd/utils.cpp index 8f366a01ac..ba411cd478 100644 --- a/cmds/installd/utils.c +++ b/cmds/installd/utils.cpp @@ -16,137 +16,119 @@ #include "installd.h" -#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); - - 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; +#include <base/stringprintf.h> +#include <base/logging.h> - 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; - } +#define CACHE_NOISY(x) //x - return 0; -} +using android::base::StringPrintf; /** - * 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. + * Check that given string is valid filename, and that it attempts no + * parent or child directory traversal. */ -int create_pkg_path(char path[PKG_PATH_MAX], - const char *pkgname, - const char *postfix, - userid_t userid) -{ - size_t userid_len; - char* userid_prefix; - if (userid == 0) { - userid_prefix = PRIMARY_USER_PREFIX; - userid_len = 0; +static bool is_valid_filename(const std::string& name) { + if (name.empty() || (name == ".") || (name == "..") + || (name.find('/') != std::string::npos)) { + return false; } else { - userid_prefix = SECONDARY_USER_PREFIX; - userid_len = snprintf(NULL, 0, "%d", userid); + return true; } +} - const size_t prefix_len = android_data_dir.len + strlen(userid_prefix) - + userid_len + 1 /*slash*/; - char prefix[prefix_len + 1]; +/** + * 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. + */ +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); - char *dst = prefix; - size_t dst_size = sizeof(prefix); + return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name); +} - 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); +std::string create_data_path(const char* volume_uuid) { + if (volume_uuid == nullptr) { + return "/data"; + } else { + CHECK(is_valid_filename(volume_uuid)); + return StringPrintf("/mnt/expand/%s", volume_uuid); + } } /** * Create the path name for user data for a certain userid. - * Returns 0 on success, and -1 on failure. */ -int create_user_path(char path[PKG_PATH_MAX], - userid_t userid) -{ - size_t userid_len; - char* userid_prefix; - if (userid == 0) { - userid_prefix = PRIMARY_USER_PREFIX; - userid_len = 0; +std::string create_data_user_path(const char* volume_uuid, userid_t userid) { + std::string data(create_data_path(volume_uuid)); + if (volume_uuid == nullptr) { + if (userid == 0) { + return StringPrintf("%s/data", data.c_str()); + } else { + return StringPrintf("%s/user/%u", data.c_str(), userid); + } } else { - userid_prefix = SECONDARY_USER_PREFIX; - userid_len = snprintf(NULL, 0, "%d/", userid); + return StringPrintf("%s/user/%u", data.c_str(), userid); } +} - char *dst = path; - size_t dst_size = PKG_PATH_MAX; +/** + * Create the path name for media for a certain userid. + */ +std::string create_data_media_path(const char* volume_uuid, userid_t userid) { + return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid); +} - 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 user path"); - return -1; +std::vector<userid_t> get_known_users(const char* volume_uuid) { + std::vector<userid_t> users; + + // We always have an owner + users.push_back(0); + + std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX); + DIR* dir = opendir(path.c_str()); + if (dir == NULL) { + // Unable to discover other users, but at least return owner + PLOG(ERROR) << "Failed to opendir " << path; + return users; } - if (userid != 0) { - if (dst_size < userid_len + 1) { - ALOGE("Error building user path"); - return -1; + struct dirent* ent; + while ((ent = readdir(dir))) { + if (ent->d_type != DT_DIR) { + continue; } - int ret = snprintf(dst, dst_size, "%d/", userid); - if (ret < 0 || (size_t) ret != userid_len) { - ALOGE("Error appending userid to path"); - return -1; + + char* end; + userid_t user = strtol(ent->d_name, &end, 10); + if (*end == '\0' && user != 0) { + LOG(DEBUG) << "Found valid user " << user; + users.push_back(user); } } - return 0; -} + closedir(dir); -/** - * Create the path name for media for a certain userid. - * Returns 0 on success, and -1 on failure. - */ -int create_user_media_path(char path[PATH_MAX], userid_t userid) { - if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) { - return -1; - } - return 0; + return users; } /** @@ -182,6 +164,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 */ @@ -472,13 +458,13 @@ int lookup_media_dir(char basepath[PATH_MAX], const char *dir) return -1; } -int64_t data_disk_free() +int64_t data_disk_free(const std::string& data_path) { struct statfs sfs; - if (statfs(android_data_dir.path, &sfs) == 0) { + if (statfs(data_path.c_str(), &sfs) == 0) { return sfs.f_bavail * sfs.f_bsize; } else { - ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno)); + PLOG(ERROR) << "Couldn't statfs " << data_path; return -1; } } @@ -516,7 +502,7 @@ static void* _cache_malloc(cache_t* cache, size_t len) int8_t* res = cache->curMemBlockAvail; int8_t* nextPos = res + len; if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) { - int8_t* newBlock = malloc(CACHE_BLOCK_SIZE); + int8_t* newBlock = (int8_t*) malloc(CACHE_BLOCK_SIZE); if (newBlock == NULL) { return NULL; } @@ -836,7 +822,7 @@ static int cache_modtime_sort(const void *lhsP, const void *rhsP) return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0); } -void clear_cache_files(cache_t* cache, int64_t free_size) +void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size) { size_t i; int skip = 0; @@ -861,7 +847,7 @@ void clear_cache_files(cache_t* cache, int64_t free_size) for (i=0; i<cache->numFiles; i++) { skip++; if (skip > 10) { - if (data_disk_free() > free_size) { + if (data_disk_free(data_path) > free_size) { return; } skip = 0; @@ -910,14 +896,14 @@ void finish_cache_collection(cache_t* cache) * The path is allowed to have at most one subdirectory and no indirections * to top level directories (i.e. have ".."). */ -static int validate_path(const dir_rec_t* dir, const char* path) { +static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) { size_t dir_len = dir->len; const char* subdir = strchr(path + dir_len, '/'); // Only allow the path to have at most one subdirectory. if (subdir != NULL) { ++subdir; - if (strchr(subdir, '/') != NULL) { + if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) { ALOGE("invalid apk path '%s' (subdir?)\n", path); return -1; } @@ -942,7 +928,7 @@ int validate_system_app_path(const char* path) { for (i = 0; i < android_system_dirs.count; i++) { const size_t dir_len = android_system_dirs.dirs[i].len; if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { - return validate_path(android_system_dirs.dirs + i, path); + return validate_path(android_system_dirs.dirs + i, path, 1); } } @@ -1000,7 +986,7 @@ int get_path_from_string(dir_rec_t* rec, const char* path) { // Add space for slash and terminating null. size_t dst_size = path_len + 2; - rec->path = malloc(dst_size); + rec->path = (char*) malloc(dst_size); if (rec->path == NULL) { return -1; } @@ -1042,6 +1028,7 @@ int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { int validate_apk_path(const char *path) { const dir_rec_t* dir = NULL; + int maxSubdirs = 1; if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { dir = &android_app_dir; @@ -1049,11 +1036,14 @@ int validate_apk_path(const char *path) dir = &android_app_private_dir; } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { dir = &android_asec_dir; + } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) { + dir = &android_mnt_expand_dir; + maxSubdirs = 2; } else { return -1; } - return validate_path(dir, path); + return validate_path(dir, path, maxSubdirs); } int append_and_increment(char** dst, const char* src, size_t* dst_size) { @@ -1066,13 +1056,13 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size) { return 0; } -char *build_string2(char *s1, char *s2) { +char *build_string2(const char *s1, const char *s2) { if (s1 == NULL || s2 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len = len_s1 + len_s2 + 1; - char *result = malloc(len); + char *result = (char *) malloc(len); if (result == NULL) return NULL; strcpy(result, s1); @@ -1081,14 +1071,14 @@ char *build_string2(char *s1, char *s2) { return result; } -char *build_string3(char *s1, char *s2, char *s3) { +char *build_string3(const char *s1, const char *s2, const char *s3) { if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len_s3 = strlen(s3); int len = len_s1 + len_s2 + len_s3 + 1; - char *result = malloc(len); + char *result = (char *) malloc(len); if (result == NULL) return NULL; strcpy(result, s1); @@ -1099,12 +1089,9 @@ char *build_string3(char *s1, char *s2, char *s3) { } /* Ensure that /data/media directories are prepared for given user. */ -int ensure_media_user_dirs(userid_t userid) { - char media_user_path[PATH_MAX]; - - // Ensure /data/media/<userid> exists - create_user_media_path(media_user_path, userid); - if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { +int ensure_media_user_dirs(const char* uuid, userid_t userid) { + std::string media_user_path(create_data_media_path(uuid, userid)); + if (fs_prepare_dir(media_user_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { return -1; } diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h index ef0feab720..d56fa89b51 100644 --- a/include/gui/ConsumerBase.h +++ b/include/gui/ConsumerBase.h @@ -76,6 +76,9 @@ public: // when a new frame becomes available. void setFrameAvailableListener(const wp<FrameAvailableListener>& listener); + // See IGraphicBufferConsumer::detachBuffer + status_t detachBuffer(int slot); + private: ConsumerBase(const ConsumerBase&); void operator=(const ConsumerBase&); diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index b874e3a320..e576018bf2 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -163,6 +163,21 @@ void ConsumerBase::setFrameAvailableListener( mFrameAvailableListener = listener; } +status_t ConsumerBase::detachBuffer(int slot) { + CB_LOGV("detachBuffer"); + Mutex::Autolock lock(mMutex); + + status_t result = mConsumer->detachBuffer(slot); + if (result != NO_ERROR) { + CB_LOGE("Failed to detach buffer: %d", result); + return result; + } + + freeBufferLocked(slot); + + return result; +} + void ConsumerBase::dump(String8& result) const { dump(result, ""); } |