From da30dc7336f03ca629fe173db1425fdce989119c Mon Sep 17 00:00:00 2001 From: Robert Craig Date: Thu, 27 Mar 2014 10:21:12 -0400 Subject: [PATCH] Modify installd's restorecon function. Changes above with PMS and below with libselinux have resulted in a few changes to the restorecon data api. This change is needed in order to support the new way to issue a recursive restorecon of certain /data/data directories. The restorecondata function has also been modified to find all users on the device for a given package name (argument to the function) and to issue a separate recursive restorecon call for each. Change-Id: Ie440cba2c96f0907458086348197e1506d31c1b6 Signed-off-by: rpcraig --- cmds/installd/commands.c | 81 ++++++++++++++++++++++++++++++++-------- cmds/installd/installd.c | 8 ++-- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 12e8cd199..669f403e6 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); - - unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE | - SELINUX_ANDROID_RESTORECON_DATADATA; - + struct dirent *entry; + DIR *d; + struct stat s; + char *userdir; + char *primarydir; + char *pkgdir; int ret = 0; - if (!data_dir || !user_dir) { + // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. + unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE; + + if (!pkgName || !seinfo) { + ALOGE("Package name or seinfo tag is null when trying to restorecon."); return -1; } - if (selinux_android_restorecon(data_dir, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", data_dir, strerror(errno)); + if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) { + return -1; + } + + // 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 a080ee618..a078e1c0d 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)