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
This commit is contained in:
Ricky Wai 2021-01-15 14:03:23 +00:00 committed by rickywai
parent 610eba0ad0
commit a2ca11e49b
5 changed files with 73 additions and 12 deletions

View file

@ -377,7 +377,17 @@ binder::Status VoldNativeService::remountAppStorageDirs(int uid, int pid,
ENFORCE_SYSTEM_OR_ROOT; ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK; 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<std::string>& 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) { binder::Status VoldNativeService::setupAppDir(const std::string& path, int32_t appUid) {

View file

@ -66,6 +66,8 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
binder::Status remountUid(int32_t uid, int32_t remountMode); binder::Status remountUid(int32_t uid, int32_t remountMode);
binder::Status remountAppStorageDirs(int uid, int pid, binder::Status remountAppStorageDirs(int uid, int pid,
const std::vector<std::string>& packageNames); const std::vector<std::string>& packageNames);
binder::Status unmountAppStorageDirs(int uid, int pid,
const std::vector<std::string>& packageNames);
binder::Status ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid); binder::Status ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid);
binder::Status setupAppDir(const std::string& path, int32_t appUid); binder::Status setupAppDir(const std::string& path, int32_t appUid);

View file

@ -683,6 +683,43 @@ bool scanProcProcesses(uid_t uid, userid_t userId, ScanProcCallback callback, vo
return true; 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 // In each app's namespace, mount tmpfs on obb and data dir, and bind mount obb and data
// package dirs. // package dirs.
static bool remountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir, 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()); userId, dirName.c_str(), packageName.c_str());
} }
// Fork the process and remount storage // Fork the process and remount / unmount app data and obb dirs
bool VolumeManager::forkAndRemountStorage(int uid, int pid, bool VolumeManager::forkAndRemountStorage(int uid, int pid, bool doUnmount,
const std::vector<std::string>& packageNames) { const std::vector<std::string>& packageNames) {
userid_t userId = multiuser_get_user_id(uid); userid_t userId = multiuser_get_user_id(uid);
std::string mnt_path = StringPrintf("/proc/%d/ns/mnt", pid); 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 // Fork a child to mount Android/obb android Android/data dirs, as we don't want it to affect
// original vold process mount namespace. // original vold process mount namespace.
if (!(child = fork())) { if (!(child = fork())) {
if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid, if (doUnmount) {
sources_cstr, targets_cstr, size)) { if (umountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
_exit(0); targets_cstr, size)) {
_exit(0);
} else {
_exit(1);
}
} else { } 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; return true;
} }
int VolumeManager::remountAppStorageDirs(int uid, int pid, int VolumeManager::handleAppStorageDirs(int uid, int pid,
const std::vector<std::string>& packageNames) { bool doUnmount, const std::vector<std::string>& packageNames) {
// Only run the remount if fuse is mounted for that user. // Only run the remount if fuse is mounted for that user.
userid_t userId = multiuser_get_user_id(uid); userid_t userId = multiuser_get_user_id(uid);
bool fuseMounted = false; bool fuseMounted = false;
@ -842,7 +888,7 @@ int VolumeManager::remountAppStorageDirs(int uid, int pid,
} }
} }
if (fuseMounted) { if (fuseMounted) {
forkAndRemountStorage(uid, pid, packageNames); forkAndRemountStorage(uid, pid, doUnmount, packageNames);
} }
return 0; return 0;
} }

View file

@ -115,7 +115,8 @@ class VolumeManager {
int onSecureKeyguardStateChanged(bool isShowing); int onSecureKeyguardStateChanged(bool isShowing);
int remountUid(uid_t uid, int32_t remountMode) { return 0; } int remountUid(uid_t uid, int32_t remountMode) { return 0; }
int remountAppStorageDirs(int uid, int pid, const std::vector<std::string>& packageNames); int handleAppStorageDirs(int uid, int pid,
bool doUnmount, const std::vector<std::string>& packageNames);
/* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */ /* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */
int abortFuse(); int abortFuse();
@ -129,7 +130,8 @@ class VolumeManager {
int updateVirtualDisk(); int updateVirtualDisk();
int setDebug(bool enable); int setDebug(bool enable);
bool forkAndRemountStorage(int uid, int pid, const std::vector<std::string>& packageNames); bool forkAndRemountStorage(int uid, int pid, bool doUnmount,
const std::vector<std::string>& packageNames);
static VolumeManager* Instance(); static VolumeManager* Instance();

View file

@ -54,6 +54,7 @@ interface IVold {
void remountUid(int uid, int remountMode); void remountUid(int uid, int remountMode);
void remountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames); 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 setupAppDir(@utf8InCpp String path, int appUid);
void fixupAppDir(@utf8InCpp String path, int appUid); void fixupAppDir(@utf8InCpp String path, int appUid);