Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6aa2d320 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by The Android Automerger
Browse files

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
parent b96d0319
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -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) {