diff options
-rw-r--r-- | cmds/installd/commands.c | 79 | ||||
-rw-r--r-- | cmds/installd/installd.c | 8 |
2 files changed, 69 insertions, 18 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 12e8cd1..669f403 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -1235,31 +1235,82 @@ fail: return -1; } -int restorecon_data() +int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) { - char *data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); - char *user_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); + struct dirent *entry; + DIR *d; + struct stat s; + char *userdir; + char *primarydir; + char *pkgdir; + int ret = 0; - unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE | - SELINUX_ANDROID_RESTORECON_DATADATA; + // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. + unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE; - int ret = 0; + if (!pkgName || !seinfo) { + ALOGE("Package name or seinfo tag is null when trying to restorecon."); + return -1; + } - if (!data_dir || !user_dir) { + if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) { return -1; } - if (selinux_android_restorecon(data_dir, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", data_dir, strerror(errno)); + // 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 (selinux_android_restorecon(user_dir, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", user_dir, strerror(errno)); - ret |= -1; + if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) { + free(primarydir); + return -1; } - free(data_dir); - free(user_dir); + // Relabel package directory for all secondary users. + d = opendir(userdir); + if (d == NULL) { + free(primarydir); + free(userdir); + return -1; + } + + while ((entry = readdir(d))) { + if (entry->d_type != DT_DIR) { + continue; + } + + const char *user = entry->d_name; + // Ignore "." and ".." + if (!strcmp(user, ".") || !strcmp(user, "..")) { + continue; + } + + // user directories start with a number + if (user[0] < '0' || user[0] > '9') { + ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user); + continue; + } + + if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) { + continue; + } + + if (stat(pkgdir, &s) < 0) { + free(pkgdir); + continue; + } + + if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, uid, flags) < 0) { + ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno)); + ret |= -1; + } + free(pkgdir); + } + + closedir(d); + free(primarydir); + free(userdir); return ret; } diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index a080ee6..a078e1c 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -129,10 +129,10 @@ static int do_idmap(char **arg, char reply[REPLY_MAX]) return idmap(arg[0], arg[1], atoi(arg[2])); } -static int do_restorecon_data(char **arg __attribute__((unused)), - char reply[REPLY_MAX] __attribute__((unused))) +static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused))) { - return restorecon_data(); + return restorecon_data(arg[0], arg[1], atoi(arg[2])); + /* pkgName, seinfo, uid*/ } struct cmdinfo { @@ -159,7 +159,7 @@ struct cmdinfo cmds[] = { { "mkuserdata", 4, do_mk_user_data }, { "rmuser", 1, do_rm_user }, { "idmap", 3, do_idmap }, - { "restorecondata", 0, do_restorecon_data }, + { "restorecondata", 3, do_restorecon_data }, }; static int readx(int s, void *_buf, int count) |