Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 124198d8 authored by Kenny Root's avatar Kenny Root Committed by Android (Google) Code Review
Browse files

Merge "Update installd to allow multiuser"

parents 772a3b31 86c95845
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
ifneq ($(TARGET_SIMULATOR),true)

LOCAL_PATH := $(call my-dir)

common_src_files := \
    commands.c utils.c

#
# Static library used in testing and executable
#

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    installd.c commands.c utils.c
    $(common_src_files)

LOCAL_MODULE := libinstalld

LOCAL_MODULE_TAGS := eng tests

#LOCAL_C_INCLUDES := \
#    $(call include-path-for, system-core)/cutils
include $(BUILD_STATIC_LIBRARY)

#
# Executable
#

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    installd.c \
    $(common_src_files)

LOCAL_SHARED_LIBRARIES := \
    libcutils
+42 −62
Original line number Diff line number Diff line
@@ -17,6 +17,13 @@
#include "installd.h"
#include <diskusage/dirsize.h>

/* Directory records that are used in execution of commands. */
dir_rec_t android_data_dir;
dir_rec_t android_asec_dir;
dir_rec_t android_app_dir;
dir_rec_t android_app_private_dir;
dir_rec_array_t android_system_dirs;

int install(const char *pkgname, uid_t uid, gid_t gid)
{
    char pkgdir[PKG_PATH_MAX];
@@ -27,10 +34,15 @@ int install(const char *pkgname, uid_t uid, gid_t gid)
        return -1;
    }

    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
        LOGE("cannot create package path\n");
        return -1;
    if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
    }

    if (create_pkg_path(libdir, pkgname, PKG_LIB_POSTFIX, 0)) {
        LOGE("cannot create package lib path\n");
        return -1;
    }

    if (mkdir(pkgdir, 0751) < 0) {
        LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
@@ -59,7 +71,7 @@ int uninstall(const char *pkgname)
{
    char pkgdir[PKG_PATH_MAX];

    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0))
        return -1;

        /* delete contents AND directory, no exceptions */
@@ -71,9 +83,9 @@ int renamepkg(const char *oldpkgname, const char *newpkgname)
    char oldpkgdir[PKG_PATH_MAX];
    char newpkgdir[PKG_PATH_MAX];

    if (create_pkg_path(oldpkgdir, PKG_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX))
    if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
        return -1;
    if (create_pkg_path(newpkgdir, PKG_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX))
    if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
        return -1;

    if (rename(oldpkgdir, newpkgdir) < 0) {
@@ -87,7 +99,7 @@ int delete_user_data(const char *pkgname)
{
    char pkgdir[PKG_PATH_MAX];

    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0))
        return -1;

        /* delete contents, excluding "lib", but not the directory itself */
@@ -98,7 +110,7 @@ int delete_cache(const char *pkgname)
{
    char cachedir[PKG_PATH_MAX];

    if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, 0))
        return -1;

        /* delete contents, not the directory, no exceptions */
@@ -108,10 +120,10 @@ int delete_cache(const char *pkgname)
static int64_t disk_free()
{
    struct statfs sfs;
    if (statfs(PKG_DIR_PREFIX, &sfs) == 0) {
    if (statfs(android_data_dir.path, &sfs) == 0) {
        return sfs.f_bavail * sfs.f_bsize;
    } else {
        LOGE("Couldn't statfs " PKG_DIR_PREFIX ": %s\n", strerror(errno));
        LOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
        return -1;
    }
}
@@ -137,9 +149,9 @@ int free_cache(int64_t free_size)
    LOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
    if (avail >= free_size) return 0;

    d = opendir(PKG_DIR_PREFIX);
    d = opendir(android_data_dir.path);
    if (d == NULL) {
        LOGE("cannot open %s: %s\n", PKG_DIR_PREFIX, strerror(errno));
        LOGE("cannot open %s: %s\n", android_data_dir.path, strerror(errno));
        return -1;
    }
    dfd = dirfd(d);
@@ -172,43 +184,13 @@ int free_cache(int64_t free_size)
    return -1;
}

/* used by move_dex, rm_dex, etc to ensure that the provided paths
 * don't point anywhere other than at the APK_DIR_PREFIX
 */
static int is_valid_apk_path(const char *path)
{
    int len = strlen(APK_DIR_PREFIX);
int nosubdircheck = 0;
    if (strncmp(path, APK_DIR_PREFIX, len)) {
        len = strlen(PROTECTED_DIR_PREFIX);
        if (strncmp(path, PROTECTED_DIR_PREFIX, len)) {
            len = strlen(SDCARD_DIR_PREFIX);
            if (strncmp(path, SDCARD_DIR_PREFIX, len)) {
                LOGE("invalid apk path '%s' (bad prefix)\n", path);
                return 0;
            } else {
                nosubdircheck = 1;
            }
        }
    }
    if ((nosubdircheck != 1) && strchr(path + len, '/')) {
        LOGE("invalid apk path '%s' (subdir?)\n", path);
        return 0;
    }
    if (path[len] == '.') {
        LOGE("invalid apk path '%s' (trickery)\n", path);
        return 0;
    }
    return 1;
}

