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
This commit is contained in:
Sudheer Shanka 2018-12-12 12:43:38 -08:00
parent 042dfdde7b
commit 03992e3741
3 changed files with 62 additions and 33 deletions

View file

@ -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<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()) {

View file

@ -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<std::string>& packagesForUid, userid_t userId,
struct stat& mntWriteStat);
void handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk);
void handleDiskChanged(dev_t device);

View file

@ -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;