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

Commit c200d20e authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

am dfc30ae3: Merge "Command to move private app data between volumes."

* commit 'dfc30ae3':
  Command to move private app data between volumes.
parents 997eb5dd dfc30ae3
Loading
Loading
Loading
Loading
+5 −1
Original line number Original line Diff line number Diff line
@@ -12,7 +12,10 @@ LOCAL_MODULE := libinstalld
LOCAL_MODULE_TAGS := eng tests
LOCAL_MODULE_TAGS := eng tests
LOCAL_SRC_FILES := $(common_src_files)
LOCAL_SRC_FILES := $(common_src_files)
LOCAL_CFLAGS := $(common_cflags)
LOCAL_CFLAGS := $(common_cflags)
LOCAL_SHARED_LIBRARIES := libbase
LOCAL_SHARED_LIBRARIES := \
    libbase \
    liblogwrap \

LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
LOCAL_CLANG := true
LOCAL_CLANG := true
include $(BUILD_STATIC_LIBRARY)
include $(BUILD_STATIC_LIBRARY)
@@ -30,6 +33,7 @@ LOCAL_SHARED_LIBRARIES := \
    libbase \
    libbase \
    libcutils \
    libcutils \
    liblog \
    liblog \
    liblogwrap \
    libselinux \
    libselinux \


LOCAL_STATIC_LIBRARIES := libdiskusage
LOCAL_STATIC_LIBRARIES := libdiskusage
+86 −7
Original line number Original line Diff line number Diff line
@@ -16,15 +16,18 @@


#include "installd.h"
#include "installd.h"


#include <inttypes.h>
#include <base/stringprintf.h>
#include <sys/capability.h>
#include <base/logging.h>
#include <sys/file.h>
#include <cutils/sched_policy.h>
#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
#include <diskusage/dirsize.h>
#include <selinux/android.h>
#include <logwrap/logwrap.h>
#include <system/thread_defs.h>
#include <system/thread_defs.h>
#include <base/stringprintf.h>
#include <selinux/android.h>
#include <base/logging.h>

#include <inttypes.h>
#include <sys/capability.h>
#include <sys/file.h>
#include <unistd.h>


using android::base::StringPrintf;
using android::base::StringPrintf;


@@ -38,6 +41,8 @@ dir_rec_t android_media_dir;
dir_rec_t android_mnt_expand_dir;
dir_rec_t android_mnt_expand_dir;
dir_rec_array_t android_system_dirs;
dir_rec_array_t android_system_dirs;


static const char* kCpPath = "/system/bin/cp";

int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{
{
    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
@@ -172,6 +177,80 @@ int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t us
    return 0;
    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)
int make_user_config(userid_t userid)
{
{
    if (ensure_config_user_dirs(userid) == -1) {
    if (ensure_config_user_dirs(userid) == -1) {
@@ -1592,7 +1671,7 @@ int restorecon_data(const char* uuid, const char* pkgName,
            continue;
            continue;
        }
        }


        std::string pkgdir(StringPrintf("%s/%s/%s", userdir.c_str(), user, pkgName));
        std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName));
        if (stat(pkgdir.c_str(), &s) < 0) {
        if (stat(pkgdir.c_str(), &s) < 0) {
            continue;
            continue;
        }
        }
+15 −46
Original line number Original line Diff line number Diff line
@@ -14,14 +14,15 @@
** limitations under the License.
** limitations under the License.
*/
*/


#include "installd.h"

#include <base/logging.h>

#include <sys/capability.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/prctl.h>
#include <selinux/android.h>
#include <selinux/android.h>
#include <selinux/avc.h>
#include <selinux/avc.h>


#include "installd.h"


#define BUFFER_MAX    1024  /* input buffer for commands */
#define BUFFER_MAX    1024  /* input buffer for commands */
#define TOKEN_MAX     16    /* max number of arguments in buffer */
#define TOKEN_MAX     16    /* max number of arguments in buffer */
#define REPLY_MAX     256   /* largest reply allowed */
#define REPLY_MAX     256   /* largest reply allowed */
@@ -123,6 +124,12 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused)
    return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, 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)
