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