Create a new MOUNT_EXTERNAL_LEGACY storage mode.

Apps that are already installed on the device before isolated_storage
feature is enabled will be granted MOUNT_EXTERNAL_LEGACY mode. In this
mode, /mnt/runtime/write will be mounted at /storage giving them same
level of access as in P.

A new mount directory /mnt/runtime/full is also created which will be
used for mounting at /storage for apps started with MOUNT_EXTERNAL_FULL
mode. This will allow apps with WRITE_MEDIA_STORAGE permission to
read/write anywhere on the secondary devices without needing to bypass
sdcardfs.

Bug: 121277410
Test: manual
Test: atest android.appsecurity.cts.ExternalStorageHostTest
Change-Id: Icc1ff9da35545692daedef7173d7c89290dd2766
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 547c7ef..f600f64 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -425,8 +425,13 @@
         return -1;
     }
 
-    struct stat fullWriteSb;
-    if (TEMP_FAILURE_RETRY(stat("/mnt/runtime/write", &fullWriteSb)) == -1) {
+    struct stat mntFullSb;
+    struct stat mntWriteSb;
+    if (TEMP_FAILURE_RETRY(stat("/mnt/runtime/full", &mntFullSb)) == -1) {
+        PLOG(ERROR) << "Failed to stat /mnt/runtime/full";
+        return -1;
+    }
+    if (TEMP_FAILURE_RETRY(stat("/mnt/runtime/write", &mntWriteSb)) == -1) {
         PLOG(ERROR) << "Failed to stat /mnt/runtime/write";
         return -1;
     }
@@ -505,7 +510,8 @@
 
             int mountMode;
             if (remountMode == -1) {
-                mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+                mountMode =
+                    getMountModeForRunningProc(packagesForUid, userId, mntWriteSb, mntFullSb);
                 if (mountMode == -1) {
                     _exit(1);
                 }
@@ -525,6 +531,7 @@
                 }
             }
             if (mountMode == VoldNativeService::REMOUNT_MODE_FULL ||
+                mountMode == VoldNativeService::REMOUNT_MODE_LEGACY ||
                 mountMode == VoldNativeService::REMOUNT_MODE_NONE) {
                 // These mount modes are not going to change dynamically, so don't bother
                 // unmounting/remounting dirs.
@@ -578,7 +585,8 @@
 }
 
 int VolumeManager::getMountModeForRunningProc(const std::vector<std::string>& packagesForUid,
-                                              userid_t userId, struct stat& mntWriteStat) {
+                                              userid_t userId, struct stat& mntWriteStat,
+                                              struct stat& mntFullStat) {
     struct stat storageSb;
     if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
         PLOG(ERROR) << "Failed to stat /storage";
@@ -586,9 +594,11 @@
     }
 
     // Some packages have access to full external storage, identify processes belonging
-    // to those packages by comparing inode no.s of /mnt/runtime/write and /storage
-    if (storageSb.st_dev == mntWriteStat.st_dev && storageSb.st_ino == mntWriteStat.st_ino) {
+    // to those packages by comparing inode no.s of /mnt/runtime/full and /storage
+    if (storageSb.st_dev == mntFullStat.st_dev && storageSb.st_ino == mntFullStat.st_ino) {
         return VoldNativeService::REMOUNT_MODE_FULL;
+    } else if (storageSb.st_dev == mntWriteStat.st_dev && storageSb.st_ino == mntWriteStat.st_ino) {
+        return VoldNativeService::REMOUNT_MODE_LEGACY;
     }
 
     std::string obbMountFile =
diff --git a/VolumeManager.h b/VolumeManager.h
index 3a7bae4..7d299a1 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -174,7 +174,7 @@
     int destroySandboxForAppOnVol(const std::string& packageName, const std::string& sandboxId,
                                   userid_t userId, const std::string& volLabel);
     int getMountModeForRunningProc(const std::vector<std::string>& packagesForUid, userid_t userId,
-                                   struct stat& mntWriteStat);
+                                   struct stat& mntWriteStat, struct stat& mntFullStat);
 
     void handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk);
     void handleDiskChanged(dev_t device);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index fdccf00..425a36c 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -151,8 +151,9 @@
     const int REMOUNT_MODE_DEFAULT = 1;
     const int REMOUNT_MODE_READ = 2;
     const int REMOUNT_MODE_WRITE = 3;
-    const int REMOUNT_MODE_INSTALLER = 4;
-    const int REMOUNT_MODE_FULL = 5;
+    const int REMOUNT_MODE_LEGACY = 4;
+    const int REMOUNT_MODE_INSTALLER = 5;
+    const int REMOUNT_MODE_FULL = 6;
 
     const int VOLUME_STATE_UNMOUNTED = 0;
     const int VOLUME_STATE_CHECKING = 1;
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index cf18d73..e751eca 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -185,36 +185,16 @@
                 PLOG(ERROR) << "Failed to exec";
             }
         } else {
-            // In Pre-Q, apps have full read access to secondary storage devices but only
-            // write access for their package specific directories. In Q, they only have access
-            // to their own sandboxes and they can write anywhere inside the sandbox. Instead of
-            // updating sdcardfs to allow packages writing into their own sandboxes, we could
-            // just allow them to write anywhere by passing "-w".
             // clang-format off
-            if (GetBoolProperty(kIsolatedStorage, false)) {
-                if (execl(kFusePath, kFusePath,
-                        "-u", "1023", // AID_MEDIA_RW
-                        "-g", "1023", // AID_MEDIA_RW
-                        "-U", std::to_string(getMountUserId()).c_str(),
-                        "-w",
-                        mRawPath.c_str(),
-                        stableName.c_str(),
-                        NULL)) {
-                    // clang-format on
-                    PLOG(ERROR) << "Failed to exec";
-                }
-            } else {
-                // clang-format off
-                if (execl(kFusePath, kFusePath,
-                        "-u", "1023", // AID_MEDIA_RW
-                        "-g", "1023", // AID_MEDIA_RW
-                        "-U", std::to_string(getMountUserId()).c_str(),
-                        mRawPath.c_str(),
-                        stableName.c_str(),
-                        NULL)) {
-                    // clang-format on
-                    PLOG(ERROR) << "Failed to exec";
-                }
+            if (execl(kFusePath, kFusePath,
+                    "-u", "1023", // AID_MEDIA_RW
+                    "-g", "1023", // AID_MEDIA_RW
+                    "-U", std::to_string(getMountUserId()).c_str(),
+                    mRawPath.c_str(),
+                    stableName.c_str(),
+                    NULL)) {
+                // clang-format on
+                PLOG(ERROR) << "Failed to exec";
             }
         }