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