Merge "Fix a memory corruption issue when vector resize"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index f69a72d..a33dcf3 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -238,9 +238,6 @@
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 8224e94..6dec7f6 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_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 @@
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
similarity index 86%
rename from cmds/installd/commands.c
rename to cmds/installd/commands.cpp
index 48bccc3..de6fd96 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.cpp
@@ -14,14 +14,22 @@
** limitations under the License.
*/
+#include "installd.h"
+
+#include <base/stringprintf.h>
+#include <base/logging.h>
+#include <cutils/sched_policy.h>
+#include <diskusage/dirsize.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 "installd.h"
-#include <cutils/sched_policy.h>
-#include <diskusage/dirsize.h>
-#include <selinux/android.h>
-#include <system/thread_defs.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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 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 @@
}
}
- 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 @@
}
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 @@
}
}
- 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 @@
}
// 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 @@
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 @@
}
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 @@
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 @@
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 @@
return -1;
}
- if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) {
- return -1;
- }
+ // Special case for owner on internal storage
+ if (uuid == nullptr) {
+ std::string path(create_package_data_path(nullptr, pkgName, 0));
- // 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;
- }
-
- 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 @@
continue;
}
- if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) {
+ std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName));
+ if (stat(pkgdir.c_str(), &s) < 0) {
continue;
}
- if (stat(pkgdir, &s) < 0) {
- free(pkgdir);
- 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 @@
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 @@
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
similarity index 82%
rename from cmds/installd/installd.c
rename to cmds/installd/installd.cpp
index 5b71175..3a86181 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_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_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_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 @@
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_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_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_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_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 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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 9c30a35..f31bf4f 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_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 @@
/* 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);
-int create_user_media_path(char path[PKG_PATH_MAX], userid_t userid);
+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);
+
+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 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 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 7300b29..38a9f69 100644
--- a/cmds/installd/tests/Android.mk
+++ b/cmds/installd/tests/Android.mk
@@ -8,6 +8,7 @@
installd_utils_test.cpp
shared_libraries := \
+ libbase \
libutils \
libcutils \
@@ -25,5 +26,6 @@
$(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 94e4792..4ce559d 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 @@
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 @@
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 @@
<< "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 @@
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 @@
<< "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
similarity index 87%
rename from cmds/installd/utils.c
rename to cmds/installd/utils.cpp
index 8f366a0..ba411cd 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.cpp
@@ -16,137 +16,119 @@
#include "installd.h"
+#include <base/stringprintf.h>
+#include <base/logging.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);
+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;
- char* userid_prefix;
- if (userid == 0) {
- userid_prefix = PRIMARY_USER_PREFIX;
- userid_len = 0;
- } else {
- userid_prefix = SECONDARY_USER_PREFIX;
- userid_len = snprintf(NULL, 0, "%d", userid);
- }
+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);
- const size_t prefix_len = android_data_dir.len + strlen(userid_prefix)
- + userid_len + 1 /*slash*/;
- char prefix[prefix_len + 1];
+ return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name);
+}
- 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);
+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;
-
- 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;
- }
-
- if (userid != 0) {
- if (dst_size < userid_len + 1) {
- ALOGE("Error building user path");
- return -1;
- }
- int ret = snprintf(dst, dst_size, "%d/", userid);
- if (ret < 0 || (size_t) ret != userid_len) {
- ALOGE("Error appending userid to path");
- return -1;
- }
- }
- return 0;
}
/**
* 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;
+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);
+}
+
+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;
}
- return 0;
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_type != DT_DIR) {
+ continue;
+ }
+
+ 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);
+ }
+ }
+ closedir(dir);
+
+ return users;
}
/**
@@ -182,6 +164,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
// 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 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 @@
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 @@
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 @@
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 @@
}
/* 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 ef0feab..d56fa89 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -76,6 +76,9 @@
// 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 b874e3a..e576018 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -163,6 +163,21 @@
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, "");
}