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;