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 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <sched.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 
26 #include <sys/mount.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30 
31 #include "appspawn_msg.h"
32 #include "appspawn_utils.h"
33 #ifdef WITH_DLP
34 #include "dlp_fuse_fd.h"
35 #endif
36 #include "init_utils.h"
37 #include "parameter.h"
38 #include "securec.h"
39 
SetMountPathOperation(uint32_t * operation,uint32_t index)40 static inline void SetMountPathOperation(uint32_t *operation, uint32_t index)
41 {
42     *operation |= (1 << index);
43 }
44 
CheckSpawningMsgFlagSet(const SandboxContext * context,uint32_t index)45 static inline bool CheckSpawningMsgFlagSet(const SandboxContext *context, uint32_t index)
46 {
47     APPSPAWN_CHECK(context->message != NULL, return false, "Invalid property for type %{public}u", TLV_MSG_FLAGS);
48     return CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, index);
49 }
50 
CheckSpawningPermissionFlagSet(const SandboxContext * context,uint32_t index)51 APPSPAWN_STATIC inline bool CheckSpawningPermissionFlagSet(const SandboxContext *context, uint32_t index)
52 {
53     APPSPAWN_CHECK(context != NULL && context->message != NULL,
54         return NULL, "Invalid property for type %{public}u", TLV_PERMISSION);
55     return CheckAppSpawnMsgFlag(context->message, TLV_PERMISSION, index);
56 }
57 
CheckDirRecursive(const char * path)58 APPSPAWN_STATIC bool CheckDirRecursive(const char *path)
59 {
60     char buffer[PATH_MAX] = {0};
61     const char slash = '/';
62     const char *p = path;
63     char *curPos = strchr(path, slash);
64     while (curPos != NULL) {
65         int len = curPos - p;
66         p = curPos + 1;
67         if (len == 0) {
68             curPos = strchr(p, slash);
69             continue;
70         }
71         int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1);
72         APPSPAWN_CHECK(ret == 0, return false, "Failed to copy path");
73         ret = access(buffer, F_OK);
74         APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
75         curPos = strchr(p, slash);
76     }
77     int ret = access(path, F_OK);
78     APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
79     return true;
80 }
81 
SandboxMountPath(const MountArg * arg)82 int SandboxMountPath(const MountArg *arg)
83 {
84     APPSPAWN_CHECK(arg != NULL && arg->originPath != NULL && arg->destinationPath != NULL,
85         return APPSPAWN_ARG_INVALID, "Invalid arg ");
86 
87     APPSPAWN_LOGV("Bind mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s",
88         arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
89         (uint32_t)arg->mountFlags, arg->options, arg->originPath, arg->destinationPath);
90 
91     int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options);
92     if (ret != 0) {
93         if (arg->originPath != NULL && strstr(arg->originPath, "/data/app/el2/") != NULL) {
94             CheckDirRecursive(arg->originPath);
95         }
96         APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
97             errno, arg->originPath, arg->destinationPath);
98         return errno;
99     }
100     ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL);
101     if (ret != 0) {
102         APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
103             errno, arg->originPath, arg->destinationPath);
104         return errno;
105     }
106     return 0;
107 }
108 
BuildRootPath(char * buffer,uint32_t bufferLen,const AppSpawnSandboxCfg * sandbox,uid_t uid)109 static int BuildRootPath(char *buffer, uint32_t bufferLen, const AppSpawnSandboxCfg *sandbox, uid_t uid)
110 {
111     int ret = 0;
112     int len = 0;
113     uint32_t currLen = 0;
114     uint32_t userIdLen = sizeof(PARAMETER_USER_ID) - 1;
115     uint32_t rootLen = strlen(sandbox->rootPath);
116     char *rootPath = strstr(sandbox->rootPath, PARAMETER_USER_ID);
117     if (rootPath == NULL) {
118         len = sprintf_s(buffer, bufferLen, "%s/%d", sandbox->rootPath, uid);
119     } else {
120         ret = memcpy_s(buffer, bufferLen, sandbox->rootPath, rootPath - sandbox->rootPath);
121         APPSPAWN_CHECK(ret == 0, return ret, "Failed to copy root path %{public}s", sandbox->rootPath);
122         currLen = rootPath - sandbox->rootPath;
123 
124         if (rootLen > (currLen + userIdLen)) {
125             len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d%s",
126                 uid, sandbox->rootPath + currLen + userIdLen);
127         } else {
128             len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d", uid);
129         }
130         APPSPAWN_CHECK(len > 0 && (uint32_t)(len < (bufferLen - currLen)), return ret,
131             "Failed to format root path %{public}s", sandbox->rootPath);
132         currLen += (uint32_t)len;
133     }
134     buffer[currLen] = '\0';
135     return 0;
136 }
137 
138 static SandboxContext *g_sandboxContext = NULL;
139 
GetSandboxContext(void)140 SandboxContext *GetSandboxContext(void)
141 {
142     if (g_sandboxContext == NULL) {
143         SandboxContext *context = calloc(1, MAX_SANDBOX_BUFFER * MAX_BUFFER + sizeof(SandboxContext));
144         APPSPAWN_CHECK(context != NULL, return NULL, "Failed to get mem");
145         char *buffer = (char *)(context + 1);
146         for (int i = 0; i < MAX_BUFFER; i++) {
147             context->buffer[i].bufferLen = MAX_SANDBOX_BUFFER;
148             context->buffer[i].current = 0;
149             context->buffer[i].buffer = buffer + MAX_SANDBOX_BUFFER * i;
150         }
151         context->bundleName = NULL;
152         context->bundleHasWps = 0;
153         context->dlpBundle = 0;
154         context->appFullMountEnable = 0;
155         context->sandboxSwitch = 1;
156         context->sandboxShared = false;
157         context->message = NULL;
158         context->rootPath = NULL;
159         g_sandboxContext = context;
160     }
161     return g_sandboxContext;
162 }
163 
DeleteSandboxContext(SandboxContext * context)164 void DeleteSandboxContext(SandboxContext *context)
165 {
166     APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return);
167     if (context->rootPath) {
168         free(context->rootPath);
169         context->rootPath = NULL;
170     }
171     if (context == g_sandboxContext) {
172         g_sandboxContext = NULL;
173     }
174     free(context);
175 }
176 
InitSandboxContext(SandboxContext * context,const AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property,int nwebspawn)177 static int InitSandboxContext(SandboxContext *context,
178     const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
179 {
180     AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppProperty(property, TLV_MSG_FLAGS);
181     APPSPAWN_CHECK(msgFlags != NULL, return APPSPAWN_TLV_NONE,
182         "No msg flags in msg %{public}s", GetProcessName(property));
183     context->nwebspawn = nwebspawn;
184     context->bundleName = GetBundleName(property);
185     context->bundleHasWps = strstr(context->bundleName, "wps") != NULL;
186     context->dlpBundle = strcmp(GetProcessName(property), "com.ohos.dlpmanager") == 0;
187     context->appFullMountEnable = sandbox->appFullMountEnable;
188 
189     context->sandboxSwitch = 1;
190     context->sandboxShared = false;
191     SandboxPackageNameNode *packageNode = (SandboxPackageNameNode *)GetSandboxSection(
192         &sandbox->packageNameQueue, context->bundleName);
193     if (packageNode) {
194         context->sandboxShared = packageNode->section.sandboxShared;
195     }
196     context->message = property->message;
197 
198     context->sandboxNsFlags = CLONE_NEWNS;
199     if ((CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX) && !IsDeveloperModeOpen()) ||
200         CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_NETWORK)) {
201         context->sandboxNsFlags |= sandbox->sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0;
202     }
203 
204     // root path
205     const char *rootPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandbox->rootPath, NULL, NULL);
206     if (rootPath) {
207         context->rootPath = strdup(rootPath);
208     }
209     if (context->rootPath == NULL) {
210         DeleteSandboxContext(context);
211         return -1;
212     }
213     return 0;
214 }
215 
GetVarExtraData(const SandboxContext * context,const SandboxSection * section)216 static VarExtraData *GetVarExtraData(const SandboxContext *context, const SandboxSection *section)
217 {
218     static VarExtraData extraData;
219     (void)memset_s(&extraData, sizeof(extraData), 0, sizeof(extraData));
220     extraData.sandboxTag = GetSectionType(section);
221     if (GetSectionType(section) == SANDBOX_TAG_NAME_GROUP) {
222         SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section;
223         extraData.data.depNode = groupNode->depNode;
224     }
225     return &extraData;
226 }
227 
GetMountArgs(const SandboxContext * context,const PathMountNode * sandboxNode,uint32_t operation,MountArg * args)228 static uint32_t GetMountArgs(const SandboxContext *context,
229     const PathMountNode *sandboxNode, uint32_t operation, MountArg *args)
230 {
231     uint32_t category = sandboxNode->category;
232     const MountArgTemplate *tmp = GetMountArgTemplate(category);
233     if (tmp == 0) {
234         return MOUNT_TMP_DEFAULT;
235     }
236     args->fsType = tmp->fsType;
237     args->options = tmp->options;
238     args->mountFlags = tmp->mountFlags;
239     if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_PERMISSION)) {
240         if (!((category == MOUNT_TMP_DAC_OVERRIDE) && context->appFullMountEnable)) {
241             args->fsType = "";
242             args->options = "";
243         }
244     }
245     args->mountSharedFlag = (sandboxNode->mountSharedFlag) ? MS_SHARED : tmp->mountSharedFlag;
246     return category;
247 }
248 
CheckSandboxMountNode(const SandboxContext * context,const SandboxSection * section,const PathMountNode * sandboxNode,uint32_t operation)249 APPSPAWN_STATIC int CheckSandboxMountNode(const SandboxContext *context,
250     const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)
251 {
252     if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
253         APPSPAWN_LOGW("Invalid mount config section %{public}s", section->name);
254         return 0;
255     }
256     // special handle wps and don't use /data/app/xxx/<Package> config
257     if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) {  // flags-point
258         if (context->bundleHasWps &&
259             (strstr(sandboxNode->source, "/data/app") != NULL) &&
260             (strstr(sandboxNode->source, "/base") != NULL || strstr(sandboxNode->source, "/database") != NULL) &&
261             (strstr(sandboxNode->source, PARAMETER_PACKAGE_NAME) != NULL)) {
262             APPSPAWN_LOGW("Invalid mount source %{public}s section %{public}s",
263                 sandboxNode->source, section->name);
264             return 0;
265         }
266     }
267     // check apl
268     AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
269     if (msgDomainInfo != NULL && sandboxNode->appAplName != NULL) {
270         if (!strcmp(sandboxNode->appAplName, msgDomainInfo->apl)) {
271             APPSPAWN_LOGW("Invalid mount app apl %{public}s %{public}s section %{public}s",
272                 sandboxNode->appAplName, msgDomainInfo->apl, section->name);
273             return 0;
274         }
275     }
276     return 1;
277 }
278 
SandboxMountFusePath(const SandboxContext * context,const MountArg * args)279 static int32_t SandboxMountFusePath(const SandboxContext *context, const MountArg *args)
280 {
281     AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
282     APPSPAWN_CHECK(info != NULL, return APPSPAWN_TLV_NONE,
283         "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
284 
285     // umount fuse path, make sure that sandbox path is not a mount point
286     umount2(args->destinationPath, MNT_DETACH);
287 
288     int fd = open("/dev/fuse", O_RDWR);
289     APPSPAWN_CHECK(fd != -1, return -EINVAL,
290         "open /dev/fuse failed, errno: %{public}d sandbox path %{public}s", errno, args->destinationPath);
291 
292     char options[FUSE_OPTIONS_MAX_LEN];
293     (void)sprintf_s(options, sizeof(options), "fd=%d,"
294         "rootmode=40000,user_id=%d,group_id=%d,allow_other,"
295         "context=\"u:object_r:dlp_fuse_file:s0\","
296         "fscontext=u:object_r:dlp_fuse_file:s0", fd, info->uid, info->gid);
297 
298     APPSPAWN_LOGV("Bind mount dlp fuse \n "
299         "mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s",
300         args->fsType, args->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
301         (uint32_t)args->mountFlags, options, args->originPath, args->destinationPath);
302 
303     // To make sure destinationPath exist
304     CreateSandboxDir(args->destinationPath, FILE_MODE);
305     MountArg mountArg = {args->originPath, args->destinationPath, args->fsType, args->mountFlags, options, MS_SHARED};
306     int ret = SandboxMountPath(&mountArg);
307     if (ret != 0) {
308         close(fd);
309         return -1;
310     }
311     /* set DLP_FUSE_FD  */
312 #ifdef WITH_DLP
313     SetDlpFuseFd(fd);
314 #endif
315     return 0;
316 }
317 
CheckAndCreateSandboxFile(const char * file)318 APPSPAWN_STATIC void CheckAndCreateSandboxFile(const char *file)
319 {
320     if (access(file, F_OK) == 0) {
321         APPSPAWN_LOGI("file %{public}s already exist", file);
322         return;
323     }
324     MakeDirRec(file, FILE_MODE, 0);
325     int fd = open(file, O_CREAT, FILE_MODE);
326     if (fd < 0) {
327         APPSPAWN_LOGW("failed create %{public}s, err=%{public}d", file, errno);
328     } else {
329         close(fd);
330     }
331     return;
332 }
333 
CreateDemandSrc(const SandboxContext * context,const PathMountNode * sandboxNode,const MountArg * args)334 APPSPAWN_STATIC void CreateDemandSrc(const SandboxContext *context, const PathMountNode *sandboxNode,
335     const MountArg *args)
336 {
337     if (!sandboxNode->createDemand) {
338         return;
339     }
340     CheckAndCreateSandboxFile(args->originPath);
341     AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
342     APPSPAWN_CHECK(info != NULL, return,
343         "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
344 
345     // chmod
346     uid_t uid = sandboxNode->demandInfo->uid != INVALID_UID ? sandboxNode->demandInfo->uid : info->uid;
347     gid_t gid = sandboxNode->demandInfo->gid != INVALID_UID ? sandboxNode->demandInfo->gid : info->gid;
348     int ret = chown(args->originPath, uid, gid);
349     if (ret != 0) {
350         APPSPAWN_LOGE("Failed to chown %{public}s errno: %{public}d", args->originPath, errno);
351     }
352     if (sandboxNode->demandInfo->mode != INVALID_UID) {
353         ret = chmod(args->originPath, sandboxNode->demandInfo->mode);
354         if (ret != 0) {
355             APPSPAWN_LOGE("Failed to chmod %{public}s errno: %{public}d", args->originPath, errno);
356         }
357     }
358 }
359 
GetRealSrcPath(const SandboxContext * context,const char * source,VarExtraData * extraData)360 APPSPAWN_STATIC const char *GetRealSrcPath(const SandboxContext *context, const char *source, VarExtraData *extraData)
361 {
362     bool hasPackageName = strstr(source, "<variablePackageName>") != NULL;
363     extraData->variablePackageName = (char *)context->bundleName;
364     const char *originPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, source, NULL, extraData);
365     if (originPath == NULL) {
366         return NULL;
367     }
368     if (!hasPackageName) {
369         return originPath;
370     }
371     if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_ATOMIC_SERVICE) ||
372         !CheckDirRecursive(originPath)) {
373         return originPath;
374     }
375 
376     AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
377     char *accountId = GetAppSpawnMsgExtInfo(context->message, MSG_EXT_NAME_ACCOUNT_ID, NULL);
378     if (accountId == NULL || dacInfo == NULL) {
379         return originPath;
380     }
381 
382     // user target to format path
383     int len = sprintf_s(context->buffer[BUFFER_FOR_TARGET].buffer,
384         context->buffer[BUFFER_FOR_TARGET].bufferLen, "%s/%s", context->bundleName, accountId);
385     APPSPAWN_CHECK(len > 0, return NULL, "format variablePackageName fail %{public}s", context->bundleName);
386     extraData->variablePackageName = context->buffer[BUFFER_FOR_TARGET].buffer;
387     originPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, source, NULL, extraData);
388     if (originPath == NULL) {
389         return NULL;
390     }
391     MakeDirRec(originPath, FILE_MODE, 0);
392     int ret = chown(originPath, dacInfo->uid, dacInfo->gid);
393     APPSPAWN_CHECK_ONLY_LOG(ret == 0, "chown failed, path %{public}s, errno %{public}d", originPath, errno);
394     return originPath;
395 }
396 
DoSandboxPathNodeMount(const SandboxContext * context,const SandboxSection * section,const PathMountNode * sandboxNode,uint32_t operation)397 static int DoSandboxPathNodeMount(const SandboxContext *context,
398     const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)
399 {
400     if (CheckSandboxMountNode(context, section, sandboxNode, operation) == 0) {
401         return 0;
402     }
403 
404     MountArg args = {};
405     uint32_t category = GetMountArgs(context, sandboxNode, operation, &args);
406     VarExtraData *extraData = GetVarExtraData(context, section);
407     args.originPath = GetRealSrcPath(context, sandboxNode->source, extraData);
408     // dest
409     extraData->operation = operation;  // only destinationPath
410     // 对name group的节点,需要对目的沙盒进行特殊处理,不能带root-dir
411     if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_NAME_GROUP) &&
412         CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_ONLY_SANDBOX)) {
413         args.destinationPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, sandboxNode->target, NULL, extraData);
414     } else {
415         args.destinationPath = GetSandboxRealVar(context,
416             BUFFER_FOR_TARGET, sandboxNode->target, context->rootPath, extraData);
417     }
418     APPSPAWN_CHECK(args.originPath != NULL && args.destinationPath != NULL,
419         return APPSPAWN_ARG_INVALID, "Invalid path %{public}s %{public}s", args.originPath, args.destinationPath);
420 
421     if (sandboxNode->sandboxNode.type == SANDBOX_TAG_MOUNT_FILE) {
422         CheckAndCreateSandboxFile(args.destinationPath);
423     } else {
424         CreateSandboxDir(args.destinationPath, FILE_MODE);
425     }
426     CreateDemandSrc(context, sandboxNode, &args);
427 
428     if (CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_UNMOUNT)) {  // unmount this deps
429         APPSPAWN_LOGV("umount2 %{public}s", args.destinationPath);
430         umount2(args.destinationPath, MNT_DETACH);
431     }
432     int ret = 0;
433     if ((category == MOUNT_TMP_DLP_FUSE || category == MOUNT_TMP_FUSE) && context->dlpBundle == 1) {
434         ret = SandboxMountFusePath(context, &args);
435     } else {
436         ret = SandboxMountPath(&args);
437     }
438 
439     if (ret != 0 && sandboxNode->checkErrorFlag) {
440         APPSPAWN_LOGE("Failed to mount config, section: %{public}s result: %{public}d category: %{public}d",
441             section->name, ret, category);
442         return ret;
443     }
444     return 0;
445 }
446 
DoSandboxPathSymLink(const SandboxContext * context,const SandboxSection * section,const SymbolLinkNode * sandboxNode)447 static int DoSandboxPathSymLink(const SandboxContext *context,
448     const SandboxSection *section, const SymbolLinkNode *sandboxNode)
449 {
450     // Check the validity of the symlink configuration
451     if (sandboxNode->linkName == NULL || sandboxNode->target == NULL) {
452         APPSPAWN_LOGW("Invalid symlink config, section %{public}s", section->name);
453         return 0;
454     }
455 
456     const char *target = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandboxNode->target, NULL, NULL);
457     const char *linkName = GetSandboxRealVar(context, BUFFER_FOR_TARGET,
458         sandboxNode->linkName, context->rootPath, NULL);
459     APPSPAWN_LOGV("symlink, from %{public}s to %{public}s", target, linkName);
460     int ret = symlink(target, linkName);
461     if (ret && errno != EEXIST) {
462         if (sandboxNode->checkErrorFlag) {
463             APPSPAWN_LOGE("symlink failed, errno: %{public}d link info %{public}s %{public}s",
464                 errno, sandboxNode->target, sandboxNode->linkName);
465             return errno;
466         }
467         APPSPAWN_LOGV("symlink failed, errno: %{public}d link info %{public}s %{public}s",
468             errno, sandboxNode->target, sandboxNode->linkName);
469     }
470     return 0;
471 }
472 
DoSandboxNodeMount(const SandboxContext * context,const SandboxSection * section,uint32_t operation)473 static int DoSandboxNodeMount(const SandboxContext *context, const SandboxSection *section, uint32_t operation)
474 {
475     ListNode *node = section->front.next;
476     while (node != &section->front) {
477         int ret = 0;
478         SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
479         switch (sandboxNode->type) {
480             case SANDBOX_TAG_MOUNT_PATH:
481             case SANDBOX_TAG_MOUNT_FILE:
482                 ret = DoSandboxPathNodeMount(context, section, (PathMountNode *)sandboxNode, operation);
483                 break;
484             case SANDBOX_TAG_SYMLINK:
485                 if (!CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_SYMLINK)) {
486                     break;
487                 }
488                 ret = DoSandboxPathSymLink(context, section, (SymbolLinkNode *)sandboxNode);
489                 break;
490             default:
491                 break;
492         }
493         if (ret != 0) {
494             return ret;
495         }
496         node = node->next;
497     }
498     return 0;
499 }
500 
UpdateMountPathDepsPath(const SandboxContext * context,SandboxNameGroupNode * groupNode)501 static int UpdateMountPathDepsPath(const SandboxContext *context, SandboxNameGroupNode *groupNode)
502 {
503     PathMountNode *depNode = groupNode->depNode;
504     const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, depNode->source, NULL, NULL);
505     const char *sandboxPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, depNode->target, NULL, NULL);
506     if (srcPath == NULL || sandboxPath == NULL) {
507         APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name);
508         return APPSPAWN_SANDBOX_MOUNT_FAIL;
509     }
510     free(depNode->source);
511     depNode->source = strdup(srcPath);
512     free(depNode->target);
513     depNode->target = strdup(sandboxPath);
514     if (depNode->source == NULL || depNode->target == NULL) {
515         APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name);
516         if (depNode->source) {
517             free(depNode->source);
518             depNode->source = NULL;
519         }
520         if (depNode->target) {
521             free(depNode->target);
522             depNode->target = NULL;
523         }
524         return APPSPAWN_SANDBOX_MOUNT_FAIL;
525     }
526     return 0;
527 }
528 
CheckAndCreateDepPath(const SandboxContext * context,const SandboxNameGroupNode * groupNode)529 static bool CheckAndCreateDepPath(const SandboxContext *context, const SandboxNameGroupNode *groupNode)
530 {
531     PathMountNode *mountNode = (PathMountNode *)GetFirstSandboxMountNode(&groupNode->section);
532     if (mountNode == NULL) {
533         return false;
534     }
535 
536     // 这里可能需要替换deps的数据
537     VarExtraData *extraData = GetVarExtraData(context, &groupNode->section);
538     const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, mountNode->source, NULL, extraData);
539     if (srcPath == NULL) {
540         return false;
541     }
542     if (access(srcPath, F_OK) == 0) {
543         APPSPAWN_LOGV("Src path %{public}s exist, do not mount", srcPath);
544         return true;
545     }
546     // 不存在,则创建并挂载
547     APPSPAWN_LOGV("Mount depended source: %{public}s", groupNode->depNode->source);
548     CreateSandboxDir(groupNode->depNode->source, FILE_MODE);
549     return false;
550 }
551 
MountSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox,const SandboxSection * section,uint32_t op)552 static int MountSandboxConfig(const SandboxContext *context,
553     const AppSpawnSandboxCfg *sandbox, const SandboxSection *section, uint32_t op)
554 {
555     uint32_t operation = (op != MOUNT_PATH_OP_NONE) ? op : 0;
556     SetMountPathOperation(&operation, section->sandboxNode.type);
557     // if sandbox switch is off, don't do symlink work again
558     if (context->sandboxSwitch && sandbox->topSandboxSwitch) {
559         SetMountPathOperation(&operation, MOUNT_PATH_OP_SYMLINK);
560     }
561 
562     int ret = DoSandboxNodeMount(context, section, operation);
563     APPSPAWN_CHECK(ret == 0, return ret,
564         "Mount sandbox config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
565 
566     if (section->nameGroups == NULL) {
567         return 0;
568     }
569 
570     for (uint32_t i = 0; i < section->number; i++) {
571         if (section->nameGroups[i] == NULL) {
572             continue;
573         }
574         SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
575         SetMountPathOperation(&operation, SANDBOX_TAG_NAME_GROUP);
576         ret = DoSandboxNodeMount(context, &groupNode->section, operation);
577         APPSPAWN_CHECK(ret == 0, return ret,
578             "Mount name group %{public}s fail result: %{public}d", groupNode->section.name, ret);
579     }
580     return 0;
581 }
582 
SetExpandSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)583 static int SetExpandSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
584 {
585     int ret = ProcessExpandAppSandboxConfig(context, sandbox, "HspList");
586     APPSPAWN_CHECK(ret == 0, return ret,
587         "Set HspList config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
588     ret = ProcessExpandAppSandboxConfig(context, sandbox, "DataGroup");
589     APPSPAWN_CHECK(ret == 0, return ret,
590         "Set DataGroup config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
591 
592     bool mountDestBundlePath = false;
593     AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
594     if (msgDomainInfo != NULL) {
595         mountDestBundlePath = (strcmp(msgDomainInfo->apl, APL_SYSTEM_BASIC) == 0) ||
596             (strcmp(msgDomainInfo->apl, APL_SYSTEM_CORE) == 0);
597     }
598     if (mountDestBundlePath || (CheckSpawningMsgFlagSet(context, APP_FLAGS_ACCESS_BUNDLE_DIR) != 0)) {
599         // need permission check for system app here
600         const char *destBundlesPath = GetSandboxRealVar(context,
601             BUFFER_FOR_TARGET, "/data/bundles/", context->rootPath, NULL);
602         CreateSandboxDir(destBundlesPath, FILE_MODE);
603         MountArg mountArg = {PHYSICAL_APP_INSTALL_PATH, destBundlesPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE};
604         ret = SandboxMountPath(&mountArg);
605         APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
606     }
607     return 0;
608 }
609 
SetSandboxPackageNameConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)610 static int SetSandboxPackageNameConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
611 {
612     SandboxPackageNameNode *sandboxNode =
613         (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName);
614     if (sandboxNode != NULL) {
615         int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE);
616         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
617     }
618     return 0;
619 }
620 
SetSandboxSpawnFlagsConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)621 static int SetSandboxSpawnFlagsConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
622 {
623     ListNode *node = sandbox->spawnFlagsQueue.front.next;
624     while (node != &sandbox->spawnFlagsQueue.front) {
625         SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node);
626         // match flags point
627         if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) {
628             node = node->next;
629             continue;
630         }
631 
632         int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE);
633         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
634         node = node->next;
635     }
636     return 0;
637 }
638 
SetSandboxPermissionConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)639 static int SetSandboxPermissionConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
640 {
641     APPSPAWN_LOGV("Set permission config");
642     ListNode *node = sandbox->permissionQueue.front.next;
643     while (node != &sandbox->permissionQueue.front) {
644         SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
645         if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) {
646             node = node->next;
647             continue;
648         }
649 
650         APPSPAWN_LOGV("SetSandboxPermissionConfig permission %{public}d %{public}s",
651             permissionNode->permissionIndex, permissionNode->section.name);
652         int ret = MountSandboxConfig(context, sandbox, &permissionNode->section, MOUNT_PATH_OP_NONE);
653         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
654         node = node->next;
655     }
656     return 0;
657 }
658 
SetOverlayAppSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)659 static int SetOverlayAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
660 {
661     if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_OVERLAY)) {
662         return 0;
663     }
664     int ret = ProcessExpandAppSandboxConfig(context, sandbox, "Overlay");
665     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
666     return 0;
667 }
668 
SetBundleResourceSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)669 static int SetBundleResourceSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
670 {
671     if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_BUNDLE_RESOURCES)) {
672         return 0;
673     }
674     const char *destPath = GetSandboxRealVar(context,
675         BUFFER_FOR_TARGET, "/data/storage/bundle_resources/", context->rootPath, NULL);
676     CreateSandboxDir(destPath, FILE_MODE);
677     MountArg mountArg = {
678         "/data/service/el1/public/bms/bundle_resources/", destPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE
679     };
680     int ret = SandboxMountPath(&mountArg);
681     return ret;
682 }
683 
ChangeCurrentDir(const SandboxContext * context)684 static int32_t ChangeCurrentDir(const SandboxContext *context)
685 {
686     int32_t ret = 0;
687     ret = chdir(context->rootPath);
688     APPSPAWN_CHECK(ret == 0, return ret,
689         "chdir failed, app: %{public}s, path: %{public}s errno: %{public}d",
690         context->bundleName, context->rootPath, errno);
691 
692     if (context->sandboxShared) {
693         ret = chroot(context->rootPath);
694         APPSPAWN_CHECK(ret == 0, return ret,
695             "chroot failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
696         return ret;
697     }
698     ret = syscall(SYS_pivot_root, context->rootPath, context->rootPath);
699     APPSPAWN_CHECK(ret == 0, return ret,
700         "pivot root failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
701     ret = umount2(".", MNT_DETACH);
702     APPSPAWN_CHECK(ret == 0, return ret,
703         "MNT_DETACH failed,  path: %{public}s errno: %{public}d", context->rootPath, errno);
704     APPSPAWN_LOGV("ChangeCurrentDir %{public}s ", context->rootPath);
705     return ret;
706 }
707 
SandboxRootFolderCreateNoShare(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox,bool remountProc)708 static int SandboxRootFolderCreateNoShare(
709     const SandboxContext *context, const AppSpawnSandboxCfg *sandbox, bool remountProc)
710 {
711     APPSPAWN_LOGV("SandboxRootFolderCreateNoShare %{public}s ", context->rootPath);
712     int ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
713     APPSPAWN_CHECK(ret == 0, return ret,
714         "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
715 
716     MountArg arg = {context->rootPath, context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL, MS_SLAVE};
717     ret = SandboxMountPath(&arg);
718     APPSPAWN_CHECK(ret == 0, return ret,
719         "mount path failed, app: %{public}s errno: %{public}d", context->rootPath, ret);
720     return ret;
721 }
722 
SandboxRootFolderCreate(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)723 static int SandboxRootFolderCreate(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
724 {
725     APPSPAWN_LOGV("topSandboxSwitch %{public}d sandboxSwitch: %{public}d sandboxShared: %{public}d \n",
726         sandbox->topSandboxSwitch, context->sandboxSwitch, context->sandboxShared);
727 
728     int ret = 0;
729     if (sandbox->topSandboxSwitch == 0 || context->sandboxSwitch == 0) {
730         ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
731         APPSPAWN_CHECK(ret == 0, return ret,
732             "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
733         // bind mount "/" to /mnt/sandbox/<packageName> path
734         // rootfs: to do more resources bind mount here to get more strict resources constraints
735         ret = mount("/", context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL);
736         APPSPAWN_CHECK(ret == 0, return ret,
737             "mount bind / failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
738     } else if (!context->sandboxShared) {
739         bool remountProc = !context->nwebspawn && ((sandbox->sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID);
740         ret = SandboxRootFolderCreateNoShare(context, sandbox, remountProc);
741     }
742     return ret;
743 }
744 
IsSandboxMounted(const AppSpawnSandboxCfg * sandbox,const char * name,const char * rootPath)745 static bool IsSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, const char *rootPath)
746 {
747     char path[PATH_MAX] = {};
748     int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX);
749     APPSPAWN_CHECK(len > 0, return false, "Failed to format path");
750 
751     FILE *f = fopen(path, "rb");
752     if (f != NULL) {
753         fclose(f);
754 #ifndef APPSPAWN_TEST
755         return true;
756 #endif
757     }
758     return false;
759 }
760 
SetSandboxMounted(const AppSpawnSandboxCfg * sandbox,const char * name,char * rootPath)761 static int SetSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, char *rootPath)
762 {
763     APPSPAWN_LOGW("SetSystemConstMounted %{public}s ", rootPath);
764     char path[PATH_MAX] = {};
765     int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX);
766     APPSPAWN_CHECK(len > 0, return 0, "Failed to format path");
767 
768     FILE *f = fopen(path, "wb");
769     if (f != NULL) {
770         fclose(f);
771     }
772     return 0;
773 }
774 
UnmountPath(char * rootPath,uint32_t len,const SandboxMountNode * sandboxNode)775 static void UnmountPath(char *rootPath, uint32_t len, const SandboxMountNode *sandboxNode)
776 {
777     if (sandboxNode->type == SANDBOX_TAG_MOUNT_PATH) {
778         PathMountNode *pathNode = (PathMountNode *)sandboxNode;
779         int ret = strcat_s(rootPath, len, pathNode->target);
780         APPSPAWN_CHECK(ret == 0, return, "Failed to format");
781         APPSPAWN_LOGV("Unmount sandbox config sandbox path %{public}s ", rootPath);
782         ret = umount2(rootPath, MNT_DETACH);
783         APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount2 %{public}s errno: %{public}d", rootPath, errno);
784     }
785 }
786 
UnmountDepPaths(const AppSpawnSandboxCfg * sandbox,uid_t uid)787 int UnmountDepPaths(const AppSpawnSandboxCfg *sandbox, uid_t uid)
788 {
789     APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context");
790     APPSPAWN_LOGI("Unmount sandbox mount-paths-deps %{public}u ", sandbox->depNodeCount);
791     char path[PATH_MAX] = {};
792     int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE);
793     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1);
794     uint32_t rootLen = strlen(path);
795     for (uint32_t i = 0; i < sandbox->depNodeCount; i++) {
796         SandboxNameGroupNode *groupNode = sandbox->depGroupNodes[i];
797         if (groupNode == NULL || groupNode->depNode == NULL) {
798             continue;
799         }
800         // unmount this deps
801         UnmountPath(path, sizeof(path), &groupNode->depNode->sandboxNode);
802         path[rootLen] = '\0';
803     }
804     return 0;
805 }
806 
UnmountSandboxConfigs(const AppSpawnSandboxCfg * sandbox,uid_t uid,const char * name)807 int UnmountSandboxConfigs(const AppSpawnSandboxCfg *sandbox, uid_t uid, const char *name)
808 {
809     APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context");
810     APPSPAWN_CHECK(name != NULL, return -1, "Invalid name");
811     char path[PATH_MAX] = {};
812     int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE);
813     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1);
814     uint32_t rootLen = strlen(path);
815     APPSPAWN_LOGI("Unmount sandbox %{public}s root: %{public}s", name, path);
816 
817     if (!IsSandboxMounted(sandbox, name, path)) {
818         return 0;
819     }
820 
821     SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, name);
822     if (section == NULL) {
823         return 0;
824     }
825     ListNode *node = section->front.next;
826     while (node != &section->front) {
827         SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
828         UnmountPath(path, sizeof(path), sandboxNode);
829         path[rootLen] = '\0';
830         // get next
831         node = node->next;
832     }
833 
834     // delete stamp file
835     ret = strcat_s(path, sizeof(path), SANDBOX_STAMP_FILE_SUFFIX);
836     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return 0);
837     APPSPAWN_LOGI("Unmount sandbox %{public}s ", path);
838     unlink(path);
839     return 0;
840 }
841 
StagedMountSystemConst(const AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property,int nwebspawn)842 int StagedMountSystemConst(const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
843 {
844     APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
845     /**
846      * system-const 处理逻辑
847      *   root-dir "/mnt/sandbox/app-root/<currentUserId>"
848      *   遍历system-const, 处理mount path   -- 可以清除配置
849      *      src = mount-path.src-path
850      *      dst = root-dir + mount-path.sandbox-path
851      *
852      *   遍历name-groups,处理mount path
853      *      检查type,必须是 system-const
854      *      如果存在 mount-paths-deps
855      *          src = mount-path.src-path
856      *          dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path>
857      *      否则:
858      *          src = mount-path.src-path
859      *          dst = root-dir + mount-path.sandbox-path
860      */
861     SandboxContext *context = GetSandboxContext();
862     APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR);
863     int ret = InitSandboxContext(context, sandbox, property, nwebspawn);
864     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
865 
866     if (IsSandboxMounted(sandbox, "system-const", context->rootPath)) {
867         APPSPAWN_LOGV("Sandbox system-const %{public}s has been mount", context->rootPath);
868         DeleteSandboxContext(context);
869         return 0;
870     }
871 
872     APPSPAWN_LOGV("Set sandbox system-const %{public}s", context->rootPath);
873     uint32_t operation = 0;
874     SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX); // 首次挂载,使用sandbox替换
875     SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const");
876     if (section != NULL) {
877         ret = MountSandboxConfig(context, sandbox, section, operation);
878     }
879     SetSandboxMounted(sandbox, "system-const", context->rootPath);
880     DeleteSandboxContext(context);
881     return ret;
882 }
883 
StagedMountPreUnShare(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)884 int StagedMountPreUnShare(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
885 {
886     APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context");
887     APPSPAWN_LOGV("Set sandbox config before unshare group count %{public}d", sandbox->depNodeCount);
888 
889     /**
890      * 在unshare前处理mount-paths-deps 处理逻辑
891      *   root-dir global.sandbox-root
892      *   src-dir "/mnt/sandbox/app-common/<currentUserId>"
893      *   遍历mount-paths-deps,处理mount-paths-deps
894      *      src = mount-paths-deps.src-path
895      *      dst = root-dir + mount-paths-deps.sandbox-path
896      *      如果设置no-exist,检查mount-paths 的src(实际路径) 是否不存在,
897                 则安mount-paths-deps.src-path 创建。 按shared方式挂载mount-paths-deps
898      *      如果是 always,按shared方式挂载mount-paths-deps
899      *      不配置 按always 处理
900      *
901      */
902     int ret = 0;
903     for (uint32_t i = 0; i < sandbox->depNodeCount; i++) {
904         SandboxNameGroupNode *groupNode = sandbox->depGroupNodes[i];
905         if (groupNode == NULL || groupNode->depNode == NULL) {
906             continue;
907         }
908         APPSPAWN_LOGV("Set sandbox deps config %{public}s ", groupNode->section.name);
909         // change source and target to real path
910         ret = UpdateMountPathDepsPath(context, groupNode);
911         APPSPAWN_CHECK(ret == 0, return ret,
912             "Failed to update deps path name group %{public}s", groupNode->section.name);
913 
914         if (groupNode->depMode == MOUNT_MODE_NOT_EXIST && CheckAndCreateDepPath(context, groupNode)) {
915             continue;
916         }
917 
918         uint32_t operation = 0;
919         SetMountPathOperation(&operation, MOUNT_PATH_OP_UNMOUNT);
920         groupNode->depMounted = 1;
921         ret = DoSandboxPathNodeMount(context, &groupNode->section, groupNode->depNode, operation);
922         if (ret != 0) {
923             APPSPAWN_LOGE("Mount deps root fail %{public}s", groupNode->section.name);
924             return ret;
925         }
926     }
927     return 0;
928 }
929 
SetAppVariableConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)930 static int SetAppVariableConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
931 {
932     /**
933      * app-variable 处理逻辑
934      *   root-dir global.sandbox-root
935      *   app-variabl, 处理mount path
936      *      src = mount-path.src-path
937      *      dst = root-dir + mount-path.src-path
938      *   遍历name-groups,处理mount path
939      *      如果存在 mount-paths-deps
940      *          dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path>
941      *      否则:
942      *          src = mount-path.src-path
943      *          dst = root-dir + mount-path.sandbox-path
944      */
945     int ret = 0;
946     // 首次挂载,使用sandbox替换
947     uint32_t operation = 0;
948     SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX);
949     SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable");
950     if (section == NULL) {
951         return 0;
952     }
953     ret = MountSandboxConfig(context, sandbox, section, operation);
954     APPSPAWN_CHECK(ret == 0, return ret,
955         "Set app-variable config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
956     return 0;
957 }
958 
StagedMountPostUnshare(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)959 int StagedMountPostUnshare(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
960 {
961     APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context");
962     APPSPAWN_LOGV("Set sandbox config after unshare ");
963 
964     int ret = SetAppVariableConfig(context, sandbox);
965     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
966     if (!context->nwebspawn) {
967         ret = SetExpandSandboxConfig(context, sandbox);
968         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
969     }
970 
971     ret = SetSandboxSpawnFlagsConfig(context, sandbox);
972     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
973 
974     ret = SetSandboxPackageNameConfig(context, sandbox);
975     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
976 
977     ret = SetSandboxPermissionConfig(context, sandbox);
978     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
979     return ret;
980 }
981 
MountSandboxConfigs(const AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property,int nwebspawn)982 int MountSandboxConfigs(const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
983 {
984     APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
985     APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
986 
987     SandboxContext *context = GetSandboxContext();
988     APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR);
989     int ret = InitSandboxContext(context, sandbox, property, nwebspawn);
990     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
991 
992     APPSPAWN_LOGV("Set sandbox config %{public}s sandboxNsFlags 0x%{public}x",
993         context->rootPath, context->sandboxNsFlags);
994     do {
995         ret = StagedMountPreUnShare(context, sandbox);
996         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
997 
998         CreateSandboxDir(context->rootPath, FILE_MODE);
999         // add pid to a new mnt namespace
1000         ret = unshare(context->sandboxNsFlags);
1001         APPSPAWN_CHECK(ret == 0, break,
1002             "unshare failed, app: %{public}s errno: %{public}d", context->bundleName, errno);
1003         if ((context->sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) {
1004             ret = EnableNewNetNamespace();
1005             APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1006         }
1007 
1008         ret = SandboxRootFolderCreate(context, sandbox);
1009         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1010 
1011         ret = StagedMountPostUnshare(context, sandbox);
1012         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1013 
1014         ret = SetOverlayAppSandboxConfig(context, sandbox);
1015         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1016         ret = SetBundleResourceSandboxConfig(context, sandbox);
1017         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1018 
1019         ret = ChangeCurrentDir(context);
1020         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1021         APPSPAWN_LOGV("Change root dir success %{public}s ", context->rootPath);
1022     } while (0);
1023     DeleteSandboxContext(context);
1024     return ret;
1025 }
1026