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

Commit 663b1046 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Mount package sandboxes during process initialization.

vold creates external storage sandboxes for packages at
/mnt/user/<user-id>/package/<package-name> when the user starts.
These package specific sandboxes will be mounted at /storage
whenever a new process starts.

Bug: 111890351
Test: n/a (changes are protected by a sys property, there's no change in
      behavior without turning on that property)

Change-Id: I8db4ab823c8dccc454e8004b119ba394a08d6475
parent e2f5ce74
Loading
Loading
Loading
Loading
+61 −20
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@
namespace {

using android::String8;
using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::base::GetBoolProperty;
@@ -79,6 +80,7 @@ using android::base::GetBoolProperty;

static pid_t gSystemServerPid = 0;

static const char kIsolatedStorage[] = "persist.sys.isolated_storage";
static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
static jclass gZygoteClass;
static jmethodID gCallPostForkChildHooks;
@@ -379,6 +381,28 @@ static int UnmountTree(const char* path) {
    return 0;
}

static bool createPkgSandbox(uid_t uid, const char* package_name, std::string& pkg_sandbox_dir,
        std::string* error_msg) {
    // Create /mnt/user/0/package/<package-name>
    userid_t user_id = multiuser_get_user_id(uid);
    StringAppendF(&pkg_sandbox_dir, "/%d", user_id);
    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
        return false;
    }
    StringAppendF(&pkg_sandbox_dir, "/package");
    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
        return false;
    }
    StringAppendF(&pkg_sandbox_dir, "/%s", package_name);
    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0755, uid, uid) != 0) {
        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
        return false;
    }
    return true;
}

// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -408,6 +432,22 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
        return true;
    }

    if (GetBoolProperty(kIsolatedStorage, false)) {
        if (package_name == nullptr) {
            return true;
        }

        std::string pkgSandboxDir("/mnt/user");
        if (!createPkgSandbox(uid, package_name, pkgSandboxDir, error_msg)) {
            return false;
        }
        if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
                nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
            *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
                    pkgSandboxDir.c_str(), strerror(errno));
            return false;
        }
    } else {
        if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
                NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
            *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
@@ -430,6 +470,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
                                      strerror(errno));
            return false;
        }
    }

    return true;
}