1 /*
2 * Copyright (C) 2024 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 "appspawn_sandbox.h"
17 #include "sandbox_adapter.h"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <sched.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <sys/mount.h>
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include "securec.h"
32
33 #include "appspawn_msg.h"
34 #include "appspawn_utils.h"
35 #ifdef WITH_DLP
36 #include "dlp_fuse_fd.h"
37 #endif
38 #include "init_utils.h"
39 #include "parameter.h"
40 #include "appspawn_permission.h"
41
42 #ifdef WITH_SELINUX
43 #ifdef APPSPAWN_MOUNT_TMPSHM
44 #include "policycoreutils.h"
45 #endif // APPSPAWN_MOUNT_TMPSHM
46 #endif // WITH_SELINUX
47
48 #define USER_ID_SIZE 16
49 #define DIR_MODE 0711
50 #define DEV_SHM_DIR "/dev/shm/"
51
SetMountPathOperation(uint32_t *operation, uint32_t index)52 static inline void SetMountPathOperation(uint32_t *operation, uint32_t index)
53 {
54 *operation |= (1 << index);
55 }
56
CheckSpawningMsgFlagSet(const SandboxContext *context, uint32_t index)57 static inline bool CheckSpawningMsgFlagSet(const SandboxContext *context, uint32_t index)
58 {
59 APPSPAWN_CHECK(context->message != NULL, return false, "Invalid property for type %{public}u", TLV_MSG_FLAGS);
60 return CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, index);
61 }
62
CheckSpawningPermissionFlagSet(const SandboxContext *context, uint32_t index)63 APPSPAWN_STATIC inline bool CheckSpawningPermissionFlagSet(const SandboxContext *context, uint32_t index)
64 {
65 APPSPAWN_CHECK(context != NULL && context->message != NULL,
66 return NULL, "Invalid property for type %{public}u", TLV_PERMISSION);
67 return CheckAppSpawnMsgFlag(context->message, TLV_PERMISSION, index);
68 }
69
CheckDirRecursive(const char *path)70 APPSPAWN_STATIC bool CheckDirRecursive(const char *path)
71 {
72 char buffer[PATH_MAX] = {0};
73 const char slash = '/';
74 const char *p = path;
75 char *curPos = strchr(path, slash);
76 while (curPos != NULL) {
77 int len = curPos - p;
78 p = curPos + 1;
79 if (len == 0) {
80 curPos = strchr(p, slash);
81 continue;
82 }
83 int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1);
84 APPSPAWN_CHECK(ret == 0, return false, "Failed to copy path");
85 ret = access(buffer, F_OK);
86 APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
87 curPos = strchr(p, slash);
88 }
89 int ret = access(path, F_OK);
90 APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
91 return true;
92 }
93
SandboxMountPath(const MountArg *arg)94 int SandboxMountPath(const MountArg *arg)
95 {
96 APPSPAWN_CHECK(arg != NULL && arg->originPath != NULL && arg->destinationPath != NULL,
97 return APPSPAWN_ARG_INVALID, "Invalid arg ");
98
99 APPSPAWN_LOGV("Bind mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s",
100 arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
101 (uint32_t)arg->mountFlags, arg->options, arg->originPath, arg->destinationPath);
102
103 int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options);
104 if (ret != 0) {
105 if (arg->originPath != NULL && strstr(arg->originPath, "/data/app/el2/") != NULL) {
106 CheckDirRecursive(arg->originPath);
107 }
108 APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
109 errno, arg->originPath, arg->destinationPath);
110 return errno;
111 }
112 ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL);
113 if (ret != 0) {
114 APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
115 errno, arg->originPath, arg->destinationPath);
116 return errno;
117 }
118 return 0;
119 }
120
BuildRootPath(char *buffer, uint32_t bufferLen, const AppSpawnSandboxCfg *sandbox, uid_t uid)121 static int BuildRootPath(char *buffer, uint32_t bufferLen, const AppSpawnSandboxCfg *sandbox, uid_t uid)
122 {
123 int ret = 0;
124 int len = 0;
125 uint32_t currLen = 0;
126 uint32_t userIdLen = sizeof(PARAMETER_USER_ID) - 1;
127 uint32_t rootLen = strlen(sandbox->rootPath);
128 char *rootPath = strstr(sandbox->rootPath, PARAMETER_USER_ID);
129 if (rootPath == NULL) {
130 len = sprintf_s(buffer, bufferLen, "%s/%d", sandbox->rootPath, uid);
131 } else {
132 ret = memcpy_s(buffer, bufferLen, sandbox->rootPath, rootPath - sandbox->rootPath);
133 APPSPAWN_CHECK(ret == 0, return ret, "Failed to copy root path %{public}s", sandbox->rootPath);
134 currLen = rootPath - sandbox->rootPath;
135
136 if (rootLen > (currLen + userIdLen)) {
137 len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d%s",
138 uid, sandbox->rootPath + currLen + userIdLen);
139 } else {
140 len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d", uid);
141 }
142 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < (bufferLen - currLen)), return ret,
143 "Failed to format root path %{public}s", sandbox->rootPath);
144 currLen += (uint32_t)len;
145 }
146 buffer[currLen] = '\0';
147 return 0;
148 }
149
150 static SandboxContext *g_sandboxContext = NULL;
151
GetSandboxContext(void)152 SandboxContext *GetSandboxContext(void)
153 {
154 if (g_sandboxContext == NULL) {
155 SandboxContext *context = calloc(1, MAX_SANDBOX_BUFFER * MAX_BUFFER + sizeof(SandboxContext));
156 APPSPAWN_CHECK(context != NULL, return NULL, "Failed to get mem");
157 char *buffer = (char *)(context + 1);
158 for (int i = 0; i < MAX_BUFFER; i++) {
159 context->buffer[i].bufferLen = MAX_SANDBOX_BUFFER;
160 context->buffer[i].current = 0;
161 context->buffer[i].buffer = buffer + MAX_SANDBOX_BUFFER * i;
162 }
163 context->bundleName = NULL;
164 context->bundleHasWps = 0;
165 context->dlpBundle = 0;
166 context->appFullMountEnable = 0;
167 context->sandboxSwitch = 1;
168 context->sandboxShared = false;
169 context->message = NULL;
170 context->rootPath = NULL;
171 g_sandboxContext = context;
172 }
173 return g_sandboxContext;
174 }
175
DeleteSandboxContext(SandboxContext *context)176 void DeleteSandboxContext(SandboxContext *context)
177 {
178 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return);
179 if (context->rootPath) {
180 free(context->rootPath);
181 context->rootPath = NULL;
182 }
183 if (context == g_sandboxContext) {
184 g_sandboxContext = NULL;
185 }
186 free(context);
187 }
188
InitSandboxContext(SandboxContext *context, const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)189 static int InitSandboxContext(SandboxContext *context,
190 const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
191 {
192 AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppProperty(property, TLV_MSG_FLAGS);
193 APPSPAWN_CHECK(msgFlags != NULL, return APPSPAWN_TLV_NONE,
194 "No msg flags in msg %{public}s", GetProcessName(property));
195 context->nwebspawn = nwebspawn;
196 context->bundleName = GetBundleName(property);
197 context->bundleHasWps = strstr(context->bundleName, "wps") != NULL;
198 context->dlpBundle = strcmp(GetProcessName(property), "com.ohos.dlpmanager") == 0;
199 context->appFullMountEnable = sandbox->appFullMountEnable;
200
201 context->sandboxSwitch = 1;
202 context->sandboxShared = false;
203 SandboxPackageNameNode *packageNode = (SandboxPackageNameNode *)GetSandboxSection(
204 &sandbox->packageNameQueue, context->bundleName);
205 if (packageNode) {
206 context->sandboxShared = packageNode->section.sandboxShared;
207 }
208 context->message = property->message;
209
210 context->sandboxNsFlags = CLONE_NEWNS;
211 if ((CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX) && !IsDeveloperModeOpen()) ||
212 CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_NETWORK)) {
213 context->sandboxNsFlags |= sandbox->sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0;
214 }
215
216 ListNode *node = sandbox->permissionQueue.front.next;
217 while (node != &sandbox->permissionQueue.front) {
218 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
219 if (permissionNode == NULL) {
220 return -1;
221 }
222 context->sandboxShared = permissionNode->section.sandboxShared;
223 node = node->next;
224 }
225
226 // root path
227 const char *rootPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandbox->rootPath, NULL, NULL);
228 if (rootPath) {
229 context->rootPath = strdup(rootPath);
230 }
231 if (context->rootPath == NULL) {
232 DeleteSandboxContext(context);
233 return -1;
234 }
235 return 0;
236 }
237
GetVarExtraData(const SandboxContext *context, const SandboxSection *section)238 static VarExtraData *GetVarExtraData(const SandboxContext *context, const SandboxSection *section)
239 {
240 static VarExtraData extraData;
241 (void)memset_s(&extraData, sizeof(extraData), 0, sizeof(extraData));
242 extraData.sandboxTag = GetSectionType(section);
243 if (GetSectionType(section) == SANDBOX_TAG_NAME_GROUP) {
244 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section;
245 extraData.data.depNode = groupNode->depNode;
246 }
247 return &extraData;
248 }
249
GetMountArgs(const SandboxContext *context, const PathMountNode *sandboxNode, uint32_t operation, MountArg *args)250 static uint32_t GetMountArgs(const SandboxContext *context,
251 const PathMountNode *sandboxNode, uint32_t operation, MountArg *args)
252 {
253 uint32_t category = sandboxNode->category;
254 const MountArgTemplate *tmp = GetMountArgTemplate(category);
255 if (tmp == 0) {
256 return MOUNT_TMP_DEFAULT;
257 }
258 args->fsType = tmp->fsType;
259 args->options = tmp->options;
260 args->mountFlags = tmp->mountFlags;
261 args->mountSharedFlag = (sandboxNode->mountSharedFlag) ? MS_SHARED : tmp->mountSharedFlag;
262 return category;
263 }
264
CheckSandboxMountNode(const SandboxContext *context, const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)265 APPSPAWN_STATIC int CheckSandboxMountNode(const SandboxContext *context,
266 const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)
267 {
268 if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
269 APPSPAWN_LOGW("Invalid mount config section %{public}s", section->name);
270 return 0;
271 }
272 // special handle wps and don't use /data/app/xxx/<Package> config
273 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) { // flags-point
274 if (context->bundleHasWps &&
275 (strstr(sandboxNode->source, "/data/app") != NULL) &&
276 (strstr(sandboxNode->source, "/base") != NULL || strstr(sandboxNode->source, "/database") != NULL) &&
277 (strstr(sandboxNode->source, PARAMETER_PACKAGE_NAME) != NULL)) {
278 APPSPAWN_LOGW("Invalid mount source %{public}s section %{public}s",
279 sandboxNode->source, section->name);
280 return 0;
281 }
282 }
283 // check apl
284 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
285 if (msgDomainInfo != NULL && sandboxNode->appAplName != NULL) {
286 if (!strcmp(sandboxNode->appAplName, msgDomainInfo->apl)) {
287 APPSPAWN_LOGW("Invalid mount app apl %{public}s %{public}s section %{public}s",
288 sandboxNode->appAplName, msgDomainInfo->apl, section->name);
289 return 0;
290 }
291 }
292 return 1;
293 }
294
SandboxMountFusePath(const SandboxContext *context, const MountArg *args)295 static int32_t SandboxMountFusePath(const SandboxContext *context, const MountArg *args)
296 {
297 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
298 APPSPAWN_CHECK(info != NULL, return APPSPAWN_TLV_NONE,
299 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
300
301 // umount fuse path, make sure that sandbox path is not a mount point
302 umount2(args->destinationPath, MNT_DETACH);
303
304 int fd = open("/dev/fuse", O_RDWR);
305 APPSPAWN_CHECK(fd != -1, return -EINVAL,
306 "open /dev/fuse failed, errno: %{public}d sandbox path %{public}s", errno, args->destinationPath);
307
308 char options[OPTIONS_MAX_LEN] = {0};
309 int ret = sprintf_s(options, sizeof(options), "fd=%d,"
310 "rootmode=40000,user_id=%d,group_id=%d,allow_other,"
311 "context=\"u:object_r:dlp_fuse_file:s0\","
312 "fscontext=u:object_r:dlp_fuse_file:s0", fd, info->uid, info->gid);
313 APPSPAWN_CHECK(ret > 0, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "sprintf options fail");
314
315 APPSPAWN_LOGV("Bind mount dlp fuse \n "
316 "mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s",
317 args->fsType, args->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
318 (uint32_t)args->mountFlags, options, args->originPath, args->destinationPath);
319
320 // To make sure destinationPath exist
321 CreateSandboxDir(args->destinationPath, FILE_MODE);
322 MountArg mountArg = {args->originPath, args->destinationPath, args->fsType, args->mountFlags, options, MS_SHARED};
323 ret = SandboxMountPath(&mountArg);
324 if (ret != 0) {
325 close(fd);
326 return -1;
327 }
328 /* set DLP_FUSE_FD */
329 #ifdef WITH_DLP
330 SetDlpFuseFd(fd);
331 #endif
332 return 0;
333 }
334
CheckAndCreateSandboxFile(const char *file)335 APPSPAWN_STATIC void CheckAndCreateSandboxFile(const char *file)
336 {
337 if (access(file, F_OK) == 0) {
338 APPSPAWN_LOGI("file %{public}s already exist", file);
339 return;
340 }
341 MakeDirRec(file, FILE_MODE, 0);
342 int fd = open(file, O_CREAT, FILE_MODE);
343 if (fd < 0) {
344 APPSPAWN_LOGW("failed create %{public}s, err=%{public}d", file, errno);
345 } else {
346 close(fd);
347 }
348 return;
349 }
350
CreateDemandSrc(const SandboxContext *context, const PathMountNode *sandboxNode, const MountArg *args)351 APPSPAWN_STATIC void CreateDemandSrc(const SandboxContext *context, const PathMountNode *sandboxNode,
352 const MountArg *args)
353 {
354 if (!sandboxNode->createDemand) {
355 return;
356 }
357 CheckAndCreateSandboxFile(args->originPath);
358 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
359 APPSPAWN_CHECK(info != NULL, return,
360 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
361
362 // chmod
363 uid_t uid = sandboxNode->demandInfo->uid != INVALID_UID ? sandboxNode->demandInfo->uid : info->uid;
364 gid_t gid = sandboxNode->demandInfo->gid != INVALID_UID ? sandboxNode->demandInfo->gid : info->gid;
365 int ret = chown(args->originPath, uid, gid);
366 if (ret != 0) {
367 APPSPAWN_LOGE("Failed to chown %{public}s errno: %{public}d", args->originPath, errno);
368 }
369 if (sandboxNode->demandInfo->mode != INVALID_UID) {
370 ret = chmod(args->originPath, sandboxNode->demandInfo->mode);
371 if (ret != 0) {
372 APPSPAWN_LOGE("Failed to chmod %{public}s errno: %{public}d", args->originPath, errno);
373 }
374 }
375 }
376
GetRealSrcPath(const SandboxContext *context, const char *source, VarExtraData *extraData)377 APPSPAWN_STATIC const char *GetRealSrcPath(const SandboxContext *context, const char *source, VarExtraData *extraData)
378 {
379 bool hasPackageName = strstr(source, "<variablePackageName>") != NULL;
380 extraData->variablePackageName = (char *)context->bundleName;
381 const char *originPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, source, NULL, extraData);
382 if (originPath == NULL) {
383 return NULL;
384 }
385 if (hasPackageName && CheckSpawningMsgFlagSet(context, APP_FLAGS_ATOMIC_SERVICE)) {
386 MakeAtomicServiceDir(context, originPath);
387 }
388 return originPath;
389 }
390
391 // 设置挂载参数options
SetMountArgsOption(const SandboxContext *context, uint32_t category, uint32_t operation, MountArg *args)392 static int32_t SetMountArgsOption(const SandboxContext *context, uint32_t category, uint32_t operation, MountArg *args)
393 {
394 if ((category != MOUNT_TMP_DAC_OVERRIDE) && (category != MOUNT_TMP_DAC_OVERRIDE_DELETE)) {
395 return 0;
396 }
397
398 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
399 if (info == NULL) {
400 APPSPAWN_LOGE("Get msg dac info failed");
401 return APPSPAWN_ARG_INVALID;
402 }
403
404 char options[OPTIONS_MAX_LEN] = {0};
405 int len = sprintf_s(options, OPTIONS_MAX_LEN, "%s%s%d", args->options, SHAREFS_OPTION_USER, info->uid / UID_BASE);
406 if (len <= 0) {
407 APPSPAWN_LOGE("sprintf_s failed");
408 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
409 }
410 args->options = options;
411 return 0;
412 }
413
414 // 根据沙盒配置文件中挂载类别进行挂载挂载
DoSandboxMountByCategory(const SandboxContext *context, const PathMountNode *sandboxNode, MountArg *args, uint32_t operation)415 static int DoSandboxMountByCategory(const SandboxContext *context, const PathMountNode *sandboxNode,
416 MountArg *args, uint32_t operation)
417 {
418 int ret = 0;
419 uint32_t category = GetMountArgs(context, sandboxNode, operation, args);
420 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_PERMISSION) ||
421 CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) {
422 ret = SetMountArgsOption(context, category, operation, args);
423 if (ret != 0) {
424 APPSPAWN_LOGE("set mount arg option fail. ret: %{public}d", ret);
425 return ret;
426 }
427 }
428 if (category == MOUNT_TMP_DLP_FUSE || category == MOUNT_TMP_FUSE) {
429 ret = SandboxMountFusePath(context, args);
430 } else {
431 ret = SandboxMountPath(args);
432 }
433 return ret;
434 }
435
DoSandboxPathNodeMount(const SandboxContext *context, const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)436 static int DoSandboxPathNodeMount(const SandboxContext *context,
437 const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)
438 {
439 if (CheckSandboxMountNode(context, section, sandboxNode, operation) == 0) {
440 return 0;
441 }
442
443 MountArg args = {};
444 uint32_t category = GetMountArgs(context, sandboxNode, operation, &args);
445 VarExtraData *extraData = GetVarExtraData(context, section);
446 args.originPath = GetRealSrcPath(context, sandboxNode->source, extraData);
447 // dest
448 extraData->operation = operation; // only destinationPath
449 // 对name group的节点,需要对目的沙盒进行特殊处理,不能带root-dir
450 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_NAME_GROUP) &&
451 CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_ONLY_SANDBOX)) {
452 args.destinationPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, sandboxNode->target, NULL, extraData);
453 } else {
454 args.destinationPath = GetSandboxRealVar(context,
455 BUFFER_FOR_TARGET, sandboxNode->target, context->rootPath, extraData);
456 }
457 APPSPAWN_CHECK(args.originPath != NULL && args.destinationPath != NULL,
458 return APPSPAWN_ARG_INVALID, "Invalid path %{public}s %{public}s", args.originPath, args.destinationPath);
459
460 if (sandboxNode->sandboxNode.type == SANDBOX_TAG_MOUNT_FILE) {
461 CheckAndCreateSandboxFile(args.destinationPath);
462 } else {
463 if (access(args.destinationPath, F_OK) != 0) {
464 CreateSandboxDir(args.destinationPath, FILE_MODE);
465 }
466 }
467 CreateDemandSrc(context, sandboxNode, &args);
468
469 if (CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_UNMOUNT)) { // unmount this deps
470 APPSPAWN_LOGV("umount2 %{public}s", args.destinationPath);
471 umount2(args.destinationPath, MNT_DETACH);
472 }
473 int ret = 0;
474 ret = DoSandboxMountByCategory(context, sandboxNode, &args, operation);
475 if (ret != 0 && sandboxNode->checkErrorFlag) {
476 APPSPAWN_LOGE("Failed to mount config, section: %{public}s result: %{public}d category: %{public}d",
477 section->name, ret, category);
478 return ret;
479 }
480 return 0;
481 }
482
DoSandboxPathSymLink(const SandboxContext *context, const SandboxSection *section, const SymbolLinkNode *sandboxNode)483 static int DoSandboxPathSymLink(const SandboxContext *context,
484 const SandboxSection *section, const SymbolLinkNode *sandboxNode)
485 {
486 // Check the validity of the symlink configuration
487 if (sandboxNode->linkName == NULL || sandboxNode->target == NULL) {
488 APPSPAWN_LOGW("Invalid symlink config, section %{public}s", section->name);
489 return 0;
490 }
491
492 const char *target = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandboxNode->target, NULL, NULL);
493 const char *linkName = GetSandboxRealVar(context, BUFFER_FOR_TARGET,
494 sandboxNode->linkName, context->rootPath, NULL);
495 APPSPAWN_LOGV("symlink from %{public}s to %{public}s", target, linkName);
496 if (access(linkName, F_OK) == 0) {
497 if (rmdir(linkName) != 0) {
498 APPSPAWN_LOGW("linkName %{public}s already exist and rmdir failed, errno %{public}d", linkName, errno);
499 }
500 }
501 int ret = symlink(target, linkName);
502 if (ret && errno != EEXIST) {
503 if (sandboxNode->checkErrorFlag) {
504 APPSPAWN_LOGE("symlink failed, errno: %{public}d link info %{public}s %{public}s",
505 errno, sandboxNode->target, sandboxNode->linkName);
506 return errno;
507 }
508 APPSPAWN_LOGV("symlink failed, errno: %{public}d link info %{public}s %{public}s",
509 errno, sandboxNode->target, sandboxNode->linkName);
510 }
511 return 0;
512 }
513
DoSandboxNodeMount(const SandboxContext *context, const SandboxSection *section, uint32_t operation)514 static int DoSandboxNodeMount(const SandboxContext *context, const SandboxSection *section, uint32_t operation)
515 {
516 ListNode *node = section->front.next;
517 while (node != §ion->front) {
518 int ret = 0;
519 SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
520 switch (sandboxNode->type) {
521 case SANDBOX_TAG_MOUNT_PATH:
522 case SANDBOX_TAG_MOUNT_FILE:
523 ret = DoSandboxPathNodeMount(context, section, (PathMountNode *)sandboxNode, operation);
524 break;
525 case SANDBOX_TAG_SYMLINK:
526 if (!CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_SYMLINK)) {
527 break;
528 }
529 ret = DoSandboxPathSymLink(context, section, (SymbolLinkNode *)sandboxNode);
530 break;
531 default:
532 break;
533 }
534 if (ret != 0) {
535 return ret;
536 }
537 node = node->next;
538 }
539 return 0;
540 }
541
IsUnlockStatus(uint32_t uid, const char *bundleName, size_t bundleNameLen)542 static bool IsUnlockStatus(uint32_t uid, const char *bundleName, size_t bundleNameLen)
543 {
544 const int userIdBase = UID_BASE;
545 uid = uid / userIdBase;
546 if (uid == 0) {
547 return true;
548 }
549
550 const char rootPath[] = "/data/app/el2/";
551 const char basePath[] = "/base/";
552 size_t allPathSize = strlen(rootPath) + strlen(basePath) + 1 + USER_ID_SIZE + bundleNameLen;
553 char *path = (char *)malloc(sizeof(char) * allPathSize);
554 APPSPAWN_CHECK(path != NULL, return true, "Failed to malloc path");
555 int len = sprintf_s(path, allPathSize, "%s%u%s%s", rootPath, uid, basePath, bundleName);
556 APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); return true, "Failed to get base path");
557
558 if (access(path, F_OK) == 0) {
559 APPSPAWN_LOGI("this is unlock status");
560 free(path);
561 return true;
562 }
563 free(path);
564 APPSPAWN_LOGI("this is lock status");
565 return false;
566 }
567
MountDir(AppSpawnMsgDacInfo *info, const char *bundleName, const char *rootPath, const char *targetPath)568 static void MountDir(AppSpawnMsgDacInfo *info, const char *bundleName, const char *rootPath, const char *targetPath)
569 {
570 if (info == NULL || bundleName == NULL || rootPath == NULL || targetPath == NULL) {
571 return;
572 }
573
574 const int userIdBase = UID_BASE;
575 size_t allPathSize = strlen(rootPath) + strlen(targetPath) + strlen(bundleName) + 2;
576 allPathSize += USER_ID_SIZE;
577 char *path = (char *)malloc(sizeof(char) * (allPathSize));
578 APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path");
579 int len = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, info->uid / userIdBase, bundleName, targetPath);
580 APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path);
581 return, "Failed to get sandbox path");
582
583 if (access(path, F_OK) == 0) {
584 free(path);
585 return;
586 }
587
588 MakeDirRec(path, DIR_MODE, 1);
589 if (mount(path, path, NULL, MS_BIND | MS_REC, NULL) != 0) {
590 APPSPAWN_LOGI("bind mount %{public}s failed, error %{public}d", path, errno);
591 free(path);
592 return;
593 }
594 if (mount(NULL, path, NULL, MS_SHARED, NULL) != 0) {
595 APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno);
596 free(path);
597 return;
598 }
599 APPSPAWN_LOGI("mount path %{public}s to shared success", path);
600 free(path);
601 return;
602 }
603
604 static const MountSharedTemplate MOUNT_SHARED_MAP[] = {
605 {"/data/storage/el2", NULL},
606 {"/data/storage/el3", NULL},
607 {"/data/storage/el4", NULL},
608 {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"},
609 {"/storage/Users", "ohos.permission.FILE_ACCESS_MANAGER"},
610 };
611
MountDirToShared(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)612 static void MountDirToShared(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
613 {
614 const char rootPath[] = "/mnt/sandbox/";
615 const char nwebPath[] = "/mnt/nweb";
616 const char nwebTmpPath[] = "/mnt/nweb/tmp";
617 const char appRootName[] = "app-root";
618 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
619 if (info == NULL || context->bundleName == NULL) {
620 return;
621 }
622 MountDir(info, appRootName, rootPath, nwebPath);
623 MountDir(info, appRootName, rootPath, nwebTmpPath);
624
625 if (IsUnlockStatus(info->uid, context->bundleName, strlen(context->bundleName))) {
626 return;
627 }
628
629 int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]);
630 for (int i = 0; i < length; i++) {
631 if (MOUNT_SHARED_MAP[i].permission == NULL) {
632 MountDir(info, context->bundleName, rootPath, MOUNT_SHARED_MAP[i].sandboxPath);
633 } else {
634 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, MOUNT_SHARED_MAP[i].permission);
635 APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index);
636 if (CheckSpawningPermissionFlagSet(context, index)) {
637 MountDir(info, context->bundleName, rootPath, MOUNT_SHARED_MAP[i].sandboxPath);
638 }
639 }
640 }
641 char lockSbxPathStamp[MAX_SANDBOX_BUFFER] = { 0 };
642 int ret = 0;
643 if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX_TYPE) != 0) {
644 ret = snprintf_s(lockSbxPathStamp, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%d/isolated/%s_locked",
645 rootPath, info->uid / UID_BASE, context->bundleName);
646 } else {
647 ret = snprintf_s(lockSbxPathStamp, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%d/%s_locked",
648 rootPath, info->uid / UID_BASE, context->bundleName);
649 }
650 if (ret <= 0) {
651 APPSPAWN_LOGE("snprintf_s lock sandbox path stamp failed");
652 return;
653 }
654
655 CreateSandboxDir(lockSbxPathStamp, FILE_MODE);
656 }
657
UpdateMountPathDepsPath(const SandboxContext *context, SandboxNameGroupNode *groupNode)658 static int UpdateMountPathDepsPath(const SandboxContext *context, SandboxNameGroupNode *groupNode)
659 {
660 PathMountNode *depNode = groupNode->depNode;
661 const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, depNode->source, NULL, NULL);
662 const char *sandboxPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, depNode->target, NULL, NULL);
663 if (srcPath == NULL || sandboxPath == NULL) {
664 APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name);
665 return APPSPAWN_SANDBOX_MOUNT_FAIL;
666 }
667 free(depNode->source);
668 depNode->source = strdup(srcPath);
669 free(depNode->target);
670 depNode->target = strdup(sandboxPath);
671 if (depNode->source == NULL || depNode->target == NULL) {
672 APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name);
673 if (depNode->source) {
674 free(depNode->source);
675 depNode->source = NULL;
676 }
677 if (depNode->target) {
678 free(depNode->target);
679 depNode->target = NULL;
680 }
681 return APPSPAWN_SANDBOX_MOUNT_FAIL;
682 }
683 return 0;
684 }
685
CheckAndCreateDepPath(const SandboxContext *context, const SandboxNameGroupNode *groupNode)686 static bool CheckAndCreateDepPath(const SandboxContext *context, const SandboxNameGroupNode *groupNode)
687 {
688 PathMountNode *mountNode = (PathMountNode *)GetFirstSandboxMountNode(&groupNode->section);
689 if (mountNode == NULL) {
690 return false;
691 }
692
693 // 这里可能需要替换deps的数据
694 VarExtraData *extraData = GetVarExtraData(context, &groupNode->section);
695 const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, mountNode->source, NULL, extraData);
696 if (srcPath == NULL) {
697 return false;
698 }
699 if (access(srcPath, F_OK) == 0) {
700 APPSPAWN_LOGV("Src path %{public}s exist, do not mount", srcPath);
701 return true;
702 }
703 // 不存在,则创建并挂载
704 APPSPAWN_LOGV("Mount depended source: %{public}s", groupNode->depNode->source);
705 CreateSandboxDir(groupNode->depNode->source, FILE_MODE);
706 return false;
707 }
708
MountSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox, const SandboxSection *section, uint32_t op)709 static int MountSandboxConfig(const SandboxContext *context,
710 const AppSpawnSandboxCfg *sandbox, const SandboxSection *section, uint32_t op)
711 {
712 uint32_t operation = (op != MOUNT_PATH_OP_NONE) ? op : 0;
713 SetMountPathOperation(&operation, section->sandboxNode.type);
714 // if sandbox switch is off, don't do symlink work again
715 if (context->sandboxSwitch && sandbox->topSandboxSwitch) {
716 SetMountPathOperation(&operation, MOUNT_PATH_OP_SYMLINK);
717 }
718
719 int ret = DoSandboxNodeMount(context, section, operation);
720 APPSPAWN_CHECK(ret == 0, return ret,
721 "Mount sandbox config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
722
723 if (section->nameGroups == NULL) {
724 return 0;
725 }
726
727 for (uint32_t i = 0; i < section->number; i++) {
728 if (section->nameGroups[i] == NULL) {
729 continue;
730 }
731 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
732 if (groupNode->depMounted != 1) {
733 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX);
734 }
735 SetMountPathOperation(&operation, SANDBOX_TAG_NAME_GROUP);
736 ret = DoSandboxNodeMount(context, &groupNode->section, operation);
737 APPSPAWN_CHECK(ret == 0, return ret,
738 "Mount name group %{public}s fail result: %{public}d", groupNode->section.name, ret);
739 }
740 return 0;
741 }
742
SetExpandSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)743 static int SetExpandSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
744 {
745 int ret = ProcessExpandAppSandboxConfig(context, sandbox, "HspList");
746 APPSPAWN_CHECK(ret == 0, return ret,
747 "Set HspList config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
748 ret = ProcessExpandAppSandboxConfig(context, sandbox, "DataGroup");
749 APPSPAWN_CHECK(ret == 0, return ret,
750 "Set DataGroup config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
751
752 bool mountDestBundlePath = false;
753 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
754 if (msgDomainInfo != NULL) {
755 mountDestBundlePath = (strcmp(msgDomainInfo->apl, APL_SYSTEM_BASIC) == 0) ||
756 (strcmp(msgDomainInfo->apl, APL_SYSTEM_CORE) == 0);
757 }
758 if (mountDestBundlePath || (CheckSpawningMsgFlagSet(context, APP_FLAGS_ACCESS_BUNDLE_DIR) != 0)) {
759 // need permission check for system app here
760 const char *destBundlesPath = GetSandboxRealVar(context,
761 BUFFER_FOR_TARGET, "/data/bundles/", context->rootPath, NULL);
762 CreateSandboxDir(destBundlesPath, FILE_MODE);
763 MountArg mountArg = {PHYSICAL_APP_INSTALL_PATH, destBundlesPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE};
764 ret = SandboxMountPath(&mountArg);
765 APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
766 }
767 return 0;
768 }
769
SetSandboxPackageNameConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)770 static int SetSandboxPackageNameConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
771 {
772 SandboxPackageNameNode *sandboxNode =
773 (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName);
774 if (sandboxNode != NULL) {
775 int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE);
776 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
777 }
778 return 0;
779 }
780
SetSandboxSpawnFlagsConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)781 static int SetSandboxSpawnFlagsConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
782 {
783 ListNode *node = sandbox->spawnFlagsQueue.front.next;
784 while (node != &sandbox->spawnFlagsQueue.front) {
785 SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node);
786 // match flags point
787 if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) {
788 node = node->next;
789 continue;
790 }
791
792 int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE);
793 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
794 node = node->next;
795 }
796 return 0;
797 }
798
SetSandboxPermissionConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)799 static int SetSandboxPermissionConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
800 {
801 APPSPAWN_LOGV("Set permission config");
802 ListNode *node = sandbox->permissionQueue.front.next;
803 while (node != &sandbox->permissionQueue.front) {
804 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
805 if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) {
806 node = node->next;
807 continue;
808 }
809
810 APPSPAWN_LOGV("SetSandboxPermissionConfig permission %{public}d %{public}s",
811 permissionNode->permissionIndex, permissionNode->section.name);
812 int ret = MountSandboxConfig(context, sandbox, &permissionNode->section, MOUNT_PATH_OP_NONE);
813 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
814 node = node->next;
815 }
816 return 0;
817 }
818
SetOverlayAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)819 static int SetOverlayAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
820 {
821 if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_OVERLAY)) {
822 return 0;
823 }
824 int ret = ProcessExpandAppSandboxConfig(context, sandbox, "Overlay");
825 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
826 return 0;
827 }
828
SetBundleResourceSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)829 static int SetBundleResourceSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
830 {
831 if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_BUNDLE_RESOURCES)) {
832 return 0;
833 }
834 const char *destPath = GetSandboxRealVar(context,
835 BUFFER_FOR_TARGET, "/data/storage/bundle_resources/", context->rootPath, NULL);
836 CreateSandboxDir(destPath, FILE_MODE);
837 MountArg mountArg = {
838 "/data/service/el1/public/bms/bundle_resources/", destPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE
839 };
840 int ret = SandboxMountPath(&mountArg);
841 return ret;
842 }
843
ChangeCurrentDir(const SandboxContext *context)844 static int32_t ChangeCurrentDir(const SandboxContext *context)
845 {
846 int32_t ret = 0;
847 ret = chdir(context->rootPath);
848 APPSPAWN_CHECK(ret == 0, return ret,
849 "chdir failed, app: %{public}s, path: %{public}s errno: %{public}d",
850 context->bundleName, context->rootPath, errno);
851
852 if (context->sandboxShared) {
853 ret = chroot(context->rootPath);
854 APPSPAWN_CHECK(ret == 0, return ret,
855 "chroot failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
856 return ret;
857 }
858 ret = syscall(SYS_pivot_root, context->rootPath, context->rootPath);
859 APPSPAWN_CHECK(ret == 0, return ret,
860 "pivot root failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
861 ret = umount2(".", MNT_DETACH);
862 APPSPAWN_CHECK(ret == 0, return ret,
863 "MNT_DETACH failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
864 APPSPAWN_LOGV("ChangeCurrentDir %{public}s ", context->rootPath);
865 return ret;
866 }
867
SandboxRootFolderCreateNoShare( const SandboxContext *context, const AppSpawnSandboxCfg *sandbox, bool remountProc)868 static int SandboxRootFolderCreateNoShare(
869 const SandboxContext *context, const AppSpawnSandboxCfg *sandbox, bool remountProc)
870 {
871 APPSPAWN_LOGV("SandboxRootFolderCreateNoShare %{public}s ", context->rootPath);
872 int ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
873 APPSPAWN_CHECK(ret == 0, return ret,
874 "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
875
876 MountArg arg = {context->rootPath, context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL, MS_SLAVE};
877 ret = SandboxMountPath(&arg);
878 APPSPAWN_CHECK(ret == 0, return ret,
879 "mount path failed, app: %{public}s errno: %{public}d", context->rootPath, ret);
880 return ret;
881 }
882
SandboxRootFolderCreate(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)883 static int SandboxRootFolderCreate(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
884 {
885 APPSPAWN_LOGV("topSandboxSwitch %{public}d sandboxSwitch: %{public}d sandboxShared: %{public}d \n",
886 sandbox->topSandboxSwitch, context->sandboxSwitch, context->sandboxShared);
887
888 int ret = 0;
889 if (sandbox->topSandboxSwitch == 0 || context->sandboxSwitch == 0) {
890 ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
891 APPSPAWN_CHECK(ret == 0, return ret,
892 "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
893 // bind mount "/" to /mnt/sandbox/<packageName> path
894 // rootfs: to do more resources bind mount here to get more strict resources constraints
895 ret = mount("/", context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL);
896 APPSPAWN_CHECK(ret == 0, return ret,
897 "mount bind / failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
898 } else if (!context->sandboxShared) {
899 bool remountProc = !context->nwebspawn && ((sandbox->sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID);
900 ret = SandboxRootFolderCreateNoShare(context, sandbox, remountProc);
901 }
902 return ret;
903 }
904
IsSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, const char *rootPath)905 static bool IsSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, const char *rootPath)
906 {
907 char path[PATH_MAX] = {};
908 int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX);
909 APPSPAWN_CHECK(len > 0, return false, "Failed to format path");
910
911 FILE *f = fopen(path, "rb");
912 if (f != NULL) {
913 fclose(f);
914 #ifndef APPSPAWN_TEST
915 return true;
916 #endif
917 }
918 return false;
919 }
920
SetSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, char *rootPath)921 static int SetSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, char *rootPath)
922 {
923 APPSPAWN_LOGW("SetSystemConstMounted %{public}s ", rootPath);
924 char path[PATH_MAX] = {};
925 int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX);
926 APPSPAWN_CHECK(len > 0, return 0, "Failed to format path");
927
928 FILE *f = fopen(path, "wb");
929 if (f != NULL) {
930 fclose(f);
931 }
932 return 0;
933 }
934
UnmountPath(char *rootPath, uint32_t len, const SandboxMountNode *sandboxNode)935 static void UnmountPath(char *rootPath, uint32_t len, const SandboxMountNode *sandboxNode)
936 {
937 if (sandboxNode->type == SANDBOX_TAG_MOUNT_PATH) {
938 PathMountNode *pathNode = (PathMountNode *)sandboxNode;
939 int ret = strcat_s(rootPath, len, pathNode->target);
940 APPSPAWN_CHECK(ret == 0, return, "Failed to format");
941 APPSPAWN_LOGV("Unmount sandbox config sandbox path %{public}s ", rootPath);
942 ret = umount2(rootPath, MNT_DETACH);
943 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount2 %{public}s errno: %{public}d", rootPath, errno);
944 }
945 }
946
UnmountDepPaths(const AppSpawnSandboxCfg *sandbox, uid_t uid)947 int UnmountDepPaths(const AppSpawnSandboxCfg *sandbox, uid_t uid)
948 {
949 APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context");
950 APPSPAWN_LOGI("Unmount sandbox mount-paths-deps %{public}u ", sandbox->depNodeCount);
951 char path[PATH_MAX] = {};
952 int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE);
953 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1);
954 uint32_t rootLen = strlen(path);
955 for (uint32_t i = 0; i < sandbox->depNodeCount; i++) {
956 SandboxNameGroupNode *groupNode = sandbox->depGroupNodes[i];
957 if (groupNode == NULL || groupNode->depNode == NULL) {
958 continue;
959 }
960 // unmount this deps
961 UnmountPath(path, sizeof(path), &groupNode->depNode->sandboxNode);
962 path[rootLen] = '\0';
963 }
964 return 0;
965 }
966
UnmountSandboxConfigs(const AppSpawnSandboxCfg *sandbox, uid_t uid, const char *name)967 int UnmountSandboxConfigs(const AppSpawnSandboxCfg *sandbox, uid_t uid, const char *name)
968 {
969 APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context");
970 APPSPAWN_CHECK(name != NULL, return -1, "Invalid name");
971 char path[PATH_MAX] = {};
972 int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE);
973 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1);
974 uint32_t rootLen = strlen(path);
975 APPSPAWN_LOGI("Unmount sandbox %{public}s root: %{public}s", name, path);
976
977 if (!IsSandboxMounted(sandbox, name, path)) {
978 return 0;
979 }
980
981 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, name);
982 if (section == NULL) {
983 return 0;
984 }
985 ListNode *node = section->front.next;
986 while (node != §ion->front) {
987 SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
988 UnmountPath(path, sizeof(path), sandboxNode);
989 path[rootLen] = '\0';
990 // get next
991 node = node->next;
992 }
993
994 // delete stamp file
995 ret = strcat_s(path, sizeof(path), SANDBOX_STAMP_FILE_SUFFIX);
996 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return 0);
997 APPSPAWN_LOGI("Unmount sandbox %{public}s ", path);
998 unlink(path);
999 return 0;
1000 }
1001
1002 // Check whether the process incubation contains the ohos.permission.ACCESS_DLP_FILE permission
IsADFPermission(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property)1003 static bool IsADFPermission(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property)
1004 {
1005 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, ACCESS_DLP_FILE_MODE);
1006 if (index > 0 && CheckAppPermissionFlagSet(property, index)) {
1007 return true;
1008 }
1009
1010 if (GetBundleName(property) != NULL && strstr(GetBundleName(property), "com.ohos.dlpmanager") != NULL) {
1011 return true;
1012 }
1013 return false;
1014 }
1015
StagedMountSystemConst(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)1016 int StagedMountSystemConst(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
1017 {
1018 APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
1019 /**
1020 * system-const 处理逻辑
1021 * root-dir "/mnt/sandbox/app-root/<currentUserId>"
1022 * 遍历system-const, 处理mount path -- 可以清除配置
1023 * src = mount-path.src-path
1024 * dst = root-dir + mount-path.sandbox-path
1025 *
1026 * 遍历name-groups,处理mount path
1027 * 检查type,必须是 system-const
1028 * 如果存在 mount-paths-deps
1029 * src = mount-path.src-path
1030 * dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path>
1031 * 否则:
1032 * src = mount-path.src-path
1033 * dst = root-dir + mount-path.sandbox-path
1034 */
1035 SandboxContext *context = GetSandboxContext();
1036 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR);
1037 int ret = InitSandboxContext(context, sandbox, property, nwebspawn);
1038 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1039
1040 if (IsSandboxMounted(sandbox, "system-const", context->rootPath) && IsADFPermission(sandbox, property) != true) {
1041 APPSPAWN_LOGV("Sandbox system-const %{public}s has been mount", context->rootPath);
1042 DeleteSandboxContext(context);
1043 return 0;
1044 }
1045
1046 APPSPAWN_LOGV("Set sandbox system-const %{public}s", context->rootPath);
1047 uint32_t operation = 0;
1048 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX); // 首次挂载,使用sandbox替换
1049 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const");
1050 if (section != NULL) {
1051 ret = MountSandboxConfig(context, sandbox, section, operation);
1052 }
1053 SetSandboxMounted(sandbox, "system-const", context->rootPath);
1054 DeleteSandboxContext(context);
1055 return ret;
1056 }
1057
MountDepGroups(const SandboxContext *context, SandboxNameGroupNode *groupNode)1058 static int MountDepGroups(const SandboxContext *context, SandboxNameGroupNode *groupNode)
1059 {
1060 /**
1061 * 在unshare前处理mount-paths-deps 处理逻辑
1062 * 1.判断是否有mount-paths-deps节点,没有直接返回;
1063 * 2.填充json文件中路径的变量值;
1064 * 3.校验deps-mode的值是否是not-exists
1065 * 是not-exist则判断mount-paths.src-path是否存在,若不存在则创建并挂载mount-paths-deps中的目录
1066 * 若存在则不挂载mount-paths-deps中的目录
1067 * 是always则创建并挂载mount-paths-deps中的目录;
1068 * deps-mode默认值为always;
1069 *
1070 */
1071 int ret = 0;
1072 if (groupNode == NULL || groupNode->depNode == NULL) {
1073 return 0;
1074 }
1075
1076 ret = UpdateMountPathDepsPath(context, groupNode);
1077 APPSPAWN_CHECK(ret == 0, return ret, "Failed to updata deps path name groups %{public}s", groupNode->section.name);
1078
1079 if (groupNode->depMode == MOUNT_MODE_NOT_EXIST && CheckAndCreateDepPath(context, groupNode)) {
1080 return 0;
1081 }
1082
1083 uint32_t operation = 0;
1084 SetMountPathOperation(&operation, MOUNT_PATH_OP_UNMOUNT);
1085 groupNode->depMounted = 1;
1086 ret = DoSandboxPathNodeMount(context, &groupNode->section, groupNode->depNode, operation);
1087 if (ret != 0) {
1088 APPSPAWN_LOGE("Mount deps root fail %{public}s", groupNode->section.name);
1089 }
1090 return ret;
1091 }
1092
SetSystemConstDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1093 static int SetSystemConstDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1094 {
1095 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const");
1096 if (section == NULL || section->nameGroups == NULL) {
1097 return 0;
1098 }
1099
1100 int ret = 0;
1101 for (uint32_t i = 0; i < section->number; i++) {
1102 if (section->nameGroups[i] == NULL) {
1103 continue;
1104 }
1105 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
1106 ret = MountDepGroups(context, groupNode);
1107 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1108 }
1109 return ret;
1110 }
1111
SetAppVariableDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1112 static int SetAppVariableDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1113 {
1114 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable");
1115 if (section == NULL || section->nameGroups == NULL) {
1116 return 0;
1117 }
1118
1119 int ret = 0;
1120 for (uint32_t i = 0; i < section->number; i++) {
1121 if (section->nameGroups[i] == NULL) {
1122 continue;
1123 }
1124 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
1125 ret = MountDepGroups(context, groupNode);
1126 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1127 }
1128 return ret;
1129 }
1130
SetSpawnFlagsDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1131 static int SetSpawnFlagsDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1132 {
1133 ListNode *node = sandbox->spawnFlagsQueue.front.next;
1134 int ret = 0;
1135 while (node != &sandbox->spawnFlagsQueue.front) {
1136 SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node);
1137 // match flags point
1138 if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) {
1139 node = node->next;
1140 continue;
1141 }
1142
1143 if (sandboxNode->section.nameGroups == NULL) {
1144 node = node->next;
1145 continue;
1146 }
1147
1148 for (uint32_t i = 0; i < sandboxNode->section.number; i++) {
1149 if (sandboxNode->section.nameGroups[i] == NULL) {
1150 continue;
1151 }
1152 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)sandboxNode->section.nameGroups[i];
1153 ret = MountDepGroups(context, groupNode);
1154 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1155 }
1156 node = node->next;
1157 }
1158 return ret;
1159 }
1160
SetPackageNameDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1161 static int SetPackageNameDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1162 {
1163 SandboxPackageNameNode *sandboxNode =
1164 (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName);
1165 if (sandboxNode == NULL || sandboxNode->section.nameGroups == NULL) {
1166 return 0;
1167 }
1168
1169 int ret = 0;
1170 for (uint32_t i = 0; i < sandboxNode->section.number; i++) {
1171 if (sandboxNode->section.nameGroups[i] == NULL) {
1172 continue;
1173 }
1174 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)sandboxNode->section.nameGroups[i];
1175 ret = MountDepGroups(context, groupNode);
1176 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1177 }
1178 return ret;
1179 }
1180
SetPermissionDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1181 static int SetPermissionDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1182 {
1183 ListNode *node = sandbox->permissionQueue.front.next;
1184 int ret = 0;
1185 while (node != &sandbox->permissionQueue.front) {
1186 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
1187 // match flags point
1188 if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) {
1189 node = node->next;
1190 continue;
1191 }
1192
1193 if (permissionNode->section.nameGroups == NULL) {
1194 node = node->next;
1195 continue;
1196 }
1197
1198 for (uint32_t i = 0; i < permissionNode->section.number; i++) {
1199 if (permissionNode->section.nameGroups[i] == NULL) {
1200 continue;
1201 }
1202 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)permissionNode->section.nameGroups[i];
1203 ret = MountDepGroups(context, groupNode);
1204 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1205 }
1206 node = node->next;
1207 }
1208 return ret;
1209 }
1210
1211 // The execution of the preunshare phase depends on the mounted mount point
StagedDepGroupMounts(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1212 static int StagedDepGroupMounts(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1213 {
1214 int ret = SetSystemConstDepGroups(context, sandbox);
1215 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set system const deps groups");
1216
1217 ret = SetAppVariableDepGroups(context, sandbox);
1218 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set app variable deps groups");
1219
1220 ret = SetSpawnFlagsDepGroups(context, sandbox);
1221 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set spawn flags deps groups");
1222
1223 ret = SetPackageNameDepGroups(context, sandbox);
1224 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set package name deps groups");
1225
1226 ret = SetPermissionDepGroups(context, sandbox);
1227 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set permission deps groups");
1228
1229 return ret;
1230 }
1231
StagedMountPreUnShare(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)1232 int StagedMountPreUnShare(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1233 {
1234 APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context");
1235 APPSPAWN_LOGV("Set sandbox config before unshare group count %{public}d", sandbox->depNodeCount);
1236
1237 MountDirToShared(context, sandbox);
1238 int ret = StagedDepGroupMounts(context, sandbox);
1239
1240 return ret;
1241 }
1242
SetAppVariableConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)1243 static int SetAppVariableConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
1244 {
1245 /**
1246 * app-variable 处理逻辑
1247 * root-dir global.sandbox-root
1248 * app-variabl, 处理mount path
1249 * src = mount-path.src-path
1250 * dst = root-dir + mount-path.src-path
1251 * 遍历name-groups,处理mount path
1252 * 如果存在 mount-paths-deps
1253 * dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path>
1254 * 否则:
1255 * src = mount-path.src-path
1256 * dst = root-dir + mount-path.sandbox-path
1257 */
1258 int ret = 0;
1259 // 首次挂载,使用sandbox替换
1260 uint32_t operation = 0;
1261 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX);
1262 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable");
1263 if (section == NULL) {
1264 return 0;
1265 }
1266 ret = MountSandboxConfig(context, sandbox, section, operation);
1267 APPSPAWN_CHECK(ret == 0, return ret,
1268 "Set app-variable config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
1269 return 0;
1270 }
1271
StagedMountPostUnshare(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)1272 int StagedMountPostUnshare(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
1273 {
1274 APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context");
1275 APPSPAWN_LOGV("Set sandbox config after unshare ");
1276
1277 int ret = SetAppVariableConfig(context, sandbox);
1278 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1279 if (!context->nwebspawn) {
1280 ret = SetExpandSandboxConfig(context, sandbox);
1281 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1282 }
1283
1284 ret = SetSandboxSpawnFlagsConfig(context, sandbox);
1285 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1286
1287 ret = SetSandboxPackageNameConfig(context, sandbox);
1288 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1289
1290 ret = SetSandboxPermissionConfig(context, sandbox);
1291 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1292 return ret;
1293 }
1294
1295 #ifdef APPSPAWN_MOUNT_TMPSHM
MountDevShmPath(SandboxContext *context)1296 static void MountDevShmPath(SandboxContext *context)
1297 {
1298 char sandboxDevShmPath[PATH_MAX] = {};
1299 int ret = strcpy_s(sandboxDevShmPath, sizeof(sandboxDevShmPath), context->rootPath);
1300 APPSPAWN_CHECK(ret == 0, return, "Failed to strcpy rootPath");
1301 ret = strcat_s(sandboxDevShmPath, sizeof(sandboxDevShmPath), DEV_SHM_DIR);
1302 APPSPAWN_CHECK(ret == 0, return, "Failed to format devShmPath");
1303 int result = mount("tmpfs", sandboxDevShmPath, "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, "size=32M");
1304 if (result != 0) {
1305 APPSPAWN_LOGW("Error mounting %{public}s to tmpfs, errno %{public}d", sandboxDevShmPath, errno);
1306 }
1307 }
1308 #endif
1309
MountSandboxConfigs(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)1310 int MountSandboxConfigs(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
1311 {
1312 APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
1313 APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
1314
1315 SandboxContext *context = GetSandboxContext();
1316 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR);
1317 int ret = InitSandboxContext(context, sandbox, property, nwebspawn);
1318 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1319
1320 APPSPAWN_LOGV("Set sandbox config %{public}s sandboxNsFlags 0x%{public}x",
1321 context->rootPath, context->sandboxNsFlags);
1322 do {
1323 ret = StagedMountPreUnShare(context, sandbox);
1324 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1325
1326 CreateSandboxDir(context->rootPath, FILE_MODE);
1327 // add pid to a new mnt namespace
1328 ret = unshare(context->sandboxNsFlags);
1329 APPSPAWN_CHECK(ret == 0, break,
1330 "unshare failed, app: %{public}s errno: %{public}d", context->bundleName, errno);
1331 if ((context->sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) {
1332 ret = EnableNewNetNamespace();
1333 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1334 }
1335
1336 ret = SandboxRootFolderCreate(context, sandbox);
1337 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1338
1339 ret = StagedMountPostUnshare(context, sandbox);
1340 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1341
1342 ret = SetOverlayAppSandboxConfig(context, sandbox);
1343 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1344 ret = SetBundleResourceSandboxConfig(context, sandbox);
1345 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1346
1347 #ifdef APPSPAWN_MOUNT_TMPSHM
1348 MountDevShmPath(context);
1349 #endif
1350 ret = ChangeCurrentDir(context);
1351 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1352 #if defined(APPSPAWN_MOUNT_TMPSHM) && defined(WITH_SELINUX)
1353 Restorecon(DEV_SHM_DIR);
1354 #endif
1355 APPSPAWN_LOGV("Change root dir success %{public}s ", context->rootPath);
1356 } while (0);
1357 DeleteSandboxContext(context);
1358 return ret;
1359 }
1360