Mount storage Android/data and Android/obb as tmpfs in app namespace

So Android/data and Android/obb won't be accessing fuse anymore,
and apps should not see other packages as well as it's sandboxed
the tmpfs.

Bug: 155462341
Test: atest AppDataIsolationTests pass after feature flag is on
Change-Id: I5658440772e669c1235d318f708a3d336523754f
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index b6edd9e..c0d0e77 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -19,6 +19,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <mntent.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -739,8 +740,10 @@
 }
 
 
-// Set the namespace the app process and remount its storage directories.
-static bool remountStorageDirs(int nsFd, const char* sources[], const char* targets[], int size) {
+// In each app's namespace, mount tmpfs on obb and data dir, and bind mount obb and data
+// package dirs.
+static bool remountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir,
+        int uid, const char* sources[], const char* targets[], int size) {
     // This code is executed after a fork so it's very important that the set of
     // methods we call here is strictly limited.
     if (setns(nsFd, CLONE_NEWNS) != 0) {
@@ -748,7 +751,27 @@
         return false;
     }
 
+    // Mount tmpfs on Android/data and Android/obb
+    if (TEMP_FAILURE_RETRY(mount("tmpfs", android_data_dir, "tmpfs",
+            MS_NOSUID | MS_NODEV | MS_NOEXEC, "uid=0,gid=0,mode=0751")) == -1) {
+        async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to mount tmpfs to %s :%s",
+                        android_data_dir, strerror(errno));
+        return false;
+    }
+    if (TEMP_FAILURE_RETRY(mount("tmpfs", android_obb_dir, "tmpfs",
+            MS_NOSUID | MS_NODEV | MS_NOEXEC, "uid=0,gid=0,mode=0751")) == -1) {
+        async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to mount tmpfs to %s :%s",
+                android_obb_dir, strerror(errno));
+        return false;
+    }
+
     for (int i = 0; i < size; i++) {
+        // Create package dir and bind mount it to the actual one.
+        if (TEMP_FAILURE_RETRY(mkdir(targets[i], 0700)) == -1) {
+            async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to mkdir %s %s",
+                    targets[i], strerror(errno));
+            return false;
+        }
         if (TEMP_FAILURE_RETRY(mount(sources[i], targets[i], NULL, MS_BIND | MS_REC, NULL)) == -1) {
             async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to mount %s to %s :%s",
                                   sources[i], targets[i], strerror(errno));
@@ -823,11 +846,17 @@
         }
     }
 
+    char android_data_dir[PATH_MAX];
+    char android_obb_dir[PATH_MAX];
+    snprintf(android_data_dir, PATH_MAX, "/storage/emulated/%d/Android/data", userId);
+    snprintf(android_obb_dir, PATH_MAX, "/storage/emulated/%d/Android/obb", userId);
+
     pid_t child;
     // Fork a child to mount Android/obb android Android/data dirs, as we don't want it to affect
     // original vold process mount namespace.
     if (!(child = fork())) {
-        if (remountStorageDirs(nsFd, sources_cstr, targets_cstr, size)) {
+        if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+                sources_cstr, targets_cstr, size)) {
             _exit(0);
         } else {
             _exit(1);