• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "securec.h"
17 #include "appspawn_hook.h"
18 #include "appspawn_manager.h"
19 #include "appspawn_trace.h"
20 #include "appspawn_utils.h"
21 #include "sandbox_core.h"
22 
23 #define USER_ID_SIZE 16
24 #define DIR_MODE 0711
25 
SetAppSandboxProperty(AppSpawnMgr * content,AppSpawningCtx * property)26 int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property)
27 {
28     APPSPAWN_CHECK(property != nullptr, return -1, "Invalid appspawn client");
29     APPSPAWN_CHECK(content != nullptr, return -1, "Invalid appspawn content");
30     // clear g_mountInfo in the child process
31     std::map<std::string, int>* mapPtr = static_cast<std::map<std::string, int>*>(GetEl1BundleMountCount());
32     if (mapPtr == nullptr) {
33         APPSPAWN_LOGE("Get el1 bundle mount count failed");
34         return APPSPAWN_ARG_INVALID;
35     }
36     mapPtr->clear();
37     int ret = 0;
38     // no sandbox
39     if (CheckAppMsgFlagsSet(property, APP_FLAGS_NO_SANDBOX)) {
40         return 0;
41     }
42     if ((content->content.sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID) {
43         ret = getprocpid();
44         if (ret < 0) {
45             return ret;
46         }
47     }
48     uint32_t sandboxNsFlags = CLONE_NEWNS;
49 
50     if (OHOS::AppSpawn::SandboxCore::NeedNetworkIsolated(property)) {
51         sandboxNsFlags |= content->content.sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0;
52     }
53 
54     APPSPAWN_LOGV("SetAppSandboxProperty sandboxNsFlags 0x%{public}x", sandboxNsFlags);
55 
56     StartAppspawnTrace("SetAppSandboxProperty");
57     if (IsNWebSpawnMode(content)) {
58         ret = OHOS::AppSpawn::SandboxCore::SetAppSandboxPropertyNweb(property, sandboxNsFlags);
59     } else {
60         ret = OHOS::AppSpawn::SandboxCore::SetAppSandboxProperty(property, sandboxNsFlags);
61     }
62     FinishAppspawnTrace();
63     // for module test do not create sandbox, use APP_FLAGS_IGNORE_SANDBOX to ignore sandbox result
64     if (CheckAppMsgFlagsSet(property, APP_FLAGS_IGNORE_SANDBOX)) {
65         APPSPAWN_LOGW("Do not care sandbox result %{public}d", ret);
66         return 0;
67     }
68     return ret;
69 }
70 
SpawnMountDirToShared(AppSpawnMgr * content,AppSpawningCtx * property)71 static int SpawnMountDirToShared(AppSpawnMgr *content, AppSpawningCtx *property)
72 {
73 #ifndef APPSPAWN_SANDBOX_NEW
74     if (!IsNWebSpawnMode(content)) {
75         // mount dynamic directory
76         MountToShared(content, property);
77     }
78 #endif
79     return 0;
80 }
81 
UninstallDebugSandbox(AppSpawnMgr * content,AppSpawningCtx * property)82 static int UninstallDebugSandbox(AppSpawnMgr *content, AppSpawningCtx *property)
83 {
84     APPSPAWN_CHECK(property != nullptr && content != nullptr, return -1,
85         "Invalid appspawn client or property");
86     return OHOS::AppSpawn::SandboxCore::UninstallDebugSandbox(content, property);
87 }
88 
InstallDebugSandbox(AppSpawnMgr * content,AppSpawningCtx * property)89 static int InstallDebugSandbox(AppSpawnMgr *content, AppSpawningCtx *property)
90 {
91     APPSPAWN_CHECK(property != nullptr && content != nullptr, return -1,
92         "Invalid appspawn client or property");
93     return OHOS::AppSpawn::SandboxCore::InstallDebugSandbox(content, property);
94 }
95 
UmountDir(const char * rootPath,const char * targetPath,const AppSpawnedProcessInfo * appInfo)96 static void UmountDir(const char *rootPath, const char *targetPath, const AppSpawnedProcessInfo *appInfo)
97 {
98     size_t allPathSize = strlen(rootPath) + USER_ID_SIZE + strlen(appInfo->name) + strlen(targetPath) + 2;
99     char *path = reinterpret_cast<char *>(malloc(sizeof(char) * (allPathSize)));
100     APPSPAWN_CHECK(path != nullptr, return, "Failed to malloc path");
101 
102     int ret = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, appInfo->uid / UID_BASE,
103         appInfo->name, targetPath);
104     APPSPAWN_CHECK(ret > 0 && ((size_t)ret < allPathSize), free(path);
105         return, "Failed to get sandbox path errno %{public}d", errno);
106 
107     ret = umount2(path, MNT_DETACH);
108     if (ret == 0) {
109         APPSPAWN_LOGI("Umount2 sandbox path %{public}s success", path);
110     } else {
111         APPSPAWN_LOGW("Failed to umount2 sandbox path %{public}s errno %{public}d", path, errno);
112     }
113     free(path);
114 }
115 
UmountSandboxPath(const AppSpawnMgr * content,const AppSpawnedProcessInfo * appInfo)116 static int UmountSandboxPath(const AppSpawnMgr *content, const AppSpawnedProcessInfo *appInfo)
117 {
118     APPSPAWN_CHECK(content != nullptr && appInfo != nullptr && appInfo->name != NULL,
119         return -1, "Invalid content or appInfo");
120     if (!IsAppSpawnMode(content)) {
121         return 0;
122     }
123     APPSPAWN_LOGV("UmountSandboxPath name %{public}s pid %{public}d", appInfo->name, appInfo->pid);
124     const char rootPath[] = "/mnt/sandbox/";
125     const char el1Path[] = "/data/storage/el1/bundle";
126 
127     std::string varBundleName = std::string(appInfo->name);
128     if (appInfo->appIndex > 0) {
129         varBundleName = "+clone-" + std::to_string(appInfo->appIndex) + "+" + varBundleName;
130     }
131 
132     uint32_t userId = appInfo->uid / UID_BASE;
133     std::string key = std::to_string(userId) + "-" + varBundleName;
134     std::map<std::string, int> *el1BundleCountMap = static_cast<std::map<std::string, int>*>(GetEl1BundleMountCount());
135     if (el1BundleCountMap == nullptr || el1BundleCountMap->find(key) == el1BundleCountMap->end()) {
136         return 0;
137     }
138     (*el1BundleCountMap)[key]--;
139     if ((*el1BundleCountMap)[key] == 0) {
140         APPSPAWN_LOGV("no app %{public}s use it in userId %{public}u, need umount", appInfo->name, userId);
141         UmountDir(rootPath, el1Path, appInfo);
142         el1BundleCountMap->erase(key);
143     } else {
144         APPSPAWN_LOGV("app %{public}s use it mount times %{public}d in userId %{public}u, not need umount",
145             appInfo->name, (*el1BundleCountMap)[key], userId);
146     }
147     return 0;
148 }
149 
150 #ifndef APPSPAWN_SANDBOX_NEW
MODULE_CONSTRUCTOR(void)151 MODULE_CONSTRUCTOR(void)
152 {
153     APPSPAWN_LOGV("Load sandbox module ...");
154     (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX,
155                              OHOS::AppSpawn::SandboxCommon::LoadAppSandboxConfigCJson);
156     (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_COMMON, SpawnMountDirToShared);
157     (void)AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_SANDBOX, SetAppSandboxProperty);
158     (void)AddAppSpawnHook(STAGE_PARENT_UNINSTALL, HOOK_PRIO_SANDBOX, UninstallDebugSandbox);
159     (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_SANDBOX, InstallDebugSandbox);
160     (void)AddProcessMgrHook(STAGE_SERVER_APP_UMOUNT, HOOK_PRIO_SANDBOX, UmountSandboxPath);
161     (void)AddServerStageHook(STAGE_SERVER_EXIT, HOOK_PRIO_SANDBOX,
162                              OHOS::AppSpawn::SandboxCommon::FreeAppSandboxConfigCJson);
163 }
164 #endif