diff --git a/modules/sandbox/sandbox_utils.cpp b/modules/sandbox/sandbox_utils.cpp index 58cf9da3a6a78ea16ccbab206501dc2038ddb5fa..06311c6327db1beab4ff8172986b384ec24e9037 100644 --- a/modules/sandbox/sandbox_utils.cpp +++ b/modules/sandbox/sandbox_utils.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "appspawn_hook.h" #include "appspawn_mount_permission.h" @@ -1864,10 +1866,16 @@ int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property) #define DIR_MODE 0711 #ifndef APPSPAWN_SANDBOX_NEW +static const MountSharedTemplate MOUNT_SHARED_MAP[] = { + {"/data/storage/el2", nullptr}, + {"/data/storage/el3", nullptr}, + {"/data/storage/el4", nullptr}, + {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, +}; + static bool IsUnlockStatus(uint32_t uid) { - const int userIdBase = 200000; - uid = uid / userIdBase; + uid = uid / UID_BASE; if (uid == 0) { return true; } @@ -1881,126 +1889,185 @@ static bool IsUnlockStatus(uint32_t uid) return false; } -static void MountDir(const AppSpawningCtx *property, const char *rootPath, const char *srcPath, const char *targetPath) +#define PATH_MAX_LEN 256 +static int DoSharedMount(const MountArgs *arg) { - const int userIdBase = 200000; - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - const char *bundleName = GetBundleName(property); - if (info == NULL || bundleName == NULL) { - return; + if (arg == nullptr || arg->srcPath == nullptr || arg->destPath == nullptr) { + APPSPAWN_LOGE("Invalid arg"); + return APPSPAWN_ARG_INVALID; } - size_t allPathSize = strlen(rootPath) + strlen(targetPath) + strlen(bundleName) + 2; - allPathSize += USER_ID_SIZE; - char *path = reinterpret_cast(malloc(sizeof(char) * (allPathSize))); - APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path"); - int len = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, info->uid / userIdBase, bundleName, targetPath); - APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); - return, "Failed to get sandbox path"); - if (srcPath != nullptr) { - g_mountInfo[string(bundleName)]++; - } + APPSPAWN_LOGV("Mount arg: '%{public}s' '%{public}s' %{public}lu '%{public}s' %{public}s => %{public}s", + arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE", + arg->mountFlags, arg->options, arg->srcPath, arg->destPath); - if (access(path, F_OK) == 0 && srcPath == nullptr) { - free(path); - return; + int ret = mount(arg->srcPath, arg->destPath, arg->fsType, arg->mountFlags, arg->options); + if (ret != 0) { + APPSPAWN_LOGI("mount %{public}s to %{public}s failed, errno %{public}d", + arg->srcPath, arg->destPath, errno); + return ret; } - - MakeDirRec(path, DIR_MODE, 1); - const char *sourcePath = (srcPath == nullptr) ? path : srcPath; - if (srcPath != nullptr) { - int ret = umount2(path, MNT_DETACH); - APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount path %{public}s, errno %{public}d", path, errno); + ret = mount(nullptr, arg->destPath, nullptr, arg->mountSharedFlag, nullptr); + if (ret != 0) { + APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", arg->destPath, errno); + return ret; } + APPSPAWN_LOGI("mount path %{public}s to shared success", arg->destPath); + return 0; +} - if (mount(sourcePath, path, nullptr, MS_BIND | MS_REC, nullptr) != 0) { - APPSPAWN_LOGI("bind mount %{public}s to %{public}s failed, error %{public}d", sourcePath, path, errno); - free(path); +static void GetMountInfo(std::vector &sharedMounts) +{ + std::ifstream file("/proc/self/mountinfo"); + if (!file.is_open()) { return; } - if (mount(nullptr, path, nullptr, MS_SHARED, nullptr) != 0) { - APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno); - free(path); - return; + + std::string line; + while (std::getline(file, line)) { + if (line.find("shared:") != std::string::npos) { + sharedMounts.push_back(line); + } } - APPSPAWN_LOGI("mount path %{public}s to shared success", path); - free(path); - return; + file.close(); } -static const MountSharedTemplate MOUNT_SHARED_MAP[] = { - {"/data/storage/el2", nullptr}, - {"/data/storage/el3", nullptr}, - {"/data/storage/el4", nullptr}, - {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, -}; +static bool IsSandboxPathShared(const std::vector &sharedMounts, const std::string &sandboxPath) +{ + std::regex mountPoint(sandboxPath); + for (const auto &sharedMount : sharedMounts) { + if (std::regex_search(sharedMount, mountPoint)) { + return true; + } + } + return false; +} -#define PATH_MAX_LEN 256 -static int MountInShared(const AppSpawningCtx *property, const char *rootPath, const char *src, const char *target) +static int MountEl1Bundle(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) { - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - const char *bundleName = GetBundleName(property); - if (info == NULL || bundleName == NULL) { - return APPSPAWN_ARG_INVALID; + /* /data/app/el1/bundle/public/ */ + char sourcePath[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sourcePath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/data/app/el1/bundle/public/%s", bundleName); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf data/app/el1/bundle/public/%{public}s failed, errno %{public}d", bundleName, errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - char path[PATH_MAX_LEN] = {0}; - int ret = snprintf_s(path, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s/%u/%s/%s", rootPath, info->uid / UID_BASE, - bundleName, target); + /* /mnt/sandbox///data/storage/el1/bundle */ + char targetPath[PATH_MAX_LEN] = {0}; + ret = snprintf_s(targetPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%d/%s/data/storage/el1/bundle", + info->uid/ UID_BASE, bundleName); if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s path failed, errno %{public}d", errno); + APPSPAWN_LOGE("snprintf el1 bundle sandbox path failed, errno %{public}d", errno); return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - char currentUserPath[PATH_MAX_LEN] = {0}; - ret = snprintf_s(currentUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s/currentUser", path); + ret = MakeDirRec(targetPath, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", targetPath, errno); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + ret = umount2(targetPath, MNT_DETACH); + if (ret < 0) { + APPSPAWN_LOGE("umount2 %{public}s failed, errno %{public}d", targetPath, errno); + } + + MountArgs arg = {}; + arg.srcPath = sourcePath; + arg.destPath = targetPath; + arg.fsType = nullptr; + arg.mountFlags = MS_BIND | MS_REC; + arg.options = nullptr; + arg.mountSharedFlag = MS_SHARED; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", targetPath, ret); + return ret; + } + return 0; +} + +static int MountWithFileMgr(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ + /* /mnt/user//nosharefs/docs */ + char nosharefsDocsDir[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(nosharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/user/%u/nosharefs/docs", + info->uid / UID_BASE); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf nosharefsDocsDir failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + /* /mnt/sandbox//storage/Users */ + char storageUserPath[PATH_MAX_LEN] = {0}; + ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%d/%s/storage/Users", + info->uid / UID_BASE, bundleName); if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s currentUserPath failed, errno %{public}d", errno); + APPSPAWN_LOGE("snprintf nosharefsDocsDir failed, errno %{public}d", errno); return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - if (access(currentUserPath, F_OK) == 0) { + // Check whether the directory is a shared mount point + std::vector sharedMounts; + GetMountInfo(sharedMounts); + if (IsSandboxPathShared(sharedMounts, storageUserPath)) { + APPSPAWN_LOGI("shared mountpoint is exist"); return 0; } - ret = MakeDirRec(path, DIR_MODE, 1); + ret = MakeDirRec(storageUserPath, DIR_MODE, 1); if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", storageUserPath, errno); return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; } - if (mount(src, path, nullptr, MS_BIND | MS_REC, nullptr) != 0) { - APPSPAWN_LOGI("bind mount %{public}s to %{public}s failed, error %{public}d", src, path, errno); - return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; - } - if (mount(nullptr, path, nullptr, MS_SHARED, nullptr) != 0) { - APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno); - return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; + MountArgs arg = {}; + arg.srcPath = nosharefsDocsDir; + arg.destPath = storageUserPath; + arg.fsType = nullptr; + arg.mountFlags = MS_BIND | MS_REC; + arg.options = nullptr; + arg.mountSharedFlag = MS_SHARED; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", storageUserPath, ret); + return ret; } - return 0; } -static int SharedMountInSharefs(const AppSpawningCtx *property, const char *rootPath, - const char *src, const char *target) +static int MountWithOther(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) { - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - if (info == NULL) { - return APPSPAWN_ARG_INVALID; + /* /mnt/user//sharefs/docs */ + char sharefsDocsDir[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/user/%u/sharefs/docs", + info->uid / UID_BASE); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf sharefsDocsDir failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - char currentUserPath[PATH_MAX_LEN] = {0}; - int ret = snprintf_s(currentUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s/currentUser", target); + /* /mnt/sandbox//storage/Users */ + char storageUserPath[PATH_MAX_LEN] = {0}; + ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%d/%s/storage/Users", + info->uid / UID_BASE, bundleName); if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s currentUserPath failed, errno %{public}d", errno); + APPSPAWN_LOGE("snprintf nosharefsDocsDir failed, errno %{public}d", errno); return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - if (access(currentUserPath, F_OK) == 0) { + // Check whether the directory is a shared mount point + std::vector sharedMounts; + GetMountInfo(sharedMounts); + if (IsSandboxPathShared(sharedMounts, storageUserPath)) { + APPSPAWN_LOGI("shared mountpoint is exist"); return 0; } - ret = MakeDirRec(target, DIR_MODE, 1); + ret = MakeDirRec(storageUserPath, DIR_MODE, 1); if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", storageUserPath, errno); return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; } @@ -2008,114 +2075,129 @@ static int SharedMountInSharefs(const AppSpawningCtx *property, const char *root ret = snprintf_s(options, PATH_MAX_LEN, PATH_MAX_LEN - 1, "override_support_delete,user_id=%u", info->uid / UID_BASE); if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s options failed, errno %{public}d", errno); + APPSPAWN_LOGE("snprintf options failed, errno %{public}d", errno); return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - if (mount(src, target, "sharefs", MS_NODEV, options) != 0) { - APPSPAWN_LOGE("sharefs mount %{public}s to %{public}s failed, error %{public}d", - src, target, errno); - return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; - } - if (mount(nullptr, target, nullptr, MS_SHARED, nullptr) != 0) { - APPSPAWN_LOGE("mount path %{public}s to shared failed, errno %{public}d", target, errno); - return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; + MountArgs arg = {}; + arg.srcPath = sharefsDocsDir; + arg.destPath = storageUserPath; + arg.fsType = "sharefs"; + arg.mountFlags = MS_NODEV; + arg.options = options; + arg.mountSharedFlag = MS_SHARED; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", storageUserPath, ret); + return ret; } - return 0; } -static void UpdateStorageDir(const AppSpawningCtx *property) +static void MountStorageUsers(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) { - const char mntUser[] = "/mnt/user"; - const char nosharefsDocs[] = "nosharefs/docs"; - const char sharefsDocs[] = "sharefs/docs"; - const char rootPath[] = "/mnt/sandbox"; - const char userPath[] = "/storage/Users"; - - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - if (info == nullptr) { - return; - } - - /* /mnt/user//nosharefs/Docs */ - char nosharefsDocsDir[PATH_MAX_LEN] = {0}; - int ret = snprintf_s(nosharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s/%u/%s", - mntUser, info->uid / UID_BASE, nosharefsDocs); - if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s nosharefsDocsDir failed, errno %{public}d", errno); - return; - } - - /* /mnt/user//sharefs/Docs */ - char sharefsDocsDir[PATH_MAX_LEN] = {0}; - ret = snprintf_s(sharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s/%u/%s", - mntUser, info->uid / UID_BASE, sharefsDocs); - if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s sharefsDocsDir failed, errno %{public}d", errno); - return; - } - + int ret = 0; int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER"); - int res = CheckAppPermissionFlagSet(property, static_cast(index)); - if (res == 0) { - char storageUserPath[PATH_MAX_LEN] = {0}; - const char *bundleName = GetBundleName(property); - ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s/%u/%s/%s", rootPath, info->uid / UID_BASE, - bundleName, userPath); - if (ret <= 0) { - APPSPAWN_LOGE("snprintf_s storageUserPath failed, errno %{public}d", errno); - return; - } + int checkRes = CheckAppPermissionFlagSet(property, static_cast(index)); + if (checkRes == 0) { /* mount /mnt/user//sharefs/docs to /mnt/sandbox///storage/Users */ - ret = SharedMountInSharefs(property, rootPath, sharefsDocsDir, storageUserPath); + ret = MountWithOther(property, info, bundleName); } else { /* mount /mnt/user//nosharefs/docs to /mnt/sandbox///storage/Users */ - ret = MountInShared(property, rootPath, nosharefsDocsDir, userPath); + ret = MountWithFileMgr(property, info, bundleName); } if (ret != 0) { - APPSPAWN_LOGE("Update storage dir, ret %{public}d", ret); + APPSPAWN_LOGE("Update storage dir failed, ret %{public}d", ret); } - APPSPAWN_LOGI("Update %{public}s storage dir success", res == 0 ? "sharefs dir" : "no sharefs dir"); + APPSPAWN_LOGI("Update %{public}s storage dir success", checkRes == 0 ? "sharefs dir" : "no sharefs dir"); } -static void MountDirToShared(const AppSpawningCtx *property) +static int MountSharedMapItem(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName, + const char *sandboxPathItem) { - const char rootPath[] = "/mnt/sandbox/"; - const char el1Path[] = "/data/storage/el1/bundle"; - const char lockSuffix[] = "_locked"; - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - const char *bundleName = GetBundleName(property); - if (info == NULL || bundleName == NULL) { - return; + /* /mnt/sandbox///data/storage/el */ + char sandboxPath[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sandboxPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%d/%s/%s", + info->uid / UID_BASE, bundleName, sandboxPathItem); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf sandboxPath failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; } - string sourcePath = "/data/app/el1/bundle/public/" + string(bundleName); - MountDir(property, rootPath, sourcePath.c_str(), el1Path); - if (IsUnlockStatus(info->uid)) { - return; + // Check whether the directory is a shared mount point + std::vector sharedMounts; + GetMountInfo(sharedMounts); + if (IsSandboxPathShared(sharedMounts, sandboxPath)) { + APPSPAWN_LOGI("shared mountpoint is exist"); + return 0; + } + + ret = MakeDirRec(sandboxPath, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", sandboxPath, errno); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; } - UpdateStorageDir(property); + MountArgs arg = {}; + arg.srcPath = sandboxPath; + arg.destPath = sandboxPath; + arg.fsType = nullptr; + arg.mountFlags = MS_BIND | MS_REC; + arg.options = nullptr; + arg.mountSharedFlag = MS_SHARED; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", sandboxPath, ret); + return ret; + } + return 0; +} +static void MountSharedMap(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]); for (int i = 0; i < length; i++) { if (MOUNT_SHARED_MAP[i].permission == nullptr) { - MountDir(property, rootPath, nullptr, MOUNT_SHARED_MAP[i].sandboxPath); + MountSharedMapItem(property, info, bundleName, MOUNT_SHARED_MAP[i].sandboxPath); } else { int index = GetPermissionIndex(nullptr, MOUNT_SHARED_MAP[i].permission); APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index); if (CheckAppPermissionFlagSet(property, static_cast(index))) { - MountDir(property, rootPath, nullptr, MOUNT_SHARED_MAP[i].sandboxPath); + MountSharedMapItem(property, info, bundleName, MOUNT_SHARED_MAP[i].sandboxPath); } } } +} - std::string lockSbxPathStamp = rootPath + to_string(info->uid / UID_BASE) + "/"; +static void MountDirToShared(const AppSpawningCtx *property) +{ + if (property == nullptr) { + return; + } + + AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); + const char *bundleName = GetBundleName(property); + if (info == NULL || bundleName == NULL) { + return; + } + + MountEl1Bundle(property, info, bundleName); + MountStorageUsers(property, info, bundleName); + + if (IsUnlockStatus(info->uid)) { + return; + } + + MountSharedMap(property, info, bundleName); + + std::string lockSbxPathStamp = "/mnt/sandbox" + to_string(info->uid / UID_BASE) + "/"; lockSbxPathStamp += CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : ""; lockSbxPathStamp += bundleName; - lockSbxPathStamp += lockSuffix; - OHOS::AppSpawn::MakeDirRecursive(lockSbxPathStamp.c_str(), OHOS::AppSpawn::FILE_MODE); + lockSbxPathStamp += "_locked"; + int ret = MakeDirRec(lockSbxPathStamp.c_str(), DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", lockSbxPathStamp.c_str(), errno); + } } #endif diff --git a/modules/sandbox/sandbox_utils.h b/modules/sandbox/sandbox_utils.h index 442eba7a28f41bb3170e0815848f29df8b2f931f..6e7199eee66eca5b6ff10449dbe4ff73eecc649c 100755 --- a/modules/sandbox/sandbox_utils.h +++ b/modules/sandbox/sandbox_utils.h @@ -142,4 +142,13 @@ typedef struct { const char *permission; } MountSharedTemplate; +typedef struct { + const char *srcPath; + const char *destPath; + const char *fsType; + unsigned long mountFlags; + const char *options; + mode_t mountSharedFlag; +} MountArgs; + #endif // SANDBOX_UTILS_H