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