summaryrefslogtreecommitdiffstats
path: root/core/jni/com_android_internal_os_Zygote.cpp
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2015-06-30 15:56:33 -0700
committerJeff Sharkey <jsharkey@android.com>2015-06-30 15:56:33 -0700
commitfaf3f692174be30ef9226981e640bc9a09c4da97 (patch)
treece04d548146a7ce823b3b457069f27a1d4cde61d /core/jni/com_android_internal_os_Zygote.cpp
parent4954aff536d4fcf163f410fa83fca30dc9fde4ca (diff)
downloadframeworks_base-faf3f692174be30ef9226981e640bc9a09c4da97.zip
frameworks_base-faf3f692174be30ef9226981e640bc9a09c4da97.tar.gz
frameworks_base-faf3f692174be30ef9226981e640bc9a09c4da97.tar.bz2
Fully unmount existing storage in Zygote.
Before mounting the requested storage into place, fully unmount all existing mounts inherited from the root namespace. Bug: 22192518 Change-Id: I6f7f12c1219d25ee487a031d37c60fb4051d24ad
Diffstat (limited to 'core/jni/com_android_internal_os_Zygote.cpp')
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp36
1 files changed, 34 insertions, 2 deletions
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index f7cfe0e..db88962 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -20,9 +20,13 @@
#include <sys/mount.h>
#include <linux/fs.h>
+#include <list>
+#include <string>
+
#include <fcntl.h>
#include <grp.h>
#include <inttypes.h>
+#include <mntent.h>
#include <paths.h>
#include <signal.h>
#include <stdlib.h>
@@ -249,6 +253,34 @@ static void SetSchedulerPolicy(JNIEnv* env) {
}
}
+static int UnmountTree(const char* path) {
+ size_t path_len = strlen(path);
+
+ FILE* fp = setmntent("/proc/mounts", "r");
+ if (fp == NULL) {
+ ALOGE("Error opening /proc/mounts: %s", strerror(errno));
+ return -errno;
+ }
+
+ // Some volumes can be stacked on each other, so force unmount in
+ // reverse order to give us the best chance of success.
+ std::list<std::string> toUnmount;
+ mntent* mentry;
+ while ((mentry = getmntent(fp)) != NULL) {
+ if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
+ toUnmount.push_front(std::string(mentry->mnt_dir));
+ }
+ }
+ endmntent(fp);
+
+ for (auto path : toUnmount) {
+ if (umount2(path.c_str(), MNT_DETACH)) {
+ ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
+ }
+ }
+ return 0;
+}
+
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -262,7 +294,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
}
// Unmount storage provided by root namespace and mount requested view
- umount2("/storage", MNT_FORCE);
+ UnmountTree("/storage");
String8 storageSource;
if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
@@ -281,7 +313,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
return false;
}
- // Mount user-specific symlink helpers into place
+ // Mount user-specific symlink helper into place
userid_t user_id = multiuser_get_user_id(uid);
const String8 userSource(String8::format("/mnt/user/%d", user_id));
if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {