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
52static inline void SetMountPathOperation(uint32_t *operation, uint32_t index)
53{
54    *operation |= (1 << index);
55}
56
57static 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
63APPSPAWN_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
70APPSPAWN_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
94int 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
121static 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
150static SandboxContext *g_sandboxContext = NULL;
151
152SandboxContext *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
176void 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
189static 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
238static 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
250static 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
265APPSPAWN_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
295static 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
335APPSPAWN_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
351APPSPAWN_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
377APPSPAWN_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
392static 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// 根据沙盒配置文件中挂载类别进行挂载挂载
415static 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
436static 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
483static 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
514static 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
542static 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
568static 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
604static 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
612static 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
658static 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
686static 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
709static 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
743static 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
770static 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
781static 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
799static 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
819static 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
829static 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
844static 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
868static 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
883static 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
905static 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
921static 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
935static 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
947int 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
967int 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
1003static 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
1016int 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
1058static 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
1093static 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
1112static 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
1131static 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
1161static 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
1181static 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
1212static 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
1232int 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
1243static 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
1272int 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
1296static 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
1310int 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