From a2ca11e49bdc5bbfa2011d8c48748b5c6f0fcb38 Mon Sep 17 00:00:00 2001 From: Ricky Wai Date: Fri, 15 Jan 2021 14:03:23 +0000 Subject: [PATCH] Add a method in vold to unmount app data and obb dir for testing This new method will be used in new sm command. Tests can use this so data and obb dirs are unmounted, and won't be killed when volume is unmounted. Bug: 148049767 Test: New sm command able to unmount app's data and obb dirs Change-Id: Ifbc661ca510e996abd4b7ce1fb195aaa7afc37ad --- VoldNativeService.cpp | 12 ++++++- VoldNativeService.h | 2 ++ VolumeManager.cpp | 64 +++++++++++++++++++++++++++++++----- VolumeManager.h | 6 ++-- binder/android/os/IVold.aidl | 1 + 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 03dee48..9f4f7b0 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -377,7 +377,17 @@ binder::Status VoldNativeService::remountAppStorageDirs(int uid, int pid, ENFORCE_SYSTEM_OR_ROOT; ACQUIRE_LOCK; - return translate(VolumeManager::Instance()->remountAppStorageDirs(uid, pid, packageNames)); + return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid, + false /* doUnmount */, packageNames)); +} + +binder::Status VoldNativeService::unmountAppStorageDirs(int uid, int pid, + const std::vector& packageNames) { + ENFORCE_SYSTEM_OR_ROOT; + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid, + true /* doUnmount */, packageNames)); } binder::Status VoldNativeService::setupAppDir(const std::string& path, int32_t appUid) { diff --git a/VoldNativeService.h b/VoldNativeService.h index 8fd6261..47991c2 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -66,6 +66,8 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status remountUid(int32_t uid, int32_t remountMode); binder::Status remountAppStorageDirs(int uid, int pid, const std::vector& packageNames); + binder::Status unmountAppStorageDirs(int uid, int pid, + const std::vector& packageNames); binder::Status ensureAppDirsCreated(const std::vector& paths, int32_t appUid); binder::Status setupAppDir(const std::string& path, int32_t appUid); diff --git a/VolumeManager.cpp b/VolumeManager.cpp index bbdcd3a..5b249cb 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -683,6 +683,43 @@ bool scanProcProcesses(uid_t uid, userid_t userId, ScanProcCallback callback, vo return true; } +// In each app's namespace, unmount obb and data dirs +static bool umountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir, + int uid, const char* targets[], int size) { + // This code is executed after a fork so it's very important that the set of + // methods we call here is strictly limited. + if (setns(nsFd, CLONE_NEWNS) != 0) { + async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to setns %s", strerror(errno)); + return false; + } + + // Unmount of Android/data/foo needs to be done before Android/data below. + bool result = true; + for (int i = 0; i < size; i++) { + if (TEMP_FAILURE_RETRY(umount2(targets[i], MNT_DETACH)) < 0 && errno != EINVAL && + errno != ENOENT) { + async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s: %s", + targets[i], strerror(errno)); + result = false; + } + } + + // Mount tmpfs on Android/data and Android/obb + if (TEMP_FAILURE_RETRY(umount2(android_data_dir, MNT_DETACH)) < 0 && errno != EINVAL && + errno != ENOENT) { + async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s", + android_data_dir, strerror(errno)); + result = false; + } + if (TEMP_FAILURE_RETRY(umount2(android_obb_dir, MNT_DETACH)) < 0 && errno != EINVAL && + errno != ENOENT) { + async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s", + android_obb_dir, strerror(errno)); + result = false; + } + return result; +} + // In each app's namespace, mount tmpfs on obb and data dir, and bind mount obb and data // package dirs. static bool remountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir, @@ -741,8 +778,8 @@ static std::string getStorageDirTarget(userid_t userId, std::string dirName, userId, dirName.c_str(), packageName.c_str()); } -// Fork the process and remount storage -bool VolumeManager::forkAndRemountStorage(int uid, int pid, +// Fork the process and remount / unmount app data and obb dirs +bool VolumeManager::forkAndRemountStorage(int uid, int pid, bool doUnmount, const std::vector& packageNames) { userid_t userId = multiuser_get_user_id(uid); std::string mnt_path = StringPrintf("/proc/%d/ns/mnt", pid); @@ -798,11 +835,20 @@ bool VolumeManager::forkAndRemountStorage(int uid, int pid, // Fork a child to mount Android/obb android Android/data dirs, as we don't want it to affect // original vold process mount namespace. if (!(child = fork())) { - if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid, - sources_cstr, targets_cstr, size)) { - _exit(0); + if (doUnmount) { + if (umountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid, + targets_cstr, size)) { + _exit(0); + } else { + _exit(1); + } } else { - _exit(1); + if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid, + sources_cstr, targets_cstr, size)) { + _exit(0); + } else { + _exit(1); + } } } @@ -827,8 +873,8 @@ bool VolumeManager::forkAndRemountStorage(int uid, int pid, return true; } -int VolumeManager::remountAppStorageDirs(int uid, int pid, - const std::vector& packageNames) { +int VolumeManager::handleAppStorageDirs(int uid, int pid, + bool doUnmount, const std::vector& packageNames) { // Only run the remount if fuse is mounted for that user. userid_t userId = multiuser_get_user_id(uid); bool fuseMounted = false; @@ -842,7 +888,7 @@ int VolumeManager::remountAppStorageDirs(int uid, int pid, } } if (fuseMounted) { - forkAndRemountStorage(uid, pid, packageNames); + forkAndRemountStorage(uid, pid, doUnmount, packageNames); } return 0; } diff --git a/VolumeManager.h b/VolumeManager.h index 9640303..3573b1a 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -115,7 +115,8 @@ class VolumeManager { int onSecureKeyguardStateChanged(bool isShowing); int remountUid(uid_t uid, int32_t remountMode) { return 0; } - int remountAppStorageDirs(int uid, int pid, const std::vector& packageNames); + int handleAppStorageDirs(int uid, int pid, + bool doUnmount, const std::vector& packageNames); /* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */ int abortFuse(); @@ -129,7 +130,8 @@ class VolumeManager { int updateVirtualDisk(); int setDebug(bool enable); - bool forkAndRemountStorage(int uid, int pid, const std::vector& packageNames); + bool forkAndRemountStorage(int uid, int pid, bool doUnmount, + const std::vector& packageNames); static VolumeManager* Instance(); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index de381d3..19ce9ba 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -54,6 +54,7 @@ interface IVold { void remountUid(int uid, int remountMode); void remountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames); + void unmountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames); void setupAppDir(@utf8InCpp String path, int appUid); void fixupAppDir(@utf8InCpp String path, int appUid);