Loading cmds/installd/commands.c +23 −3 Original line number Original line Diff line number Diff line Loading @@ -213,18 +213,30 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona) int delete_persona(uid_t persona) int delete_persona(uid_t persona) { { char pkgdir[PKG_PATH_MAX]; char data_path[PKG_PATH_MAX]; if (create_persona_path(data_path, persona)) { return -1; } if (delete_dir_contents(data_path, 1, NULL)) { return -1; } if (create_persona_path(pkgdir, persona)) char media_path[PATH_MAX]; if (create_persona_media_path(media_path, (userid_t) persona) == -1) { return -1; } if (delete_dir_contents(media_path, 1, NULL) == -1) { return -1; return -1; } return delete_dir_contents(pkgdir, 1, NULL); return 0; } } int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) { { char src_data_dir[PKG_PATH_MAX]; char src_data_dir[PKG_PATH_MAX]; char pkg_path[PKG_PATH_MAX]; char pkg_path[PKG_PATH_MAX]; char media_path[PATH_MAX]; DIR *d; DIR *d; struct dirent *de; struct dirent *de; struct stat s; struct stat s; Loading @@ -233,6 +245,9 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) if (create_persona_path(src_data_dir, src_persona)) { if (create_persona_path(src_data_dir, src_persona)) { return -1; return -1; } } if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) { return -1; } d = opendir(src_data_dir); d = opendir(src_data_dir); if (d != NULL) { if (d != NULL) { Loading Loading @@ -260,6 +275,11 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) } } closedir(d); closedir(d); } } // ensure /data/media/<user_id> exists if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { return -1; } return 0; return 0; } } Loading cmds/installd/installd.c +94 −22 Original line number Original line Diff line number Diff line Loading @@ -331,37 +331,109 @@ int initialize_globals() { } } int initialize_directories() { int initialize_directories() { int res = -1; int version = 0; FILE* file; // Read current filesystem layout version to handle upgrade paths char version_path[PATH_MAX]; if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) { return -1; } file = fopen(version_path, "r"); if (file != NULL) { fscanf(file, "%d", &version); fclose(file); } // /data/user // /data/user char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); // /data/data // /data/data char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); // /data/user/0 // /data/user/0 char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0"); "0"); if (!user_data_dir || !legacy_data_dir || !primary_data_dir) { int ret = -1; goto fail; if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) { } ret = 0; // Make the /data/user directory if necessary // Make the /data/user directory if necessary if (access(user_data_dir, R_OK) < 0) { if (access(user_data_dir, R_OK) < 0) { if (mkdir(user_data_dir, 0711) < 0) { if (mkdir(user_data_dir, 0711) < 0) { return -1; goto fail; } } if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { return -1; goto fail; } } if (chmod(user_data_dir, 0711) < 0) { if (chmod(user_data_dir, 0711) < 0) { return -1; goto fail; } } } } // Make the /data/user/0 symlink to /data/data if necessary // Make the /data/user/0 symlink to /data/data if necessary if (access(primary_data_dir, R_OK) < 0) { if (access(primary_data_dir, R_OK) < 0) { ret = symlink(legacy_data_dir, primary_data_dir); if (symlink(legacy_data_dir, primary_data_dir)) { goto fail; } } // /data/media/0 char owner_media_dir[PATH_MAX]; create_persona_media_path(owner_media_dir, 0); if (version == 0) { // Introducing multi-user, so migrate /data/media contents into /data/media/0 ALOGD("Migrating /data/media for multi-user"); // /data/media.tmp char media_tmp_dir[PATH_MAX]; snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path); // Only copy when upgrade not already in progress if (access(media_tmp_dir, F_OK) == -1) { if (rename(android_media_dir.path, media_tmp_dir) == -1) { ALOGE("Failed to move legacy media path: %s", strerror(errno)); goto fail; } } } // Create /data/media again if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // Move any owner data into place if (access(media_tmp_dir, F_OK) == 0) { if (rename(media_tmp_dir, owner_media_dir) == -1) { ALOGE("Failed to move owner media path: %s", strerror(errno)); goto fail; } } version = 1; } // Ensure /data/media/0 is always ready if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // Persist our current version file = fopen(version_path, "w"); if (file != NULL) { fprintf(file, "%d", version); fsync(fileno(file)); fclose(file); } else { ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); goto fail; } // Success! res = 0; fail: free(user_data_dir); free(user_data_dir); free(legacy_data_dir); free(legacy_data_dir); free(primary_data_dir); free(primary_data_dir); } return res; return ret; } } int main(const int argc, const char *argv[]) { int main(const int argc, const char *argv[]) { Loading cmds/installd/installd.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <cutils/sockets.h> #include <cutils/sockets.h> #include <cutils/log.h> #include <cutils/log.h> #include <cutils/properties.h> #include <cutils/properties.h> #include <cutils/multiuser.h> #include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h> Loading Loading @@ -138,6 +139,8 @@ int create_pkg_path(char path[PKG_PATH_MAX], int create_persona_path(char path[PKG_PATH_MAX], int create_persona_path(char path[PKG_PATH_MAX], uid_t persona); uid_t persona); int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid); int create_move_path(char path[PKG_PATH_MAX], int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* pkgname, const char* leaf, const char* leaf, Loading Loading @@ -180,6 +183,8 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size); char *build_string2(char *s1, char *s2); char *build_string2(char *s1, char *s2); char *build_string3(char *s1, char *s2, char *s3); char *build_string3(char *s1, char *s2, char *s3); int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); /* commands.c */ /* commands.c */ int install(const char *pkgname, uid_t uid, gid_t gid); int install(const char *pkgname, uid_t uid, gid_t gid); Loading cmds/installd/utils.c +50 −0 Original line number Original line Diff line number Diff line Loading @@ -137,6 +137,17 @@ int create_persona_path(char path[PKG_PATH_MAX], return 0; return 0; } } /** * Create the path name for media for a certain persona. * Returns 0 on success, and -1 on failure. */ int create_persona_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; } int create_move_path(char path[PKG_PATH_MAX], int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* pkgname, const char* leaf, const char* leaf, Loading Loading @@ -979,3 +990,42 @@ char *build_string3(char *s1, char *s2, char *s3) { return result; return result; } } /* Ensure that directory exists with given mode and owners. */ int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { // Check if path needs to be created struct stat sb; if (stat(path, &sb) == -1) { if (errno == ENOENT) { goto create; } else { ALOGE("Failed to stat(%s): %s", path, strerror(errno)); return -1; } } // Exists, verify status if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) { return 0; } else { goto fixup; } create: if (mkdir(path, mode) == -1) { ALOGE("Failed to mkdir(%s): %s", path, strerror(errno)); return -1; } fixup: if (chown(path, uid, gid) == -1) { ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno)); return -1; } if (chmod(path, mode) == -1) { ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno)); return -1; } return 0; } core/java/android/os/Process.java +10 −3 Original line number Original line Diff line number Diff line Loading @@ -376,12 +376,13 @@ public class Process { public static final ProcessStartResult start(final String processClass, public static final ProcessStartResult start(final String processClass, final String niceName, final String niceName, int uid, int gid, int[] gids, int uid, int gid, int[] gids, int debugFlags, int targetSdkVersion, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String seInfo, String[] zygoteArgs) { String[] zygoteArgs) { try { try { return startViaZygote(processClass, niceName, uid, gid, gids, return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, targetSdkVersion, seInfo, zygoteArgs); debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs); } catch (ZygoteStartFailedEx ex) { } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, Log.e(LOG_TAG, "Starting VM process through Zygote failed"); "Starting VM process through Zygote failed"); Loading Loading @@ -553,7 +554,8 @@ public class Process { final String niceName, final String niceName, final int uid, final int gid, final int uid, final int gid, final int[] gids, final int[] gids, int debugFlags, int targetSdkVersion, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String seInfo, String[] extraArgs) String[] extraArgs) throws ZygoteStartFailedEx { throws ZygoteStartFailedEx { Loading @@ -580,6 +582,11 @@ public class Process { if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); argsForZygote.add("--enable-assert"); } } if (mountExternal == Zygote.MOUNT_EXTERNAL_SINGLEUSER) { argsForZygote.add("--mount-external-singleuser"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) { argsForZygote.add("--mount-external-multiuser"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); argsForZygote.add("--target-sdk-version=" + targetSdkVersion); //TODO optionally enable debuger //TODO optionally enable debuger Loading Loading
cmds/installd/commands.c +23 −3 Original line number Original line Diff line number Diff line Loading @@ -213,18 +213,30 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona) int delete_persona(uid_t persona) int delete_persona(uid_t persona) { { char pkgdir[PKG_PATH_MAX]; char data_path[PKG_PATH_MAX]; if (create_persona_path(data_path, persona)) { return -1; } if (delete_dir_contents(data_path, 1, NULL)) { return -1; } if (create_persona_path(pkgdir, persona)) char media_path[PATH_MAX]; if (create_persona_media_path(media_path, (userid_t) persona) == -1) { return -1; } if (delete_dir_contents(media_path, 1, NULL) == -1) { return -1; return -1; } return delete_dir_contents(pkgdir, 1, NULL); return 0; } } int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) { { char src_data_dir[PKG_PATH_MAX]; char src_data_dir[PKG_PATH_MAX]; char pkg_path[PKG_PATH_MAX]; char pkg_path[PKG_PATH_MAX]; char media_path[PATH_MAX]; DIR *d; DIR *d; struct dirent *de; struct dirent *de; struct stat s; struct stat s; Loading @@ -233,6 +245,9 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) if (create_persona_path(src_data_dir, src_persona)) { if (create_persona_path(src_data_dir, src_persona)) { return -1; return -1; } } if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) { return -1; } d = opendir(src_data_dir); d = opendir(src_data_dir); if (d != NULL) { if (d != NULL) { Loading Loading @@ -260,6 +275,11 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) } } closedir(d); closedir(d); } } // ensure /data/media/<user_id> exists if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { return -1; } return 0; return 0; } } Loading
cmds/installd/installd.c +94 −22 Original line number Original line Diff line number Diff line Loading @@ -331,37 +331,109 @@ int initialize_globals() { } } int initialize_directories() { int initialize_directories() { int res = -1; int version = 0; FILE* file; // Read current filesystem layout version to handle upgrade paths char version_path[PATH_MAX]; if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) { return -1; } file = fopen(version_path, "r"); if (file != NULL) { fscanf(file, "%d", &version); fclose(file); } // /data/user // /data/user char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); // /data/data // /data/data char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); // /data/user/0 // /data/user/0 char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0"); "0"); if (!user_data_dir || !legacy_data_dir || !primary_data_dir) { int ret = -1; goto fail; if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) { } ret = 0; // Make the /data/user directory if necessary // Make the /data/user directory if necessary if (access(user_data_dir, R_OK) < 0) { if (access(user_data_dir, R_OK) < 0) { if (mkdir(user_data_dir, 0711) < 0) { if (mkdir(user_data_dir, 0711) < 0) { return -1; goto fail; } } if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { return -1; goto fail; } } if (chmod(user_data_dir, 0711) < 0) { if (chmod(user_data_dir, 0711) < 0) { return -1; goto fail; } } } } // Make the /data/user/0 symlink to /data/data if necessary // Make the /data/user/0 symlink to /data/data if necessary if (access(primary_data_dir, R_OK) < 0) { if (access(primary_data_dir, R_OK) < 0) { ret = symlink(legacy_data_dir, primary_data_dir); if (symlink(legacy_data_dir, primary_data_dir)) { goto fail; } } // /data/media/0 char owner_media_dir[PATH_MAX]; create_persona_media_path(owner_media_dir, 0); if (version == 0) { // Introducing multi-user, so migrate /data/media contents into /data/media/0 ALOGD("Migrating /data/media for multi-user"); // /data/media.tmp char media_tmp_dir[PATH_MAX]; snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path); // Only copy when upgrade not already in progress if (access(media_tmp_dir, F_OK) == -1) { if (rename(android_media_dir.path, media_tmp_dir) == -1) { ALOGE("Failed to move legacy media path: %s", strerror(errno)); goto fail; } } } // Create /data/media again if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // Move any owner data into place if (access(media_tmp_dir, F_OK) == 0) { if (rename(media_tmp_dir, owner_media_dir) == -1) { ALOGE("Failed to move owner media path: %s", strerror(errno)); goto fail; } } version = 1; } // Ensure /data/media/0 is always ready if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // Persist our current version file = fopen(version_path, "w"); if (file != NULL) { fprintf(file, "%d", version); fsync(fileno(file)); fclose(file); } else { ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); goto fail; } // Success! res = 0; fail: free(user_data_dir); free(user_data_dir); free(legacy_data_dir); free(legacy_data_dir); free(primary_data_dir); free(primary_data_dir); } return res; return ret; } } int main(const int argc, const char *argv[]) { int main(const int argc, const char *argv[]) { Loading
cmds/installd/installd.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <cutils/sockets.h> #include <cutils/sockets.h> #include <cutils/log.h> #include <cutils/log.h> #include <cutils/properties.h> #include <cutils/properties.h> #include <cutils/multiuser.h> #include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h> Loading Loading @@ -138,6 +139,8 @@ int create_pkg_path(char path[PKG_PATH_MAX], int create_persona_path(char path[PKG_PATH_MAX], int create_persona_path(char path[PKG_PATH_MAX], uid_t persona); uid_t persona); int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid); int create_move_path(char path[PKG_PATH_MAX], int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* pkgname, const char* leaf, const char* leaf, Loading Loading @@ -180,6 +183,8 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size); char *build_string2(char *s1, char *s2); char *build_string2(char *s1, char *s2); char *build_string3(char *s1, char *s2, char *s3); char *build_string3(char *s1, char *s2, char *s3); int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); /* commands.c */ /* commands.c */ int install(const char *pkgname, uid_t uid, gid_t gid); int install(const char *pkgname, uid_t uid, gid_t gid); Loading
cmds/installd/utils.c +50 −0 Original line number Original line Diff line number Diff line Loading @@ -137,6 +137,17 @@ int create_persona_path(char path[PKG_PATH_MAX], return 0; return 0; } } /** * Create the path name for media for a certain persona. * Returns 0 on success, and -1 on failure. */ int create_persona_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; } int create_move_path(char path[PKG_PATH_MAX], int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* pkgname, const char* leaf, const char* leaf, Loading Loading @@ -979,3 +990,42 @@ char *build_string3(char *s1, char *s2, char *s3) { return result; return result; } } /* Ensure that directory exists with given mode and owners. */ int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { // Check if path needs to be created struct stat sb; if (stat(path, &sb) == -1) { if (errno == ENOENT) { goto create; } else { ALOGE("Failed to stat(%s): %s", path, strerror(errno)); return -1; } } // Exists, verify status if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) { return 0; } else { goto fixup; } create: if (mkdir(path, mode) == -1) { ALOGE("Failed to mkdir(%s): %s", path, strerror(errno)); return -1; } fixup: if (chown(path, uid, gid) == -1) { ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno)); return -1; } if (chmod(path, mode) == -1) { ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno)); return -1; } return 0; }
core/java/android/os/Process.java +10 −3 Original line number Original line Diff line number Diff line Loading @@ -376,12 +376,13 @@ public class Process { public static final ProcessStartResult start(final String processClass, public static final ProcessStartResult start(final String processClass, final String niceName, final String niceName, int uid, int gid, int[] gids, int uid, int gid, int[] gids, int debugFlags, int targetSdkVersion, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String seInfo, String[] zygoteArgs) { String[] zygoteArgs) { try { try { return startViaZygote(processClass, niceName, uid, gid, gids, return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, targetSdkVersion, seInfo, zygoteArgs); debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs); } catch (ZygoteStartFailedEx ex) { } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, Log.e(LOG_TAG, "Starting VM process through Zygote failed"); "Starting VM process through Zygote failed"); Loading Loading @@ -553,7 +554,8 @@ public class Process { final String niceName, final String niceName, final int uid, final int gid, final int uid, final int gid, final int[] gids, final int[] gids, int debugFlags, int targetSdkVersion, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String seInfo, String[] extraArgs) String[] extraArgs) throws ZygoteStartFailedEx { throws ZygoteStartFailedEx { Loading @@ -580,6 +582,11 @@ public class Process { if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); argsForZygote.add("--enable-assert"); } } if (mountExternal == Zygote.MOUNT_EXTERNAL_SINGLEUSER) { argsForZygote.add("--mount-external-singleuser"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) { argsForZygote.add("--mount-external-multiuser"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); argsForZygote.add("--target-sdk-version=" + targetSdkVersion); //TODO optionally enable debuger //TODO optionally enable debuger Loading