Only restorecon /data/data if passed an explicit flag.

As discussed in the comments of:
https://android-review.googlesource.com/#/c/81292/
we do not want restorecon_recursive /data by init.rc to
change the contexts of /data/data or /data/users/N because
those contexts are dependent on package information in
/data/system/packages.list that may not be set correctly
at boot on an upgrade.  Therefore we skip /data/data
on a recursive restorecon unless passed an explicit flag.
This flag will be used by the PMS or installd in a subsequent
change to restorecon /data/data after computing the seinfo
values for packages and updating packages.list accordingly.
It will also be optionally used by the toolbox restorecon
command if passed a new option to be introduced in a subsequent
change.

Change-Id: I137588013ed1750315702c0dbe088ce3e4a29e83
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/src/android.c b/src/android.c
index dcc4965..2cab084 100644
--- a/src/android.c
+++ b/src/android.c
@@ -839,8 +839,10 @@
 }
 
 /* The path prefixes of package data directories. */
-#define DATA_DATA_PREFIX "/data/data/"
-#define DATA_USER_PREFIX "/data/user/"
+#define DATA_DATA_PATH "/data/data"
+#define DATA_USER_PATH "/data/user"
+#define DATA_DATA_PREFIX DATA_DATA_PATH "/"
+#define DATA_USER_PREFIX DATA_USER_PATH "/"
 
 static int pkgdir_selabel_lookup(const char *pathname, char **secontextp)
 {
@@ -973,6 +975,7 @@
     bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false;
     bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false;
     bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false;
+    bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false;
     struct stat sb;
     FTS *fts;
     FTSENT *ftsent;
@@ -1035,6 +1038,14 @@
                         "SELinux:  Error on %s: %s.\n", ftsent->fts_path, strerror(errno));
             fts_set(fts, ftsent, FTS_SKIP);
             continue;
+        case FTS_D:
+            if (!datadata &&
+                (!strcmp(ftsent->fts_path, DATA_DATA_PATH) ||
+                 !strcmp(ftsent->fts_path, DATA_USER_PATH))) {
+                fts_set(fts, ftsent, FTS_SKIP);
+                continue;
+            }
+            /* fall through */
         default:
             (void) restorecon_sb(ftsent->fts_path, ftsent->fts_statp, true, nochange, verbose);
             break;