Extend installd to support SELinux restorecon function.

Implement new restorecondata function which will allow
the relabeling of /data/data and /data/user directories.
This is needed in the case of certain OTAs. Not every
boot will apply this relabeling however. Consult change
I77bf2a0c4c34b1feef6fdf4d6c3bd92dbf32f4a1 for
clarification on this issue.

Change-Id: I05e8b438950ddb908e46c9168ea6ee601e6d674f
Signed-off-by: rpcraig <rpcraig@tycho.ncsc.mil>
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index f1f6f99..12e8cd1 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -1234,3 +1234,32 @@
     }
     return -1;
 }
+
+int restorecon_data()
+{
+    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;
+
+    int ret = 0;
+
+    if (!data_dir || !user_dir) {
+        return -1;
+    }
+
+    if (selinux_android_restorecon(data_dir, flags) < 0) {
+        ALOGE("restorecon failed for %s: %s\n", data_dir, 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;
+    }
+
+    free(data_dir);
+    free(user_dir);
+    return ret;
+}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index b4df3a3..40fc13f 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -129,6 +129,12 @@
     return idmap(arg[0], arg[1], atoi(arg[2]));
 }
 
+static int do_restorecon_data(char **arg __attribute__((unused)),
+    char reply[REPLY_MAX] __attribute__((unused)))
+{
+    return restorecon_data();
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -153,6 +159,7 @@
     { "mkuserdata",           4, do_mk_user_data },
     { "rmuser",               1, do_rm_user },
     { "idmap",                3, do_idmap },
+    { "restorecondata",       0, do_restorecon_data },
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index b458031..3e9caf3 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -213,3 +213,4 @@
 int movefiles();
 int linklib(const char* target, const char* source, int userId);
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
+int restorecon_data();