From 03992e3741e632749e8fd7f3db452d2daf983619 Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Wed, 12 Dec 2018 12:43:38 -0800 Subject: [PATCH] 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 --- VolumeManager.cpp | 90 +++++++++++++++++++++++------------- VolumeManager.h | 2 + binder/android/os/IVold.aidl | 3 +- 3 files changed, 62 insertions(+), 33 deletions(-) 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::StartsWith; 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 @@ int VolumeManager::mountPkgSpecificDirsForRunningProcs( _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 @@ int VolumeManager::mountPkgSpecificDirsForRunningProcs( 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 @@ int VolumeManager::mountPkgSpecificDirsForRunningProcs( return 0; } +int VolumeManager::getMountModeForRunningProc(const std::vector& 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& packageNames, const std::vector& visibleVolLabels) { if (visibleVolLabels.empty()) { diff --git a/VolumeManager.h b/VolumeManager.h index 9e990d0..b1aa954 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -171,6 +171,8 @@ class VolumeManager { const std::string& packageName, const char* dirName); int destroySandboxForAppOnVol(const std::string& packageName, const std::string& sandboxId, userid_t userId, const std::string& volLabel); + int getMountModeForRunningProc(const std::vector& packagesForUid, userid_t userId, + struct stat& mntWriteStat); void handleDiskAdded(const std::shared_ptr& disk); void handleDiskChanged(dev_t device); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 2f7430f..fdccf00 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -151,7 +151,8 @@ interface IVold { const int REMOUNT_MODE_DEFAULT = 1; const int REMOUNT_MODE_READ = 2; const int REMOUNT_MODE_WRITE = 3; - const int REMOUNT_MODE_FULL = 4; + const int REMOUNT_MODE_INSTALLER = 4; + const int REMOUNT_MODE_FULL = 5; const int VOLUME_STATE_UNMOUNTED = 0; const int VOLUME_STATE_CHECKING = 1;