From e9f7bc3e204025671987eae54086af5fa2097d3c Mon Sep 17 00:00:00 2001 From: Risan Date: Thu, 15 Nov 2018 15:14:36 +0900 Subject: [PATCH] Revert "Change AppFuse mount location to vold namespace" This reverts commit 5f53cd3b79021843a4b0a72dfdc983f14a6023ac. Test: Presubmit Change-Id: Ib2b349018c9e57cb7f5e6f755dcf8f97e9b2f255 --- VoldNativeService.cpp | 25 +------ VoldNativeService.h | 6 +- VolumeManager.cpp | 139 ++++++++++++++++++++++++----------- VolumeManager.h | 5 +- binder/android/os/IVold.aidl | 6 +- 5 files changed, 106 insertions(+), 75 deletions(-) diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 4254d18..7557dc5 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -654,36 +654,19 @@ binder::Status VoldNativeService::abortIdleMaint( return ok(); } -binder::Status VoldNativeService::mountAppFuse(int32_t uid, int32_t mountId, +binder::Status VoldNativeService::mountAppFuse(int32_t uid, int32_t pid, int32_t mountId, android::base::unique_fd* _aidl_return) { ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; - return translate(VolumeManager::Instance()->mountAppFuse(uid, mountId, _aidl_return)); + return translate(VolumeManager::Instance()->mountAppFuse(uid, pid, mountId, _aidl_return)); } -binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t mountId) { +binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t pid, int32_t mountId) { ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; - return translate(VolumeManager::Instance()->unmountAppFuse(uid, mountId)); -} - -binder::Status VoldNativeService::openAppFuseFile(int32_t uid, int32_t mountId, int32_t fileId, - int32_t flags, - android::base::unique_fd* _aidl_return) { - ENFORCE_UID(AID_SYSTEM); - ACQUIRE_LOCK; - - int fd = VolumeManager::Instance()->openAppFuseFile(uid, mountId, fileId, flags); - if (fd == -1) { - return error("Failed to open AppFuse file for uid: " + std::to_string(uid) + - " mountId: " + std::to_string(mountId) + " fileId: " + std::to_string(fileId) + - " flags: " + std::to_string(flags)); - } - - *_aidl_return = android::base::unique_fd(fd); - return ok(); + return translate(VolumeManager::Instance()->unmountAppFuse(uid, pid, mountId)); } binder::Status VoldNativeService::fdeCheckPassword(const std::string& password) { diff --git a/VoldNativeService.h b/VoldNativeService.h index 726de68..76a21fb 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -82,11 +82,9 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status runIdleMaint(const android::sp& listener); binder::Status abortIdleMaint(const android::sp& listener); - binder::Status mountAppFuse(int32_t uid, int32_t mountId, + binder::Status mountAppFuse(int32_t uid, int32_t pid, int32_t mountId, android::base::unique_fd* _aidl_return); - binder::Status unmountAppFuse(int32_t uid, int32_t mountId); - binder::Status openAppFuseFile(int32_t uid, int32_t mountId, int32_t fileId, int32_t flags, - android::base::unique_fd* _aidl_return); + binder::Status unmountAppFuse(int32_t uid, int32_t pid, int32_t mountId); binder::Status fdeCheckPassword(const std::string& password); binder::Status fdeRestart(); diff --git a/VolumeManager.cpp b/VolumeManager.cpp index 91ee413..f3604ee 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -1280,7 +1280,7 @@ static android::status_t getMountPath(uid_t uid, const std::string& name, std::s return android::OK; } -static android::status_t mount(int device_fd, const std::string& path) { +static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::string& path) { // Remove existing mount. android::vold::ForceUnmount(path); @@ -1289,10 +1289,10 @@ static android::status_t mount(int device_fd, const std::string& path) { "rootmode=40000," "default_permissions," "allow_other," - "user_id=0,group_id=0," + "user_id=%d,group_id=%d," "context=\"u:object_r:app_fuse_file:s0\"," "fscontext=u:object_r:app_fusefs:s0", - device_fd); + device_fd, uid, uid); const int result = TEMP_FAILURE_RETRY(mount("/dev/fuse", path.c_str(), "fuse", @@ -1305,34 +1305,101 @@ static android::status_t mount(int device_fd, const std::string& path) { return android::OK; } -static android::status_t runCommand(const std::string& command, uid_t uid, const std::string& path, - int device_fd) { +static android::status_t runCommandInNamespace(const std::string& command, uid_t uid, pid_t pid, + const std::string& path, int device_fd) { if (DEBUG_APPFUSE) { - LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path << " and uid " - << uid; - } - - if (command == "mount") { - return mount(device_fd, path); - } else if (command == "unmount") { - // If it's just after all FD opened on mount point are closed, umount2 can fail with - // EBUSY. To avoid the case, specify MNT_DETACH. - if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && errno != EINVAL && - errno != ENOENT) { - PLOG(ERROR) << "Failed to unmount directory."; + LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path + << " in namespace " << uid; + } + + unique_fd dir(open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC)); + if (dir.get() == -1) { + PLOG(ERROR) << "Failed to open /proc"; + return -errno; + } + + // Obtains process file descriptor. + const std::string pid_str = StringPrintf("%d", pid); + const unique_fd pid_fd(openat(dir.get(), pid_str.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); + if (pid_fd.get() == -1) { + PLOG(ERROR) << "Failed to open /proc/" << pid; + return -errno; + } + + // Check UID of process. + { + struct stat sb; + const int result = fstat(pid_fd.get(), &sb); + if (result == -1) { + PLOG(ERROR) << "Failed to stat /proc/" << pid; return -errno; } - if (rmdir(path.c_str()) != 0) { - PLOG(ERROR) << "Failed to remove the mount directory."; - return -errno; + if (sb.st_uid != AID_SYSTEM) { + LOG(ERROR) << "Only system can mount appfuse. UID expected=" << AID_SYSTEM + << ", actual=" << sb.st_uid; + return -EPERM; } - return android::OK; - } else { - LOG(ERROR) << "Unknown appfuse command " << command; - return -EPERM; } - return android::OK; + // Matches so far, but refuse to touch if in root namespace + { + std::string rootName; + std::string pidName; + if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName) || + !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) { + PLOG(ERROR) << "Failed to read namespaces"; + return -EPERM; + } + if (rootName == pidName) { + LOG(ERROR) << "Don't mount appfuse in root namespace"; + return -EPERM; + } + } + + // We purposefully leave the namespace open across the fork + unique_fd ns_fd(openat(pid_fd.get(), "ns/mnt", O_RDONLY)); // not O_CLOEXEC + if (ns_fd.get() < 0) { + PLOG(ERROR) << "Failed to open namespace for /proc/" << pid << "/ns/mnt"; + return -errno; + } + + int child = fork(); + if (child == 0) { + if (setns(ns_fd.get(), CLONE_NEWNS) != 0) { + PLOG(ERROR) << "Failed to setns"; + _exit(-errno); + } + + if (command == "mount") { + _exit(mountInNamespace(uid, device_fd, path)); + } else if (command == "unmount") { + // If it's just after all FD opened on mount point are closed, umount2 can fail with + // EBUSY. To avoid the case, specify MNT_DETACH. + if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && errno != EINVAL && + errno != ENOENT) { + PLOG(ERROR) << "Failed to unmount directory."; + _exit(-errno); + } + if (rmdir(path.c_str()) != 0) { + PLOG(ERROR) << "Failed to remove the mount directory."; + _exit(-errno); + } + _exit(android::OK); + } else { + LOG(ERROR) << "Unknown appfuse command " << command; + _exit(-EPERM); + } + } + + if (child == -1) { + PLOG(ERROR) << "Failed to folk child process"; + return -errno; + } + + android::status_t status; + TEMP_FAILURE_RETRY(waitpid(child, &status, 0)); + + return status; } int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey, @@ -1387,7 +1454,7 @@ int VolumeManager::destroyStubVolume(const std::string& volId) { return android::OK; } -int VolumeManager::mountAppFuse(uid_t uid, int mountId, unique_fd* device_fd) { +int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, unique_fd* device_fd) { std::string name = std::to_string(mountId); // Check mount point name. @@ -1412,10 +1479,10 @@ int VolumeManager::mountAppFuse(uid_t uid, int mountId, unique_fd* device_fd) { } // Mount. - return runCommand("mount", uid, path, device_fd->get()); + return runCommandInNamespace("mount", uid, pid, path, device_fd->get()); } -int VolumeManager::unmountAppFuse(uid_t uid, int mountId) { +int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) { std::string name = std::to_string(mountId); // Check mount point name. @@ -1425,19 +1492,5 @@ int VolumeManager::unmountAppFuse(uid_t uid, int mountId) { return -1; } - return runCommand("unmount", uid, path, -1 /* device_fd */); -} - -int VolumeManager::openAppFuseFile(uid_t uid, int mountId, int fileId, int flags) { - std::string name = std::to_string(mountId); - - // Check mount point name. - std::string mountPoint; - if (getMountPath(uid, name, &mountPoint) != android::OK) { - LOG(ERROR) << "Invalid mount point name"; - return -1; - } - - std::string path = StringPrintf("%s/%d", mountPoint.c_str(), fileId); - return TEMP_FAILURE_RETRY(open(path.c_str(), flags)); + return runCommandInNamespace("unmount", uid, pid, path, -1 /* device_fd */); } diff --git a/VolumeManager.h b/VolumeManager.h index 6d3a987..e25e244 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -141,9 +141,8 @@ class VolumeManager { const std::string& fsLabel, std::string* outVolId); int destroyStubVolume(const std::string& volId); - int mountAppFuse(uid_t uid, int mountId, android::base::unique_fd* device_fd); - int unmountAppFuse(uid_t uid, int mountId); - int openAppFuseFile(uid_t uid, int mountId, int fileId, int flags); + int mountAppFuse(uid_t uid, pid_t pid, int mountId, android::base::unique_fd* device_fd); + int unmountAppFuse(uid_t uid, pid_t pid, int mountId); private: VolumeManager(); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 2f7430f..c45d509 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -62,8 +62,8 @@ interface IVold { void runIdleMaint(IVoldTaskListener listener); void abortIdleMaint(IVoldTaskListener listener); - FileDescriptor mountAppFuse(int uid, int mountId); - void unmountAppFuse(int uid, int mountId); + FileDescriptor mountAppFuse(int uid, int pid, int mountId); + void unmountAppFuse(int uid, int pid, int mountId); void fdeCheckPassword(@utf8InCpp String password); void fdeRestart(); @@ -119,8 +119,6 @@ interface IVold { @utf8InCpp String fsUuid, @utf8InCpp String fsLabel); void destroyStubVolume(@utf8InCpp String volId); - FileDescriptor openAppFuseFile(int uid, int mountId, int fileId, int flags); - const int ENCRYPTION_FLAG_NO_UI = 4; const int ENCRYPTION_STATE_NONE = 1;