Create a new mount mode for installer packages.
New external storage mount mode for installers so
that they can access obb dirs of all apps.
Bug: 111789719
Test: atest android.appsecurity.cts#testExternalStorageObbGifts
Change-Id: Iab112f0273806f8f812f14d6691bbe71dff42d83
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 0b2f1bf..0137869 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -73,6 +73,7 @@
using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::unique_fd;
+using android::vold::VoldNativeService;
static const char* kPathUserMount = "/mnt/user";
static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
@@ -496,40 +497,11 @@
_exit(1);
}
- struct stat storageSb;
- if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
- PLOG(ERROR) << "Failed to stat /storage";
+ int mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+ if (mountMode == -1) {
_exit(1);
}
- // 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 == fullWriteSb.st_dev && storageSb.st_ino == fullWriteSb.st_ino) {
- _exit(0);
- } else {
- // Some packages don't have access to external storage and processes belonging to
- // those packages don't have anything mounted at /storage. So, identify those
- // processes by comparing inode no.s of /mnt/user/%d/package/%s
- // and /storage
- std::string pkgStorageSource;
- for (auto& package : packagesForUid) {
- std::string sandbox =
- StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str());
- struct stat s;
- if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &s)) == -1) {
- PLOG(ERROR) << "Failed to stat " << sandbox;
- _exit(1);
- }
- if (storageSb.st_dev == s.st_dev && storageSb.st_ino == s.st_ino) {
- pkgStorageSource = sandbox;
- break;
- }
- }
- if (pkgStorageSource.empty()) {
- _exit(0);
- }
- }
-
for (auto& volumeLabel : visibleVolLabels) {
std::string mntSource = StringPrintf("/mnt/runtime/write/%s", volumeLabel.c_str());
std::string mntTarget = StringPrintf("/storage/%s", volumeLabel.c_str());
@@ -540,7 +512,23 @@
for (auto& package : packagesForUid) {
mountPkgSpecificDir(mntSource, mntTarget, package, "data");
mountPkgSpecificDir(mntSource, mntTarget, package, "media");
- mountPkgSpecificDir(mntSource, mntTarget, package, "obb");
+ if (mountMode != VoldNativeService::REMOUNT_MODE_INSTALLER) {
+ mountPkgSpecificDir(mntSource, mntTarget, package, "obb");
+ }
+ }
+ 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;
+ continue;
+ }
+ if (TEMP_FAILURE_RETRY(mount(nullptr, mntTarget.c_str(), nullptr,
+ MS_REC | MS_SLAVE, nullptr)) == -1) {
+ PLOG(ERROR) << "Failed to set MS_SLAVE at " << mntTarget.c_str();
+ continue;
+ }
}
}
_exit(0);
@@ -555,6 +543,44 @@
return 0;
}
+int VolumeManager::getMountModeForRunningProc(const std::vector<std::string>& packagesForUid,
+ userid_t userId, struct stat& mntWriteStat) {
+ struct stat storageSb;
+ if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
+ PLOG(ERROR) << "Failed to stat /storage";
+ return -1;
+ }
+
+ // 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) {
+ return VoldNativeService::REMOUNT_MODE_FULL;
+ }
+
+ std::string obbMountFile =
+ StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId, packagesForUid[0].c_str());
+ if (access(obbMountFile.c_str(), F_OK) == 0) {
+ return VoldNativeService::REMOUNT_MODE_INSTALLER;
+ }
+
+ // Some packages don't have access to external storage and processes belonging to
+ // those packages don't have anything mounted at /storage. So, identify those
+ // processes by comparing inode no.s of /mnt/user/%d/package/%s
+ // and /storage
+ for (auto& package : packagesForUid) {
+ std::string sandbox = StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str());
+ struct stat sandboxStat;
+ if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &sandboxStat)) == -1) {
+ PLOG(ERROR) << "Failed to stat " << sandbox;
+ return -1;
+ }
+ if (storageSb.st_dev == sandboxStat.st_dev && storageSb.st_ino == sandboxStat.st_ino) {
+ return VoldNativeService::REMOUNT_MODE_WRITE;
+ }
+ }
+ return VoldNativeService::REMOUNT_MODE_NONE;
+}
+
int VolumeManager::prepareSandboxes(userid_t userId, const std::vector<std::string>& packageNames,
const std::vector<std::string>& visibleVolLabels) {
if (visibleVolLabels.empty()) {