static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused)
{
{
    return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]);
    return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]);
@@ -193,6 +200,7 @@ struct cmdinfo cmds[] = {
    { "rmcodecache",          3, do_rm_code_cache },
    { "rmcodecache",          3, do_rm_code_cache },
    { "getsize",              8, do_get_size },
    { "getsize",              8, do_get_size },
    { "rmuserdata",           3, do_rm_user_data },
    { "rmuserdata",           3, do_rm_user_data },
    { "mvuserdata",           5, do_mv_user_data },
    { "movefiles",            0, do_movefiles },
    { "movefiles",            0, do_movefiles },
    { "linklib",              4, do_linklib },
    { "linklib",              4, do_linklib },
    { "mkuserdata",           5, do_mk_user_data },
    { "mkuserdata",           5, do_mk_user_data },
@@ -621,46 +629,6 @@ fail:
    return res;
    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, ...) {
static int log_callback(int type, const char *fmt, ...) {
    va_list ap;
    va_list ap;
    int priority;
    int priority;
@@ -682,13 +650,16 @@ static int log_callback(int type, const char *fmt, ...) {
    return 0;
    return 0;
}
}


int main(const int argc __unused, const char *argv[] __unused) {
int main(const int argc __unused, char *argv[]) {
    char buf[BUFFER_MAX];
    char buf[BUFFER_MAX];
    struct sockaddr addr;
    struct sockaddr addr;
    socklen_t alen;
    socklen_t alen;
    int lsocket, s;
    int lsocket, s;
    int selinux_enabled = (is_selinux_enabled() > 0);
    int selinux_enabled = (is_selinux_enabled() > 0);


    setenv("ANDROID_LOG_TAGS", "*:v", 1);
    android::base::InitLogging(argv);

    ALOGI("installd firing up\n");
    ALOGI("installd firing up\n");


    union selinux_callback cb;
    union selinux_callback cb;
@@ -710,8 +681,6 @@ int main(const int argc __unused, const char *argv[] __unused) {
        exit(1);
        exit(1);
    }
    }


    drop_privileges();

    lsocket = android_get_control_socket(SOCKET_PATH);
    lsocket = android_get_control_socket(SOCKET_PATH);
    if (lsocket < 0) {
    if (lsocket < 0) {
        ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
        ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
+11 −1
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/wait.h>
#include <string>
#include <string>
#include <vector>


#include <cutils/fs.h>
#include <cutils/fs.h>
#include <cutils/sockets.h>
#include <cutils/sockets.h>
@@ -89,6 +90,8 @@
#define DEXOPT_PATCHOAT_NEEDED       2
#define DEXOPT_PATCHOAT_NEEDED       2
#define DEXOPT_SELF_PATCHOAT_NEEDED  3
#define DEXOPT_SELF_PATCHOAT_NEEDED  3


#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))

/* data structures */
/* data structures */


typedef struct {
typedef struct {
@@ -154,6 +157,8 @@ 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::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);
int create_user_config_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],
@@ -214,7 +219,10 @@ int uninstall(const char *uuid, const char *pkgname, userid_t userid);
int renamepkg(const char *oldpkgname, const char *newpkgname);
int renamepkg(const char *oldpkgname, const char *newpkgname);
int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid);
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 delete_user_data(const char *uuid, const char *pkgname, userid_t userid);
int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo);
int make_user_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 make_user_config(userid_t userid);
int delete_user(const char *uuid, 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_cache(const char *uuid, const char *pkgname, userid_t userid);
@@ -238,3 +246,5 @@ int create_oat_dir(const char* oat_dir, const char *instruction_set);
int rm_package_dir(const char* apk_path);
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,
int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
                            const char *instruction_set);
                            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);
+32 −0
Original line number Original line Diff line number Diff line
@@ -99,6 +99,38 @@ 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);
    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;
    }

    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;
}

/**
/**
 * Create the path name for config for a certain userid.
 * Create the path name for config for a certain userid.
 * Returns 0 on success, and -1 on failure.
 * Returns 0 on success, and -1 on failure.