From 981222f500baffae98bfd5949de41257a8238074 Mon Sep 17 00:00:00 2001 From: Zim Date: Mon, 9 Sep 2019 10:24:44 +0100 Subject: [PATCH] Bind mount lower filesystem during FUSE mount When mounting a FUSE device on /mnt/user//, bind mount the correspoinding lower filesystem path to /mnt/pass_through//. At Zygote fork time, an app with the right privilege will have the pass_through path bind mounted into /storage instead of the /mnt/user path. This provides such an app direct access to the lower filesystem without going through FUSE. Bug: 140064376 Test: mount(8) shows /mnt/pass_through/0/emulated is a bind mount of the lower fs Change-Id: I32c3cad64138910fcec9fb8f66b206706b5fd139 --- VolumeManager.cpp | 3 +++ binder/android/os/IVold.aidl | 1 + model/EmulatedVolume.cpp | 9 +++++++-- model/PublicVolume.cpp | 9 +++++++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/VolumeManager.cpp b/VolumeManager.cpp index adb4a5c..0bb87a4 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -487,6 +487,9 @@ int VolumeManager::remountUid(uid_t uid, int32_t mountMode) { case VoldNativeService::REMOUNT_MODE_FULL: mode = "full"; break; + case VoldNativeService::REMOUNT_MODE_PASS_THROUGH: + mode = "pass_through"; + break; default: PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode); return -1; diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index b1af587..ae5a3bc 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -157,6 +157,7 @@ interface IVold { const int REMOUNT_MODE_LEGACY = 4; const int REMOUNT_MODE_INSTALLER = 5; const int REMOUNT_MODE_FULL = 6; + const int REMOUNT_MODE_PASS_THROUGH = 7; const int VOLUME_STATE_UNMOUNTED = 0; const int VOLUME_STATE_CHECKING = 1; diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp index 022ff42..4910803 100644 --- a/model/EmulatedVolume.cpp +++ b/model/EmulatedVolume.cpp @@ -89,13 +89,18 @@ status_t EmulatedVolume::doMount() { if (isFuse) { LOG(INFO) << "Mounting emulated fuse volume"; android::base::unique_fd fd; - int result = MountUserFuse(getMountUserId(), label, &fd); + int user_id = getMountUserId(); + int result = MountUserFuse(user_id, label, &fd); + if (result != 0) { PLOG(ERROR) << "Failed to mount emulated fuse volume"; return -result; } setFuseFd(std::move(fd)); - return OK; + + std::string pass_through_path(StringPrintf("/mnt/pass_through/%d/%s", + user_id, label.c_str())); + return BindMount(getInternalPath(), pass_through_path); } if (!(mFusePid = fork())) { diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp index ebcb91a..d2fcc18 100644 --- a/model/PublicVolume.cpp +++ b/model/PublicVolume.cpp @@ -174,13 +174,18 @@ status_t PublicVolume::doMount() { if (isFuse) { LOG(INFO) << "Mounting public fuse volume"; android::base::unique_fd fd; - int result = MountUserFuse(getMountUserId(), stableName, &fd); + int user_id = getMountUserId(); + int result = MountUserFuse(user_id, stableName, &fd); + if (result != 0) { LOG(ERROR) << "Failed to mount public fuse volume"; return -result; } setFuseFd(std::move(fd)); - return OK; + + std::string pass_through_path(StringPrintf("/mnt/pass_through/%d/%s", + user_id, stableName.c_str())); + return BindMount(getInternalPath(), pass_through_path); } if (!(mFusePid = fork())) {