Use /mnt/storage for bind mounting package sandboxes.

Create a new slave bind mount at /mnt/storage and use this for
creating package sandboxes. This will help prevent package
specific data directories from getting duplicated and also make
handling bind mounts for packages with sharedUserIds easier.

Bug: 111890351
Test: manual
Change-Id: I0f590cc99a379d93f6db85bf56e8d274e3ea7488
This commit is contained in:
Sudheer Shanka 2018-08-07 17:10:11 -07:00
parent f2ccd56e7a
commit 3a7ee5c2ae
2 changed files with 60 additions and 21 deletions

View file

@ -98,6 +98,7 @@ VolumeManager::VolumeManager() {
// For security reasons, assume that a secure keyguard is
// showing until we hear otherwise
mSecureKeyguardShowing = true;
mMntStorageCreated = false;
}
VolumeManager::~VolumeManager() {
@ -346,9 +347,35 @@ int VolumeManager::forgetPartition(const std::string& partGuid, const std::strin
return success ? 0 : -1;
}
static int prepareMntStorageDir() {
std::string mntTarget("/mnt/storage");
if (fs_prepare_dir(mntTarget.c_str(), 0755, AID_ROOT, AID_ROOT) != 0) {
PLOG(ERROR) << "fs_prepare_dir failed on " << mntTarget;
return -errno;
}
if (TEMP_FAILURE_RETRY(mount("/mnt/runtime/write", mntTarget.c_str(),
nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
PLOG(ERROR) << "Failed to mount /mnt/runtime/write at " << mntTarget;
return -errno;
}
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;
return -errno;
}
return 0;
}
int VolumeManager::linkPrimary(userid_t userId, const std::vector<std::string>& packageNames) {
if (GetBoolProperty(kIsolatedStorage, false)) {
std::string source(StringPrintf("/mnt/runtime/write/%s", mPrimary->getLabel().c_str()));
// This should ideally go into start() but it's possible that system properties are not
// loaded at that point.
if (!mMntStorageCreated) {
prepareMntStorageDir();
mMntStorageCreated = true;
}
std::string source(StringPrintf("/mnt/storage/%s", mPrimary->getLabel().c_str()));
bool isPrimaryEmulated =
(mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated);
if (isPrimaryEmulated) {
@ -441,44 +468,47 @@ int VolumeManager::mountSandboxesForPrimaryVol(const std::string& primaryRoot, u
std::string sandboxId = mSandboxIds[appId];
uid_t uid = multiuser_get_uid(userId, appId);
// Create [1] /mnt/runtime/write/emulated/0/Android/sandbox/<sandboxId>
// Create [2] /mnt/user/0/package/<packageName>/emulated/0
// Mount [1] at [2]
// Create /mnt/storage/emulated/0/Android/sandbox/<sandboxId>
std::string pkgSandboxSourceDir = prepareSandboxSource(uid, sandboxId, sandboxRoot);
if (pkgSandboxSourceDir.empty()) {
return -errno;
}
std::string pkgSandboxTargetDir = prepareSandboxTarget(packageName, uid,
mPrimary->getLabel(), mntTargetRoot, isPrimaryEmulated);
if (pkgSandboxTargetDir.empty()) {
return -errno;
}
if (TEMP_FAILURE_RETRY(mount(pkgSandboxSourceDir.c_str(), pkgSandboxTargetDir.c_str(),
nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
PLOG(ERROR) << "Failed to mount " << pkgSandboxSourceDir << " at "
<< pkgSandboxTargetDir;
return -errno;
}
// Create [1] /mnt/runtime/write/emulated/0/Android/data/<packageName>
// Create [2] /mnt/user/0/package/<packageName>/emulated/0/Android/data/<packageName>
// Create [1] /mnt/storage/emulated/0/Android/data/<packageName>
// Create [2] /mnt/storage/emulated/0/Android/sandbox/<sandboxId>/Android/data/<packageName>
// Mount [1] at [2]
std::string pkgDataSourceDir = preparePkgDataSource(packageName, uid, dataRoot);
if (pkgDataSourceDir.empty()) {
return -errno;
}
std::string pkgDataTargetDir = preparePkgDataTarget(packageName, uid,
pkgSandboxTargetDir);
pkgSandboxSourceDir);
if (pkgDataTargetDir.empty()) {
return -errno;
}
if (TEMP_FAILURE_RETRY(mount(pkgDataSourceDir.c_str(), pkgDataTargetDir.c_str(),
nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
PLOG(ERROR) << "Failed to mount " << pkgDataSourceDir << " at "
<< pkgDataTargetDir;
return -errno;
}
// Already created [1] /mnt/storage/emulated/0/Android/sandbox/<sandboxId>
// Create [2] /mnt/user/0/package/<packageName>/emulated/0
// Mount [1] at [2]
std::string pkgSandboxTargetDir = prepareSandboxTarget(packageName, uid,
mPrimary->getLabel(), mntTargetRoot, isPrimaryEmulated);
if (pkgSandboxTargetDir.empty()) {
return -errno;
}
if (TEMP_FAILURE_RETRY(mount(pkgSandboxSourceDir.c_str(), pkgSandboxTargetDir.c_str(),
nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
PLOG(ERROR) << "Failed to mount " << pkgSandboxSourceDir << " at "
<< pkgSandboxTargetDir;
return -errno;
}
// Create [1] /mnt/user/0/package/<packageName>/self/primary
// Already created [2] /mnt/user/0/package/<packageName>/emulated/0
// Mount [2] at [1]
@ -489,7 +519,7 @@ int VolumeManager::mountSandboxesForPrimaryVol(const std::string& primaryRoot, u
return -errno;
}
if (TEMP_FAILURE_RETRY(mount(pkgSandboxTargetDir.c_str(), pkgPrimaryTargetDir.c_str(),
nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
PLOG(ERROR) << "Failed to mount " << pkgSandboxTargetDir << " at "
<< pkgPrimaryTargetDir;
return -errno;
@ -802,6 +832,13 @@ int VolumeManager::reset() {
mUserPackages.clear();
mAppIds.clear();
mSandboxIds.clear();
// For unmounting dirs under /mnt/user/<user-id>/package/<package-name>
unmount_tree("/mnt/user/");
// For unmounting dirs under /mnt/storage including the bind mount at /mnt/storage, that's
// why no trailing '/'
unmount_tree("/mnt/storage");
mMntStorageCreated = false;
return 0;
}
@ -850,7 +887,8 @@ int VolumeManager::unmountAll() {
auto test = std::string(mentry->mnt_dir);
if ((android::base::StartsWith(test, "/mnt/") &&
!android::base::StartsWith(test, "/mnt/vendor") &&
!android::base::StartsWith(test, "/mnt/product")) ||
!android::base::StartsWith(test, "/mnt/product") &&
!android::base::StartsWith(test, "/mnt/storage")) ||
android::base::StartsWith(test, "/storage/")) {
toUnmount.push_front(test);
}

View file

@ -179,6 +179,7 @@ private:
int mNextObbId;
bool mSecureKeyguardShowing;
bool mMntStorageCreated;
};
#endif