Merge "Runtime resource overlay, iteration 2"
This commit is contained in:
commit
6c14f0ad82
@ -618,14 +618,11 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
|
|||||||
ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
|
ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wait_dexopt(pid_t pid, const char* apk_path)
|
static int wait_child(pid_t pid)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
pid_t got_pid;
|
pid_t got_pid;
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait for the optimization process to finish.
|
|
||||||
*/
|
|
||||||
while (1) {
|
while (1) {
|
||||||
got_pid = waitpid(pid, &status, 0);
|
got_pid = waitpid(pid, &status, 0);
|
||||||
if (got_pid == -1 && errno == EINTR) {
|
if (got_pid == -1 && errno == EINTR) {
|
||||||
@ -641,11 +638,8 @@ static int wait_dexopt(pid_t pid, const char* apk_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||||
ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
ALOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
|
|
||||||
apk_path, status);
|
|
||||||
return status; /* always nonzero */
|
return status; /* always nonzero */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -747,9 +741,11 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
|
|||||||
}
|
}
|
||||||
exit(68); /* only get here on exec failure */
|
exit(68); /* only get here on exec failure */
|
||||||
} else {
|
} else {
|
||||||
res = wait_dexopt(pid, apk_path);
|
res = wait_child(pid);
|
||||||
if (res != 0) {
|
if (res == 0) {
|
||||||
ALOGE("dexopt in='%s' out='%s' res=%d\n", apk_path, out_path, res);
|
ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
|
||||||
|
} else {
|
||||||
|
ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", apk_path, res);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1103,3 +1099,115 @@ out:
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
|
||||||
|
{
|
||||||
|
static const char *IDMAP_BIN = "/system/bin/idmap";
|
||||||
|
static const size_t MAX_INT_LEN = 32;
|
||||||
|
char idmap_str[MAX_INT_LEN];
|
||||||
|
|
||||||
|
snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd);
|
||||||
|
|
||||||
|
execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL);
|
||||||
|
ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix)
|
||||||
|
// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
|
||||||
|
static int flatten_path(const char *prefix, const char *suffix,
|
||||||
|
const char *overlay_path, char *idmap_path, size_t N)
|
||||||
|
{
|
||||||
|
if (overlay_path == NULL || idmap_path == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const size_t len_overlay_path = strlen(overlay_path);
|
||||||
|
// will access overlay_path + 1 further below; requires absolute path
|
||||||
|
if (len_overlay_path < 2 || *overlay_path != '/') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const size_t len_idmap_root = strlen(prefix);
|
||||||
|
const size_t len_suffix = strlen(suffix);
|
||||||
|
if (SIZE_MAX - len_idmap_root < len_overlay_path ||
|
||||||
|
SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) {
|
||||||
|
// additions below would cause overflow
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (N < len_idmap_root + len_overlay_path + len_suffix) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(idmap_path, 0, N);
|
||||||
|
snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix);
|
||||||
|
char *ch = idmap_path + len_idmap_root;
|
||||||
|
while (*ch != '\0') {
|
||||||
|
if (*ch == '/') {
|
||||||
|
*ch = '@';
|
||||||
|
}
|
||||||
|
++ch;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idmap(const char *target_apk, const char *overlay_apk, uid_t uid)
|
||||||
|
{
|
||||||
|
ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
|
||||||
|
|
||||||
|
int idmap_fd = -1;
|
||||||
|
char idmap_path[PATH_MAX];
|
||||||
|
|
||||||
|
if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
|
||||||
|
idmap_path, sizeof(idmap_path)) == -1) {
|
||||||
|
ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(idmap_path);
|
||||||
|
idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
|
||||||
|
if (idmap_fd < 0) {
|
||||||
|
ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) {
|
||||||
|
ALOGE("idmap cannot chown '%s'\n", idmap_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
|
||||||
|
ALOGE("idmap cannot chmod '%s'\n", idmap_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid;
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
/* child -- drop privileges before continuing */
|
||||||
|
if (setgid(uid) != 0) {
|
||||||
|
ALOGE("setgid(%d) failed during idmap\n", uid);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (setuid(uid) != 0) {
|
||||||
|
ALOGE("setuid(%d) failed during idmap\n", uid);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
|
||||||
|
ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
run_idmap(target_apk, overlay_apk, idmap_fd);
|
||||||
|
exit(1); /* only if exec call to idmap failed */
|
||||||
|
} else {
|
||||||
|
int status = wait_child(pid);
|
||||||
|
if (status != 0) {
|
||||||
|
ALOGE("idmap failed, status=0x%04x\n", status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(idmap_fd);
|
||||||
|
return 0;
|
||||||
|
fail:
|
||||||
|
if (idmap_fd >= 0) {
|
||||||
|
close(idmap_fd);
|
||||||
|
unlink(idmap_path);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -124,6 +124,11 @@ static int do_linklib(char **arg, char reply[REPLY_MAX])
|
|||||||
return linklib(arg[0], arg[1], atoi(arg[2]));
|
return linklib(arg[0], arg[1], atoi(arg[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_idmap(char **arg, char reply[REPLY_MAX])
|
||||||
|
{
|
||||||
|
return idmap(arg[0], arg[1], atoi(arg[2]));
|
||||||
|
}
|
||||||
|
|
||||||
struct cmdinfo {
|
struct cmdinfo {
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned numargs;
|
unsigned numargs;
|
||||||
@ -147,6 +152,7 @@ struct cmdinfo cmds[] = {
|
|||||||
{ "linklib", 3, do_linklib },
|
{ "linklib", 3, do_linklib },
|
||||||
{ "mkuserdata", 4, do_mk_user_data },
|
{ "mkuserdata", 4, do_mk_user_data },
|
||||||
{ "rmuser", 1, do_rm_user },
|
{ "rmuser", 1, do_rm_user },
|
||||||
|
{ "idmap", 3, do_idmap },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int readx(int s, void *_buf, int count)
|
static int readx(int s, void *_buf, int count)
|
||||||
@ -515,6 +521,7 @@ static void drop_privileges() {
|
|||||||
capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN);
|
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_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
|
||||||
capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
|
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[0].effective = capdata[0].permitted;
|
||||||
capdata[1].effective = capdata[1].permitted;
|
capdata[1].effective = capdata[1].permitted;
|
||||||
|
@ -75,6 +75,9 @@
|
|||||||
|
|
||||||
#define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/"
|
#define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/"
|
||||||
|
|
||||||
|
#define IDMAP_PREFIX "/data/resource-cache/"
|
||||||
|
#define IDMAP_SUFFIX "@idmap"
|
||||||
|
|
||||||
#define PKG_NAME_MAX 128 /* largest allowed package name */
|
#define PKG_NAME_MAX 128 /* largest allowed package name */
|
||||||
#define PKG_PATH_MAX 256 /* max size of any path we use */
|
#define PKG_PATH_MAX 256 /* max size of any path we use */
|
||||||
|
|
||||||
@ -207,3 +210,4 @@ int free_cache(int64_t free_size);
|
|||||||
int dexopt(const char *apk_path, uid_t uid, int is_public);
|
int dexopt(const char *apk_path, uid_t uid, int is_public);
|
||||||
int movefiles();
|
int movefiles();
|
||||||
int linklib(const char* target, const char* source, int userId);
|
int linklib(const char* target, const char* source, int userId);
|
||||||
|
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
|
||||||
|
Loading…
Reference in New Issue
Block a user