int move_dex(const char *src, const char *dst)
{
    char src_dex[PKG_PATH_MAX];
    char dst_dex[PKG_PATH_MAX];

    if (!is_valid_apk_path(src)) return -1;
    if (!is_valid_apk_path(dst)) return -1;
    if (validate_apk_path(src)) return -1;
    if (validate_apk_path(dst)) return -1;

    if (create_cache_path(src_dex, src)) return -1;
    if (create_cache_path(dst_dex, dst)) return -1;
@@ -226,7 +208,7 @@ int rm_dex(const char *path)
{
    char dex_path[PKG_PATH_MAX];

    if (!is_valid_apk_path(path)) return -1;
    if (validate_apk_path(path)) return -1;
    if (create_cache_path(dex_path, path)) return -1;

    LOGI("unlink %s\n", dex_path);
@@ -245,7 +227,7 @@ int protect(char *pkgname, gid_t gid)

    if (gid < AID_SYSTEM) return -1;

    if (create_pkg_path(pkgpath, PROTECTED_DIR_PREFIX, pkgname, ".apk"))
    if (create_pkg_path_in_dir(pkgpath, &android_app_private_dir, pkgname, ".apk"))
        return -1;

    if (stat(pkgpath, &s) < 0) return -1;
@@ -280,8 +262,8 @@ int get_size(const char *pkgname, const char *apkpath,
        /* count the source apk as code -- but only if it's not
         * on the /system partition and its not on the sdcard.
         */
    if (strncmp(apkpath, "/system", 7) != 0 &&
            strncmp(apkpath, SDCARD_DIR_PREFIX, 7) != 0) {
    if (validate_system_app_path(apkpath) &&
            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
        if (stat(apkpath, &s) == 0) {
            codesize += stat_size(&s);
        }
@@ -300,7 +282,7 @@ int get_size(const char *pkgname, const char *apkpath,
        }
    }

    if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
        goto done;
    }

@@ -544,15 +526,15 @@ fail:
}

int create_move_path(char path[PKG_PATH_MAX],
    const char* prefix,
    const char* pkgname,
    const char* leaf)
    const char* leaf,
    uid_t persona)
{
    if ((strlen(prefix) + strlen(pkgname) + strlen(leaf) + 1) >= PKG_PATH_MAX) {
    if ((android_data_dir.len + strlen(pkgname) + strlen(leaf) + 1) >= PKG_PATH_MAX) {
        return -1;
    }
    
    sprintf(path, "%s%s/%s", prefix, pkgname, leaf);
    sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
    return 0;
}

@@ -720,8 +702,8 @@ int movefiles()
                            // Skip -- source package no longer exists.
                        } else {
                            LOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
                            if (!create_move_path(srcpath, PKG_DIR_PREFIX, srcpkg, buf+bufp) &&
                                    !create_move_path(dstpath, PKG_DIR_PREFIX, dstpkg, buf+bufp)) {
                            if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
                                    !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
                                movefileordir(srcpath, dstpath,
                                        strlen(dstpath)-strlen(buf+bufp),
                                        dstuid, dstgid, &s);
@@ -750,8 +732,7 @@ int movefiles()
                                        UPDATE_COMMANDS_DIR_PREFIX, name, div);
                            }
                            if (srcpkg[0] != 0) {
                                if (!create_pkg_path(srcpath, PKG_DIR_PREFIX, srcpkg,
                                        PKG_DIR_POSTFIX)) {
                                if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
                                    if (lstat(srcpath, &s) < 0) {
                                        // Package no longer exists -- skip.
                                        srcpkg[0] = 0;
@@ -762,8 +743,7 @@ int movefiles()
                                            div, UPDATE_COMMANDS_DIR_PREFIX, name);
                                }
                                if (srcpkg[0] != 0) {
                                    if (!create_pkg_path(dstpath, PKG_DIR_PREFIX, dstpkg,
                                            PKG_DIR_POSTFIX)) {
                                    if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
                                        if (lstat(dstpath, &s) == 0) {
                                            dstuid = s.st_uid;
                                            dstgid = s.st_gid;
+66 −2
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#define TOKEN_MAX     8     /* max number of arguments in buffer */
#define REPLY_MAX     256   /* largest reply allowed */


static int do_ping(char **arg, char reply[REPLY_MAX])
{
    return 0;
@@ -235,12 +234,77 @@ done:
    return 0;
}

/**
 * Initialize all the global variables that are used elsewhere. Returns 0 upon
 * success and -1 on error.
 */
void free_globals() {
    size_t i;

    for (i = 0; i < android_system_dirs.count; i++) {
        if (android_system_dirs.dirs[i].path != NULL) {
            free(android_system_dirs.dirs[i].path);
        }
    }

    free(android_system_dirs.dirs);
}

int initialize_globals() {
    // Get the android data directory.
    if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
        return -1;
    }

    // Get the android app directory.
    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
        return -1;
    }

    // Get the android protected app directory.
    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
        return -1;
    }

    // Get the sd-card ASEC mount point.
    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
        return -1;
    }

    // Take note of the system and vendor directories.
    android_system_dirs.count = 2;

    android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
    if (android_system_dirs.dirs == NULL) {
        LOGE("Couldn't allocate array for dirs; aborting\n");
        return -1;
    }

    // system
    if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) {
        free_globals();
        return -1;
    }

    // vendor
    // TODO replace this with an environment variable (doesn't exist yet)
    android_system_dirs.dirs[1].path = "/vendor/";
    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);

    return 0;
}

