Update process mount points when appop gets updated.

When an app is started, it's mountmode is dependent on
OP_REQUEST_INSTALL_PACKAGES. If user changes the appop grant of an app,
we need to update the mounts of any processes running in that app.

Bug: 121099965
Test: atest android.appsecurity.cts.ExternalStorageHostTest#testExternalStorageObbGifts
Change-Id: I87fee492891d33ccc9fc9e2548114f67d90cc759
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 0137869..f098a09 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -402,7 +402,7 @@
 
 int VolumeManager::mountPkgSpecificDirsForRunningProcs(
     userid_t userId, const std::vector<std::string>& packageNames,
-    const std::vector<std::string>& visibleVolLabels) {
+    const std::vector<std::string>& visibleVolLabels, int remountMode) {
     // TODO: New processes could be started while traversing over the existing
     // processes which would end up not having the necessary bind mounts. This
     // issue needs to be fixed, may be by doing multiple passes here?
@@ -497,9 +497,32 @@
                 _exit(1);
             }
 
-            int mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
-            if (mountMode == -1) {
-                _exit(1);
+            int mountMode;
+            if (remountMode == -1) {
+                mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+                if (mountMode == -1) {
+                    _exit(1);
+                }
+            } else {
+                mountMode = remountMode;
+                std::string obbMountFile = StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId,
+                                                        packagesForUid[0].c_str());
+                if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) {
+                    if (access(obbMountFile.c_str(), F_OK) != 0) {
+                        const unique_fd fd(
+                            TEMP_FAILURE_RETRY(open(obbMountFile.c_str(), O_RDWR | O_CREAT, 0660)));
+                    }
+                } else {
+                    if (access(obbMountFile.c_str(), F_OK) == 0) {
+                        remove(obbMountFile.c_str());
+                    }
+                }
+            }
+            if (mountMode == VoldNativeService::REMOUNT_MODE_FULL ||
+                mountMode == VoldNativeService::REMOUNT_MODE_NONE) {
+                // These mount modes are not going to change dynamically, so don't bother
+                // unmounting/remounting dirs.
+                _exit(0);
             }
 
             for (auto& volumeLabel : visibleVolLabels) {
@@ -509,6 +532,13 @@
                     StringAppendF(&mntSource, "/%d", userId);
                     StringAppendF(&mntTarget, "/%d", userId);
                 }
+                std::string obbSourceDir = StringPrintf("%s/Android/obb", mntSource.c_str());
+                std::string obbTargetDir = StringPrintf("%s/Android/obb", mntTarget.c_str());
+                if (umount2(obbTargetDir.c_str(), MNT_DETACH) == -1 && errno != EINVAL &&
+                    errno != ENOENT) {
+                    PLOG(ERROR) << "Failed to unmount " << obbTargetDir;
+                    continue;
+                }
                 for (auto& package : packagesForUid) {
                     mountPkgSpecificDir(mntSource, mntTarget, package, "data");
                     mountPkgSpecificDir(mntSource, mntTarget, package, "media");
@@ -517,16 +547,14 @@
                     }
                 }
                 if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) {
-                    StringAppendF(&mntSource, "/Android/obb");
-                    StringAppendF(&mntTarget, "/Android/obb");
-                    if (TEMP_FAILURE_RETRY(mount(mntSource.c_str(), mntTarget.c_str(), nullptr,
-                                                 MS_BIND | MS_REC, nullptr)) == -1) {
-                        PLOG(ERROR) << "Failed to mount " << mntSource << " to " << mntTarget;
+                    if (TEMP_FAILURE_RETRY(mount(obbSourceDir.c_str(), obbTargetDir.c_str(),
+                                                 nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
+                        PLOG(ERROR) << "Failed to mount " << obbSourceDir << " to " << obbTargetDir;
                         continue;
                     }
-                    if (TEMP_FAILURE_RETRY(mount(nullptr, mntTarget.c_str(), nullptr,
+                    if (TEMP_FAILURE_RETRY(mount(nullptr, obbTargetDir.c_str(), nullptr,
                                                  MS_REC | MS_SLAVE, nullptr)) == -1) {
-                        PLOG(ERROR) << "Failed to set MS_SLAVE at " << mntTarget.c_str();
+                        PLOG(ERROR) << "Failed to set MS_SLAVE at " << obbTargetDir.c_str();
                         continue;
                     }
                 }
@@ -693,7 +721,7 @@
             }
         }
     }
-    mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels);
+    mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels, -1);
     return 0;
 }
 
@@ -1064,12 +1092,56 @@
     return 0;
 }
 
-int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
-    // If the isolated storage is enabled, return -1 since in the isolated storage world, there
-    // are no longer any runtime storage permissions, so this shouldn't be called anymore.
-    if (GetBoolProperty(kIsolatedStorage, false)) {
+int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
+    if (!GetBoolProperty(kIsolatedStorage, false)) {
+        return remountUidLegacy(uid, mountMode);
+    }
+
+    appid_t appId = multiuser_get_app_id(uid);
+    userid_t userId = multiuser_get_user_id(uid);
+    std::vector<std::string> visibleVolLabels;
+    for (auto& volId : mVisibleVolumeIds) {
+        auto vol = findVolume(volId);
+        userid_t mountUserId = vol->getMountUserId();
+        if (mountUserId == userId || vol->isEmulated()) {
+            visibleVolLabels.push_back(vol->getLabel());
+        }
+    }
+
+    // Finding one package with appId is enough
+    std::vector<std::string> packageNames;
+    for (auto it = mAppIds.begin(); it != mAppIds.end(); ++it) {
+        if (it->second == appId) {
+            packageNames.push_back(it->first);
+            break;
+        }
+    }
+    if (packageNames.empty()) {
+        PLOG(ERROR) << "Failed to find packageName for " << uid;
         return -1;
     }
+    return mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels, mountMode);
+}
+
+int VolumeManager::remountUidLegacy(uid_t uid, int32_t mountMode) {
+    std::string mode;
+    switch (mountMode) {
+        case VoldNativeService::REMOUNT_MODE_NONE:
+            mode = "none";
+            break;
+        case VoldNativeService::REMOUNT_MODE_DEFAULT:
+            mode = "default";
+            break;
+        case VoldNativeService::REMOUNT_MODE_READ:
+            mode = "read";
+            break;
+        case VoldNativeService::REMOUNT_MODE_WRITE:
+            mode = "write";
+            break;
+        default:
+            PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode);
+            return -1;
+    }
     LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
 
     DIR* dir;