Multi-user external storage support.

Remount rootfs as recursively shared, so that mount changes are
propagated into child namespaces.  Mount external storage for access
from adb.

Clean multi-user dependencies for use in Dalvik.  Also define
external storage paths.

Bug: 6925012
Change-Id: I375de581a63f4f36667894c56a34a9dd45361e8f
diff --git a/adb/adb.c b/adb/adb.c
index 200fc3c..a13a7c9 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -35,6 +35,7 @@
 #include <private/android_filesystem_config.h>
 #include <linux/capability.h>
 #include <linux/prctl.h>
+#include <sys/mount.h>
 #else
 #include "usb_vendors.h"
 #endif
@@ -989,6 +990,26 @@
 }
 #endif /* !ADB_HOST */
 
+#if !ADB_HOST
+/* Give ourselves access to external storage, which is otherwise protected. */
+static void mount_external_storage(void) {
+    // Create private mount namespace for our process
+    if (unshare(CLONE_NEWNS) == -1) {
+        fatal_errno("Failed to unshare()");
+    }
+
+    // Mark rootfs as being a slave in our process so that changes
+    // from parent namespace flow into our process.
+    if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
+        fatal_errno("Failed to mount() rootfs as MS_SLAVE");
+    }
+
+    if (mount(EXTERNAL_STORAGE_SYSTEM, EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
+        fatal_errno("Failed to mount() from %s", EXTERNAL_STORAGE_SYSTEM);
+    }
+}
+#endif /* !ADB_HOST */
+
 int adb_main(int is_daemon, int server_port)
 {
 #if !ADB_HOST
@@ -1008,7 +1029,6 @@
 
     init_transport_registration();
 
-
 #if ADB_HOST
     HOST = 1;
     usb_vendors_init();
@@ -1022,6 +1042,8 @@
     }
 #else
 
+    mount_external_storage();
+
     /* don't listen on a port (default 5037) if running in secure mode */
     /* don't run as root if we are running in secure mode */
     if (should_drop_privileges()) {
diff --git a/include/cutils/multiuser.h b/include/cutils/multiuser.h
index 22bb032..0bf403c 100644
--- a/include/cutils/multiuser.h
+++ b/include/cutils/multiuser.h
@@ -30,9 +30,9 @@
 typedef uid_t userid_t;
 typedef uid_t appid_t;
 
-extern userid_t getUserId(uid_t uid);
-extern appid_t getAppId(uid_t uid);
-extern uid_t getUid(userid_t userId, appid_t appId);
+extern userid_t multiuser_getUserId(uid_t uid);
+extern appid_t multiuser_getAppId(uid_t uid);
+extern uid_t multiuser_getUid(userid_t userId, appid_t appId);
 
 #ifdef __cplusplus
 }
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 6521cbe..012c2ae 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -229,6 +229,9 @@
     { 00644, AID_ROOT,      AID_ROOT,       0 },
 };
 
+#define EXTERNAL_STORAGE_SYSTEM "/mnt/secure/sdcard0"
+#define EXTERNAL_STORAGE_APP "/storage/sdcard0"
+
 static inline void fs_config(const char *path, int dir,
                              unsigned *uid, unsigned *gid, unsigned *mode)
 {
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 2477d23..6d525ba 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -50,7 +50,8 @@
 	threads.c \
 	sched_policy.c \
 	iosched_policy.c \
-	str_parms.c
+	str_parms.c \
+	multiuser.c
 
 commonHostSources := \
         ashmem-host.c
@@ -124,8 +125,7 @@
         mq.c \
         partition_utils.c \
         qtaguid.c \
-        uevent.c \
-        multiuser.c
+        uevent.c
 
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_SRC_FILES += arch-arm/memset32.S
diff --git a/libcutils/multiuser.c b/libcutils/multiuser.c
index be9304d..3c86cee 100644
--- a/libcutils/multiuser.c
+++ b/libcutils/multiuser.c
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <cutils/multiuser.h>
 
-userid_t getUserId(uid_t uid) {
+userid_t multiuser_getUserId(uid_t uid) {
     return uid / MULTIUSER_APP_PER_USER_RANGE;
 }
 
-appid_t getAppId(uid_t uid) {
+appid_t multiuser_getAppId(uid_t uid) {
     return uid % MULTIUSER_APP_PER_USER_RANGE;
 }
 
-uid_t getUid(userid_t userId, appid_t appId) {
+uid_t multiuser_getUid(userid_t userId, appid_t appId) {
     return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE);
 }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 4c20ec1..5a31a8e 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -128,6 +128,8 @@
 on post-fs
     # once everything is setup, no need to modify /
     mount rootfs rootfs / ro remount
+    # mount shared so changes propagate into child namespaces
+    mount rootfs rootfs / shared rec
 
     # We chown/chmod /cache again so because mount is run as root + defaults
     chown system cache /cache