diff --git a/VolumeManager.cpp b/VolumeManager.cpp index c56380a..83632e4 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -427,12 +427,26 @@ int VolumeManager::mountPkgSpecificDirsForRunningProcs( return -1; } + std::string obbMountDir = StringPrintf("/mnt/user/%d/obb_mount", userId); + if (fs_prepare_dir(obbMountDir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { + PLOG(ERROR) << "Failed to fs_prepare_dir " << obbMountDir; + return -1; + } + const unique_fd obbMountDirFd( + TEMP_FAILURE_RETRY(open(obbMountDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC))); + if (obbMountDirFd.get() < 0) { + PLOG(ERROR) << "Failed to open " << obbMountDir; + return -1; + } + std::unordered_set validAppIds; for (auto& package : packageNames) { validAppIds.insert(mAppIds[package]); } std::vector& userPackages = mUserPackages[userId]; + std::vector childPids; + struct dirent* de; // Poke through all running PIDs look for apps running in userId while ((de = readdir(dirp.get()))) { @@ -508,17 +522,9 @@ int VolumeManager::mountPkgSpecificDirsForRunningProcs( } } else { mountMode = remountMode; - std::string obbMountFile = StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId, - packagesForUid[0].c_str()); - if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) { - if (access(obbMountFile.c_str(), F_OK) != 0) { - const unique_fd fd( - TEMP_FAILURE_RETRY(open(obbMountFile.c_str(), O_RDWR | O_CREAT, 0660))); - } - } else { - if (access(obbMountFile.c_str(), F_OK) == 0) { - remove(obbMountFile.c_str()); - } + if (handleMountModeInstaller(mountMode, obbMountDirFd.get(), obbMountDir, + sandboxId) < 0) { + _exit(1); } } if (mountMode == VoldNativeService::REMOUNT_MODE_FULL || @@ -573,9 +579,12 @@ int VolumeManager::mountPkgSpecificDirsForRunningProcs( if (child == -1) { PLOG(ERROR) << "Failed to fork"; } else { - TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0)); + childPids.push_back(child); } } + for (auto& child : childPids) { + TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0)); + } return 0; } @@ -597,32 +606,64 @@ int VolumeManager::getMountModeForRunningProc(const std::vector& pa } std::string obbMountFile = - StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId, packagesForUid[0].c_str()); - if (access(obbMountFile.c_str(), F_OK) == 0) { + StringPrintf("/mnt/user/%d/obb_mount/%s", userId, packagesForUid[0].c_str()); + if (TEMP_FAILURE_RETRY(access(obbMountFile.c_str(), F_OK)) != -1) { return VoldNativeService::REMOUNT_MODE_INSTALLER; + } else if (errno != ENOENT) { + PLOG(ERROR) << "Failed to access " << obbMountFile; + return -1; } // Some packages don't have access to external storage and processes belonging to // those packages don't have anything mounted at /storage. So, identify those - // processes by comparing inode no.s of /mnt/user/%d/package/%s + // processes by comparing inode no.s of /mnt/user/%d/package // and /storage - for (auto& package : packagesForUid) { - std::string sandbox = StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str()); - struct stat sandboxStat; - if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &sandboxStat)) == -1) { - PLOG(ERROR) << "Failed to stat " << sandbox; - return -1; + std::string sandbox = StringPrintf("/mnt/user/%d/package", userId); + struct stat sandboxStat; + if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &sandboxStat)) == -1) { + PLOG(ERROR) << "Failed to stat " << sandbox; + return -1; + } + if (storageSb.st_dev == sandboxStat.st_dev && storageSb.st_ino == sandboxStat.st_ino) { + return VoldNativeService::REMOUNT_MODE_WRITE; + } + + return VoldNativeService::REMOUNT_MODE_NONE; +} + +int VolumeManager::handleMountModeInstaller(int mountMode, int obbMountDirFd, + const std::string& obbMountDir, + const std::string& sandboxId) { + if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) { + if (TEMP_FAILURE_RETRY(faccessat(obbMountDirFd, sandboxId.c_str(), F_OK, 0)) != -1) { + return 0; + } else if (errno != ENOENT) { + PLOG(ERROR) << "Failed to access " << obbMountDir << "/" << sandboxId; + return -errno; } - if (storageSb.st_dev == sandboxStat.st_dev && storageSb.st_ino == sandboxStat.st_ino) { - return VoldNativeService::REMOUNT_MODE_WRITE; + const unique_fd fd( + TEMP_FAILURE_RETRY(openat(obbMountDirFd, sandboxId.c_str(), O_RDWR | O_CREAT, 0600))); + if (fd.get() < 0) { + PLOG(ERROR) << "Failed to create " << obbMountDir << "/" << sandboxId; + return -errno; + } + } else { + if (TEMP_FAILURE_RETRY(faccessat(obbMountDirFd, sandboxId.c_str(), F_OK, 0)) != -1) { + if (TEMP_FAILURE_RETRY(unlinkat(obbMountDirFd, sandboxId.c_str(), 0)) == -1) { + PLOG(ERROR) << "Failed to unlink " << obbMountDir << "/" << sandboxId; + return -errno; + } + } else if (errno != ENOENT) { + PLOG(ERROR) << "Failed to access " << obbMountDir << "/" << sandboxId; + return -errno; } } - return VoldNativeService::REMOUNT_MODE_NONE; + return 0; } int VolumeManager::prepareSandboxes(userid_t userId, const std::vector& packageNames, const std::vector& visibleVolLabels) { - prepareSandboxTargets(userId, packageNames, visibleVolLabels); + prepareSandboxTargets(userId, visibleVolLabels); if (visibleVolLabels.empty()) { return 0; @@ -643,122 +684,58 @@ int VolumeManager::prepareSandboxes(userid_t userId, const std::vector& packageNames, const std::vector& visibleVolLabels) { std::string mntTargetRoot = StringPrintf("/mnt/user/%d", userId); if (fs_prepare_dir(mntTargetRoot.c_str(), 0751, AID_ROOT, AID_ROOT) != 0) { - PLOG(ERROR) << "Failed to fs_prepare_dir %s" << mntTargetRoot; + PLOG(ERROR) << "Failed to fs_prepare_dir " << mntTargetRoot; return -errno; } + StringAppendF(&mntTargetRoot, "/package"); - if (fs_prepare_dir(mntTargetRoot.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { - PLOG(ERROR) << "Failed to fs_prepare_dir %s" << mntTargetRoot; + if (fs_prepare_dir(mntTargetRoot.c_str(), 0755, AID_ROOT, AID_ROOT) != 0) { + PLOG(ERROR) << "Failed to fs_prepare_dir " << mntTargetRoot; return -errno; } - const unique_fd dfd(open(mntTargetRoot.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); - if (dfd.get() < 0) { - PLOG(ERROR) << "Failed to open " << mntTargetRoot; + uid_t uid = multiuser_get_uid(userId, AID_EVERYBODY); + for (auto& volumeLabel : visibleVolLabels) { + std::string sandboxTarget = + StringPrintf("%s/%s", mntTargetRoot.c_str(), volumeLabel.c_str()); + if (fs_prepare_dir(sandboxTarget.c_str(), 0755, AID_ROOT, AID_ROOT) != 0) { + PLOG(ERROR) << "Failed to fs_prepare_dir " << sandboxTarget; + return -errno; + } + + if (mPrimary && volumeLabel == mPrimary->getLabel() && mPrimary->isEmulated()) { + StringAppendF(&sandboxTarget, "/%d", userId); + if (fs_prepare_dir(sandboxTarget.c_str(), 0755, AID_ROOT, AID_ROOT) != 0) { + PLOG(ERROR) << "Failed to fs_prepare_dir " << sandboxTarget; + return -errno; + } + } + } + + StringAppendF(&mntTargetRoot, "/self"); + if (fs_prepare_dir(mntTargetRoot.c_str(), 0755, AID_ROOT, AID_ROOT) != 0) { + PLOG(ERROR) << "Failed to fs_prepare_dir " << mntTargetRoot; return -errno; } - for (auto& package : packageNames) { - const auto& it = mAppIds.find(package); - if (it == mAppIds.end()) { - PLOG(ERROR) << "appId is not available for " << package; - continue; - } - appid_t appId = it->second; - uid_t uid = multiuser_get_uid(userId, appId); - if (TEMP_FAILURE_RETRY(faccessat(dfd.get(), package.c_str(), F_OK, 0)) == 0) { - continue; - } else if (errno != ENOENT) { - PLOG(ERROR) << "Failed to faccessat " << mntTargetRoot << "/" << package; - } - if (TEMP_FAILURE_RETRY(mkdirat(dfd.get(), package.c_str(), 0755)) == -1 && errno != EEXIST) { - PLOG(ERROR) << "Failed to mkdirat " << mntTargetRoot << "/" << package; - return -errno; - } - if (TEMP_FAILURE_RETRY(fchownat(dfd.get(), package.c_str(), uid, uid, 0)) == -1) { - PLOG(ERROR) << "Failed to fchownat " << mntTargetRoot << "/" << package; - return -errno; - } - } - std::string pkgPrimarySource(kEmptyString); if (mPrimary) { - StringAppendF(&pkgPrimarySource, "%s", mPrimary->getPath().c_str()); + std::string pkgPrimarySource(mPrimary->getPath()); if (mPrimary->isEmulated()) { StringAppendF(&pkgPrimarySource, "/%d", userId); } - } - for (auto& package : packageNames) { - const auto& it = mAppIds.find(package); - if (it == mAppIds.end()) { - PLOG(ERROR) << "appId is not available for " << package; - continue; - } - appid_t appId = it->second; - uid_t uid = multiuser_get_uid(userId, appId); - - std::string pkgMountTarget = StringPrintf("%s/%s", mntTargetRoot.c_str(), package.c_str()); - const unique_fd packageFd( - openat(dfd.get(), package.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); - if (packageFd.get() < 0) { - PLOG(ERROR) << "Failed to openat " << mntTargetRoot << "/" << package; - return -errno; - } - for (auto& volumeLabel : visibleVolLabels) { - if (TEMP_FAILURE_RETRY(faccessat(packageFd.get(), volumeLabel.c_str(), F_OK, 0)) == 0) { - continue; - } else if (errno != ENOENT) { - PLOG(ERROR) << "Failed to faccessat " << pkgMountTarget << "/" << volumeLabel; - } - if (TEMP_FAILURE_RETRY(mkdirat(packageFd.get(), volumeLabel.c_str(), 0755)) == -1 && - errno != EEXIST) { - PLOG(ERROR) << "Failed to mkdirat " << pkgMountTarget << "/" << volumeLabel; - return -errno; - } - if (TEMP_FAILURE_RETRY(fchownat(packageFd.get(), volumeLabel.c_str(), uid, uid, 0)) == - -1) { - PLOG(ERROR) << "Failed to fchownat " << pkgMountTarget << "/" << volumeLabel; - return -errno; - } - - if (mPrimary && volumeLabel == mPrimary->getLabel() && mPrimary->isEmulated()) { - std::string path = - StringPrintf("%s/%s/%d", pkgMountTarget.c_str(), volumeLabel.c_str(), userId); - if (TEMP_FAILURE_RETRY(mkdir(path.c_str(), 0755)) == -1 && errno != EEXIST) { - PLOG(ERROR) << "Failed to mkdir " << path; - return -errno; - } - if (TEMP_FAILURE_RETRY(chown(path.c_str(), uid, uid)) == -1) { - PLOG(ERROR) << "Failed to chown " << path; - } - } - } - if (TEMP_FAILURE_RETRY(faccessat(packageFd.get(), "self", F_OK, 0)) == -1) { - if (errno == ENOENT) { - if (TEMP_FAILURE_RETRY(mkdirat(packageFd.get(), "self", 0755)) == -1 && - errno != EEXIST) { - PLOG(ERROR) << "Failed to mkdirat " << pkgMountTarget << "/self"; - return -errno; - } - if (TEMP_FAILURE_RETRY(fchownat(packageFd.get(), "self", uid, uid, 0)) == -1) { - PLOG(ERROR) << "Failed to fchownat " << pkgMountTarget << "/self"; - return -errno; - } - } else { - PLOG(ERROR) << "Failed to faccessat " << pkgMountTarget << "/self"; - return -errno; - } - } - std::string pkgPrimaryTarget = StringPrintf("%s/self/primary", pkgMountTarget.c_str()); - if (mPrimary && Symlink(pkgPrimarySource, pkgPrimaryTarget) < 0) { + StringAppendF(&mntTargetRoot, "/primary"); + if (Symlink(pkgPrimarySource, mntTargetRoot) < 0) { return -errno; } } @@ -849,12 +826,10 @@ int VolumeManager::onUserStopped(userid_t userId) { if (hasIsolatedStorage()) { auto& userPackages = mUserPackages[userId]; std::string userMntTargetRoot = StringPrintf("/mnt/user/%d", userId); - for (auto& package : userPackages) { - std::string pkgPrimaryDir = StringPrintf("%s/package/%s/self/primary", - userMntTargetRoot.c_str(), package.c_str()); - if (Unlink(pkgPrimaryDir) < 0) { - return -errno; - } + std::string pkgPrimaryDir = + StringPrintf("%s/package/self/primary", userMntTargetRoot.c_str()); + if (Unlink(pkgPrimaryDir) < 0) { + return -errno; } mUserPackages.erase(userId); if (DeleteDirContentsAndDir(userMntTargetRoot) < 0) { @@ -946,13 +921,6 @@ int VolumeManager::destroySandboxForApp(const std::string& packageName, } } } - std::string pkgMountTargetDir = - StringPrintf("/mnt/user/%d/package/%s", userId, packageName.c_str()); - std::string pkgPrimaryDir = StringPrintf("%s/self/primary", pkgMountTargetDir.c_str()); - if (Unlink(pkgPrimaryDir) < 0) { - return -errno; - } - DeleteDirContentsAndDir(pkgMountTargetDir); return 0; } @@ -974,11 +942,6 @@ int VolumeManager::destroySandboxForAppOnVol(const std::string& packageName, return -errno; } - std::string pkgMountTargetDir = - StringPrintf("/mnt/user/%d/package/%s/%s", userId, packageName.c_str(), volLabel.c_str()); - // It's okay if this fails - DeleteDirContentsAndDir(pkgMountTargetDir); - return 0; } @@ -1062,16 +1025,13 @@ int VolumeManager::onVolumeUnmounted(android::vold::VolumeBase* vol) { int VolumeManager::destroySandboxesForVol(android::vold::VolumeBase* vol, userid_t userId) { LOG(VERBOSE) << "destroysandboxesForVol: " << vol << " for user=" << userId; - const std::vector& packageNames = mUserPackages[userId]; - for (auto& packageName : packageNames) { - std::string volSandboxRoot = StringPrintf("/mnt/user/%d/package/%s/%s", userId, - packageName.c_str(), vol->getLabel().c_str()); - if (android::vold::DeleteDirContentsAndDir(volSandboxRoot) < 0) { - PLOG(ERROR) << "DeleteDirContentsAndDir failed on " << volSandboxRoot; - continue; - } - LOG(VERBOSE) << "Success: DeleteDirContentsAndDir on " << volSandboxRoot; + std::string volSandboxRoot = + StringPrintf("/mnt/user/%d/package/%s", userId, vol->getLabel().c_str()); + if (android::vold::DeleteDirContentsAndDir(volSandboxRoot) < 0) { + PLOG(ERROR) << "DeleteDirContentsAndDir failed on " << volSandboxRoot; + return -errno; } + LOG(VERBOSE) << "Success: DeleteDirContentsAndDir on " << volSandboxRoot; return 0; } diff --git a/VolumeManager.h b/VolumeManager.h index e369f68..bb93b13 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -152,8 +152,9 @@ class VolumeManager { int prepareSandboxes(userid_t userId, const std::vector& packageNames, const std::vector& visibleVolLabels); - int prepareSandboxTargets(userid_t userId, const std::vector& packageNames, - const std::vector& visibleVolLabels); + int prepareSandboxTargets(userid_t userId, const std::vector& visibleVolLabels); + int handleMountModeInstaller(int mountMode, int obbMountDirFd, const std::string& obbMountDir, + const std::string& sandboxId); int mountPkgSpecificDirsForRunningProcs(userid_t userId, const std::vector& packageNames, const std::vector& visibleVolLabels,