OSDN Git Service

Modify installd's restorecon function.
authorRobert Craig <rpcraig@tycho.ncsc.mil>
Thu, 27 Mar 2014 14:21:12 +0000 (10:21 -0400)
committerRobert Craig <rpcraig@tycho.ncsc.mil>
Fri, 28 Mar 2014 18:32:07 +0000 (14:32 -0400)
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 <rpcraig@tycho.ncsc.mil>
cmds/installd/commands.c
cmds/installd/installd.c

index 12e8cd1..669f403 100644 (file)
@@ -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;
 }
index a080ee6..a078e1c 100644 (file)
@@ -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)