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