!1751 fix umount bug

Merge pull request !1751 from nianyuu/master
This commit is contained in:
openharmony_ci 2024-12-02 14:34:16 +00:00 committed by Gitee
commit 12f67dd599
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 55 additions and 2 deletions

View File

@ -60,6 +60,7 @@ typedef enum TagAppSpawnHookStage {
// 应用状态处理
STAGE_SERVER_APP_ADD,
STAGE_SERVER_APP_DIED,
STAGE_SERVER_APP_UMOUNT,
// run before fork
STAGE_PARENT_PRE_FORK = 20,
STAGE_PARENT_POST_FORK = 21,

View File

@ -259,7 +259,7 @@ int ProcessMgrHookExecute(AppSpawnHookStage stage, const AppSpawnContent *conten
{
APPSPAWN_CHECK(content != NULL && appInfo != NULL,
return APPSPAWN_ARG_INVALID, "Invalid hook");
APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED),
APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_UMOUNT),
return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
AppSpawnAppArg arg;
@ -279,7 +279,7 @@ static int ProcessMgrHookRun(const HOOK_INFO *hookInfo, void *executionContext)
int AddProcessMgrHook(AppSpawnHookStage stage, int prio, ProcessChangeHook hook)
{
APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED),
APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_UMOUNT),
return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
HOOK_INFO info;
info.stage = stage;

View File

@ -57,6 +57,8 @@
using namespace std;
using namespace OHOS;
static map<string, int> g_mountInfo;
namespace OHOS {
namespace AppSpawn {
namespace {
@ -1821,6 +1823,8 @@ int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property)
{
APPSPAWN_CHECK(property != nullptr, return -1, "Invalid appspwn client");
APPSPAWN_CHECK(content != nullptr, return -1, "Invalid appspwn content");
// clear g_mountInfo in the child process
g_mountInfo.clear();
int ret = 0;
// no sandbox
if (CheckAppMsgFlagsSet(property, APP_FLAGS_NO_SANDBOX)) {
@ -1899,6 +1903,9 @@ static void MountDir(const AppSpawningCtx *property, const char *rootPath, const
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)]++;
}
if (access(path, F_OK) == 0 && srcPath == nullptr) {
free(path);
@ -2120,6 +2127,49 @@ static int SpawnMountDirToShared(AppSpawnMgr *content, AppSpawningCtx *property)
return 0;
}
static void UmountDir(const char *rootPath, const char *targetPath, const AppSpawnedProcessInfo *appInfo)
{
size_t allPathSize = strlen(rootPath) + USER_ID_SIZE + strlen(appInfo->name) + strlen(targetPath) + 2;
char *path = reinterpret_cast<char *>(malloc(sizeof(char) * (allPathSize)));
APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path");
int ret = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, appInfo->uid / UID_BASE,
appInfo->name, targetPath);
APPSPAWN_CHECK(ret > 0 && ((size_t)ret < allPathSize), free(path);
return, "Failed to get sandbox path errno %{public}d", errno);
ret = umount2(path, MNT_DETACH);
if (ret == 0) {
APPSPAWN_LOGV("Umount2 sandbox path %{public}s success", path);
} else {
APPSPAWN_LOGW("Failed to umount2 sandbox path %{public}s errno %{public}d", path, errno);
}
free(path);
}
static int UmountSandboxPath(const AppSpawnMgr *content, const AppSpawnedProcessInfo *appInfo)
{
APPSPAWN_CHECK(content != NULL && appInfo != NULL && appInfo->name != NULL,
return -1, "Invalid content or appInfo");
APPSPAWN_LOGV("UmountSandboxPath name %{public}s pid %{public}d", appInfo->name, appInfo->pid);
const char rootPath[] = "/mnt/sandbox/";
const char el1Path[] = "/data/storage/el1/bundle";
if (g_mountInfo.find(string(appInfo->name)) == g_mountInfo.end()) {
return 0;
}
g_mountInfo[string(appInfo->name)]--;
if (g_mountInfo[string(appInfo->name)] == 0) {
APPSPAWN_LOGV("no app %{public}s use it, need umount", appInfo->name);
g_mountInfo.erase(string(appInfo->name));
UmountDir(rootPath, el1Path, appInfo);
} else {
APPSPAWN_LOGV("app %{public}s use it mount times %{public}d, not need umount",
appInfo->name, g_mountInfo[string(appInfo->name)]);
}
return 0;
}
#ifndef APPSPAWN_SANDBOX_NEW
MODULE_CONSTRUCTOR(void)
{
@ -2127,5 +2177,6 @@ MODULE_CONSTRUCTOR(void)
(void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX, LoadAppSandboxConfig);
(void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_COMMON, SpawnMountDirToShared);
(void)AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_SANDBOX, SetAppSandboxProperty);
(void)AddProcessMgrHook(STAGE_SERVER_APP_UMOUNT, HOOK_PRIO_SANDBOX, UmountSandboxPath);
}
#endif

View File

@ -155,6 +155,7 @@ static void HandleDiedPid(pid_t pid, uid_t uid, int status)
APPSPAWN_CHECK_ONLY_LOG(appInfo->uid == uid, "Invalid uid %{public}u %{public}u", appInfo->uid, uid);
DumpStatus(appInfo->name, pid, status);
ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
ProcessMgrHookExecute(STAGE_SERVER_APP_UMOUNT, GetAppSpawnContent(), appInfo);
// if current process of death is nwebspawn, restart appspawn
if (strcmp(appInfo->name, NWEBSPAWN_SERVER_NAME) == 0) {