int main(const int argc, const char *argv[]) {
    char buf[BUFFER_MAX];
    struct sockaddr addr;
    socklen_t alen;
    int lsocket, s, count;

    if (initialize_globals() < 0) {
        LOGE("Could not initialize globals; exiting.\n");
        exit(1);
    }

    lsocket = android_get_control_socket(SOCKET_PATH);
    if (lsocket < 0) {
        LOGE("Failed to get socket from environment: %s\n", strerror(errno));
+45 −10
Original line number Diff line number Diff line
@@ -49,21 +49,20 @@

/* elements combined with a valid package name to form paths */

#define PKG_DIR_PREFIX         "/data/data/"
#define PRIMARY_USER_PREFIX    "data/"
#define SECONDARY_USER_PREFIX  "user/"

#define PKG_DIR_POSTFIX        ""

#define PKG_LIB_PREFIX         "/data/data/"
#define PKG_LIB_POSTFIX        "/lib"

#define CACHE_DIR_PREFIX       "/data/data/"
#define CACHE_DIR_POSTFIX      "/cache"

#define APK_DIR_PREFIX         "/data/app/"
#define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA

/* other handy constants */

#define PROTECTED_DIR_PREFIX  "/data/app-private/"
#define SDCARD_DIR_PREFIX  getenv("ASEC_MOUNTPOINT")
#define PRIVATE_APP_SUBDIR     "app-private/" // sub-directory under ANDROID_DATA

#define DALVIK_CACHE_PREFIX    "/data/dalvik-cache/"
#define DALVIK_CACHE_POSTFIX   "/classes.dex"
@@ -73,14 +72,38 @@
#define PKG_NAME_MAX  128   /* largest allowed package name */
#define PKG_PATH_MAX  256   /* max size of any path we use */

/* data structures */

typedef struct {
    char* path;
    size_t len;
} dir_rec_t;

typedef struct {
    size_t count;
    dir_rec_t* dirs;
} dir_rec_array_t;

extern dir_rec_t android_app_dir;
extern dir_rec_t android_app_private_dir;
extern dir_rec_t android_data_dir;
extern dir_rec_t android_asec_dir;
extern dir_rec_array_t android_system_dirs;

/* util.c */

int create_pkg_path(char path[PKG_PATH_MAX],
                    const char *prefix,
int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
                                const dir_rec_t* dir,
                                const char* pkgname,
                                const char* postfix);

int create_pkg_path(char path[PKG_PATH_MAX],
                    const char *pkgname,
                    const char *postfix,
                    uid_t persona);

int is_valid_package_name(const char* pkgname);

int create_cache_path(char path[PKG_PATH_MAX], const char *src);

int delete_dir_contents(const char *pathname,
@@ -89,6 +112,18 @@ int delete_dir_contents(const char *pathname,

int delete_dir_contents_fd(int dfd, const char *name);

int validate_system_app_path(const char* path);

int get_path_from_env(dir_rec_t* rec, const char* var);

int get_path_from_string(dir_rec_t* rec, const char* path);

int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);

int validate_apk_path(const char *path);

int append_and_increment(char** dst, const char* src, size_t* dst_size);

/* commands.c */

int install(const char *pkgname, uid_t uid, gid_t gid);
+42 −0
Original line number Diff line number Diff line
# Build the unit tests for installd
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

ifneq ($(TARGET_SIMULATOR),true)

# Build the unit tests.
test_src_files := \
    installd_utils_test.cpp

shared_libraries := \
    libutils \
    libcutils \
    libstlport

static_libraries := \
    libinstalld \
    libdiskusage \
    libgtest \
    libgtest_main

c_includes := \
    frameworks/base/cmds/installd \
    bionic \
    bionic/libstdc++/include \
    external/gtest/include \
    external/stlport/stlport

module_tags := eng tests

$(foreach file,$(test_src_files), \
    $(eval include $(CLEAR_VARS)) \
    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
    $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
    $(eval LOCAL_SRC_FILES := $(file)) \
    $(eval LOCAL_C_INCLUDES := $(c_includes)) \
    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
    $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
    $(eval include $(BUILD_EXECUTABLE)) \
)

endif
Loading