Bind mount write view of Android/obb for installers.

Installers will be allowed to write OBB for any application; this is not
easy to achieve on sdcardfs, where the GID of Android/obb is the same as
the GID of Android/data (app-private data), meaning giving installers
write access to Android/obb would also give them write access to
Android/data.

Instead, we create a /mnt/installer view, which is exactly the same as
/mnt/user, with the sole exception that the write sdcardfs view of
Android/obb is mounted on top. This is what will allow installers to
write there, while still being restricted with respect to app-private
data in Android/data.

Bug: 134706060
Test: atest AdoptableHostTest
Change-Id: If2b93870a877efef182bdc06466552a7527499ad
This commit is contained in:
Martijn Coenen 2020-01-11 19:38:37 +01:00
parent b0e977a0b1
commit 3a2dbfee88

View file

@ -73,6 +73,26 @@ std::string EmulatedVolume::getLabel() {
}
}
// Creates a bind mount from source to target, creating the source (!) directory
// if not yet present.
static status_t doFuseBindMount(const std::string& source, const std::string& target) {
if (access(source.c_str(), F_OK) != 0) {
// Android path may not exist yet if users has just been created; create it on
// the lower fs.
if (fs_prepare_dir(source.c_str(), 0771, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
PLOG(ERROR) << "Failed to create " << source;
return -errno;
}
}
LOG(INFO) << "Bind mounting " << source << " on " << target;
auto status = BindMount(source, target);
if (status != OK) {
return status;
}
LOG(INFO) << "Bind mounted " << source << " on " << target;
return OK;
}
status_t EmulatedVolume::mountFuseBindMounts() {
std::string androidSource;
std::string label = getLabel();
@ -86,21 +106,27 @@ status_t EmulatedVolume::mountFuseBindMounts() {
std::string androidTarget(
StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));
if (access(androidSource.c_str(), F_OK) != 0) {
// Android path may not exist yet if users has just been created; create it on
// the lower fs.
if (fs_prepare_dir(androidSource.c_str(), 0771, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
PLOG(ERROR) << "Failed to create " << androidSource;
return -errno;
}
}
LOG(INFO) << "Bind mounting " << androidSource << " on " << androidTarget;
auto status = BindMount(androidSource, androidTarget);
auto status = doFuseBindMount(androidSource, androidTarget);
if (status != OK) {
return status;
}
LOG(INFO) << "Bind mounted " << androidSource << " on " << androidTarget;
// Installers get the same view as all other apps, with the sole exception that the
// OBB dirs (Android/obb) are writable to them. On sdcardfs devices, this requires
// a special bind mount, since app-private and OBB dirs share the same GID, but we
// only want to give access to the latter.
if (!mUseSdcardFs) {
return OK;
}
std::string installerSource(
StringPrintf("/mnt/runtime/write/%s/%d/Android/obb", label.c_str(), userId));
std::string installerTarget(
StringPrintf("/mnt/installer/%d/%s/%d/Android/obb", userId, label.c_str(), userId));
status = doFuseBindMount(installerSource, installerTarget);
if (status != OK) {
return status;
}
return OK;
}
@ -108,6 +134,17 @@ status_t EmulatedVolume::unmountFuseBindMounts() {
std::string label = getLabel();
int userId = getMountUserId();
if (mUseSdcardFs) {
std::string installerTarget(
StringPrintf("/mnt/installer/%d/%s/%d/Android/obb", userId, label.c_str(), userId));
LOG(INFO) << "Unmounting " << installerTarget;
auto status = UnmountTree(installerTarget);
if (status != OK) {
LOG(ERROR) << "Failed to unmount " << installerTarget;
// Intentional continue to try to unmount the other bind mount
}
}
std::string androidTarget(
StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));