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#undef _GNU_SOURCE
17#define _GNU_SOURCE
18#include <sched.h>
19
20#include "appspawn_manager.h"
21#include "appspawn_permission.h"
22#include "appspawn_sandbox.h"
23#include "appspawn_utils.h"
24#include "modulemgr.h"
25#include "parameter.h"
26#include "securec.h"
27
28static void FreePathMountNode(SandboxMountNode *node)
29{
30    PathMountNode *sandboxNode = (PathMountNode *)node;
31    if (sandboxNode->source) {
32        free(sandboxNode->source);
33        sandboxNode->source = NULL;
34    }
35    if (sandboxNode->target) {
36        free(sandboxNode->target);
37        sandboxNode->target = NULL;
38    }
39    if (sandboxNode->appAplName) {
40        free(sandboxNode->appAplName);
41        sandboxNode->appAplName = NULL;
42    }
43    free(sandboxNode);
44}
45
46static void FreeSymbolLinkNode(SandboxMountNode *node)
47{
48    SymbolLinkNode *sandboxNode = (SymbolLinkNode *)node;
49    if (sandboxNode->target) {
50        free(sandboxNode->target);
51        sandboxNode->target = NULL;
52    }
53    if (sandboxNode->linkName) {
54        free(sandboxNode->linkName);
55        sandboxNode->linkName = NULL;
56    }
57    free(sandboxNode);
58}
59
60static int SandboxNodeCompareProc(ListNode *node, ListNode *newNode)
61{
62    SandboxMountNode *sandbox1 = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
63    SandboxMountNode *sandbox2 = (SandboxMountNode *)ListEntry(newNode, SandboxMountNode, node);
64    return sandbox1->type - sandbox2->type;
65}
66
67SandboxMountNode *CreateSandboxMountNode(uint32_t dataLen, uint32_t type)
68{
69    APPSPAWN_CHECK(dataLen >= sizeof(SandboxMountNode) && dataLen <= sizeof(PathMountNode),
70        return NULL, "Invalid dataLen %{public}u", dataLen);
71    SandboxMountNode *node = (SandboxMountNode *)calloc(1, dataLen);
72    APPSPAWN_CHECK(node != NULL, return NULL, "Failed to create mount node %{public}u", type);
73    OH_ListInit(&node->node);
74    node->type = type;
75    return node;
76}
77
78void AddSandboxMountNode(SandboxMountNode *node, SandboxSection *queue)
79{
80    APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return);
81    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL, return);
82    OH_ListAddWithOrder(&queue->front, &node->node, SandboxNodeCompareProc);
83}
84
85static int PathMountNodeCompare(ListNode *node, void *data)
86{
87    PathMountNode *node1 = (PathMountNode *)ListEntry(node, SandboxMountNode, node);
88    PathMountNode *node2 = (PathMountNode *)data;
89    return (node1->sandboxNode.type == node2->sandboxNode.type) &&
90        (strcmp(node1->source, node2->source) == 0) &&
91        (strcmp(node1->target, node2->target) == 0) ? 0 : 1;
92}
93
94static int SymbolLinkNodeCompare(ListNode *node, void *data)
95{
96    SymbolLinkNode *node1 = (SymbolLinkNode *)ListEntry(node, SandboxMountNode, node);
97    SymbolLinkNode *node2 = (SymbolLinkNode *)data;
98    return (node1->sandboxNode.type == node2->sandboxNode.type) &&
99        (strcmp(node1->target, node2->target) == 0) &&
100        (strcmp(node1->linkName, node2->linkName) == 0) ? 0 : 1;
101}
102
103PathMountNode *GetPathMountNode(const SandboxSection *section, int type, const char *source, const char *target)
104{
105    APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return NULL);
106    APPSPAWN_CHECK_ONLY_EXPER(source != NULL && target != NULL, return NULL);
107    PathMountNode pathNode = {};
108    pathNode.sandboxNode.type = type;
109    pathNode.source = (char *)source;
110    pathNode.target = (char *)target;
111    ListNode *node = OH_ListFind(&section->front, (void *)&pathNode, PathMountNodeCompare);
112    if (node == NULL) {
113        return NULL;
114    }
115    return (PathMountNode *)ListEntry(node, SandboxMountNode, node);
116}
117
118SymbolLinkNode *GetSymbolLinkNode(const SandboxSection *section, const char *target, const char *linkName)
119{
120    APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return NULL);
121    APPSPAWN_CHECK_ONLY_EXPER(linkName != NULL && target != NULL, return NULL);
122    SymbolLinkNode linkNode = {};
123    linkNode.sandboxNode.type = SANDBOX_TAG_SYMLINK;
124    linkNode.target = (char *)target;
125    linkNode.linkName = (char *)linkName;
126    ListNode *node = OH_ListFind(&section->front, (void *)&linkNode, SymbolLinkNodeCompare);
127    if (node == NULL) {
128        return NULL;
129    }
130    return (SymbolLinkNode *)ListEntry(node, SandboxMountNode, node);
131}
132
133void DeleteSandboxMountNode(SandboxMountNode *sandboxNode)
134{
135    APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return);
136    OH_ListRemove(&sandboxNode->node);
137    OH_ListInit(&sandboxNode->node);
138    switch (sandboxNode->type) {
139        case SANDBOX_TAG_MOUNT_PATH:
140        case SANDBOX_TAG_MOUNT_FILE:
141            FreePathMountNode(sandboxNode);
142            break;
143        case SANDBOX_TAG_SYMLINK:
144            FreeSymbolLinkNode(sandboxNode);
145            break;
146        default:
147            APPSPAWN_LOGE("Invalid type %{public}u", sandboxNode->type);
148            free(sandboxNode);
149            break;
150    }
151}
152
153SandboxMountNode *GetFirstSandboxMountNode(const SandboxSection *section)
154{
155    if (section == NULL || ListEmpty(section->front)) {
156        return NULL;
157    }
158    return (SandboxMountNode *)ListEntry(section->front.next, SandboxMountNode, node);
159}
160
161void DumpSandboxMountNode(const SandboxMountNode *sandboxNode, uint32_t index)
162{
163    APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return);
164    switch (sandboxNode->type) {
165        case SANDBOX_TAG_MOUNT_PATH:
166        case SANDBOX_TAG_MOUNT_FILE: {
167            PathMountNode *pathNode = (PathMountNode *)sandboxNode;
168            APPSPAPWN_DUMP("        ****************************** %{public}u", index);
169            APPSPAPWN_DUMP("        sandbox node source: %{public}s", pathNode->source ? pathNode->source : "null");
170            APPSPAPWN_DUMP("        sandbox node target: %{public}s", pathNode->target ? pathNode->target : "null");
171            DumpMountPathMountNode(pathNode);
172            APPSPAPWN_DUMP("        sandbox node apl: %{public}s",
173                pathNode->appAplName ? pathNode->appAplName : "null");
174            APPSPAPWN_DUMP("        sandbox node checkErrorFlag: %{public}s",
175                pathNode->checkErrorFlag ? "true" : "false");
176            break;
177        }
178        case SANDBOX_TAG_SYMLINK: {
179            SymbolLinkNode *linkNode = (SymbolLinkNode *)sandboxNode;
180            APPSPAPWN_DUMP("        ***********************************");
181            APPSPAPWN_DUMP("        sandbox node target: %{public}s", linkNode->target ? linkNode->target : "null");
182            APPSPAPWN_DUMP("        sandbox node linkName: %{public}s",
183                linkNode->linkName ? linkNode->linkName : "null");
184            APPSPAPWN_DUMP("        sandbox node destMode: %{public}x", linkNode->destMode);
185            APPSPAPWN_DUMP("        sandbox node checkErrorFlag: %{public}s",
186                linkNode->checkErrorFlag ? "true" : "false");
187            break;
188        }
189        default:
190            break;
191    }
192}
193
194static inline void InitSandboxSection(SandboxSection *section, int type)
195{
196    OH_ListInit(&section->front);
197    section->sandboxSwitch = 0;
198    section->sandboxShared = 0;
199    section->number = 0;
200    section->gidCount = 0;
201    section->gidTable = NULL;
202    section->nameGroups = NULL;
203    section->name = NULL;
204    OH_ListInit(&section->sandboxNode.node);
205    section->sandboxNode.type = type;
206}
207
208static void ClearSandboxSection(SandboxSection *section)
209{
210    if (section->gidTable) {
211        free(section->gidTable);
212        section->gidTable = NULL;
213    }
214    // free name group
215    if (section->nameGroups) {
216        free(section->nameGroups);
217        section->nameGroups = NULL;
218    }
219    if (section->name) {
220        free(section->name);
221        section->name = NULL;
222    }
223    if (section->sandboxNode.type == SANDBOX_TAG_NAME_GROUP) {
224        SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section;
225        if (groupNode->depNode) {
226            DeleteSandboxMountNode((SandboxMountNode *)groupNode->depNode);
227        }
228    }
229    // free mount path
230    ListNode *node = section->front.next;
231    while (node != &section->front) {
232        SandboxMountNode *sandboxNode = ListEntry(node, SandboxMountNode, node);
233        // delete node
234        OH_ListRemove(&sandboxNode->node);
235        OH_ListInit(&sandboxNode->node);
236        DeleteSandboxMountNode(sandboxNode);
237        // get next
238        node = section->front.next;
239    }
240}
241
242static void DumpSandboxQueue(const ListNode *front,
243    void (*dumpSandboxMountNode)(const SandboxMountNode *node, uint32_t count))
244{
245    uint32_t count = 0;
246    ListNode *node = front->next;
247    while (node != front) {
248        SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
249        count++;
250        dumpSandboxMountNode(sandboxNode, count);
251        // get next
252        node = node->next;
253    }
254}
255
256static void DumpSandboxSection(const SandboxSection *section)
257{
258    APPSPAPWN_DUMP("    sandboxSwitch %{public}s", section->sandboxSwitch ? "true" : "false");
259    APPSPAPWN_DUMP("    sandboxShared %{public}s", section->sandboxShared ? "true" : "false");
260    APPSPAPWN_DUMP("    gidCount: %{public}u", section->gidCount);
261    for (uint32_t index = 0; index < section->gidCount; index++) {
262        APPSPAPWN_DUMP("        gidTable[%{public}u]: %{public}u", index, section->gidTable[index]);
263    }
264    APPSPAPWN_DUMP("    mount group count: %{public}u", section->number);
265    for (uint32_t i = 0; i < section->number; i++) {
266        if (section->nameGroups[i]) {
267            SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
268            APPSPAPWN_DUMP("        name[%{public}d] %{public}s", i, groupNode->section.name);
269        }
270    }
271    APPSPAPWN_DUMP("    mount-paths: ");
272    DumpSandboxQueue(&section->front, DumpSandboxMountNode);
273}
274
275SandboxSection *CreateSandboxSection(const char *name, uint32_t dataLen, uint32_t type)
276{
277    APPSPAWN_CHECK(type < SANDBOX_TAG_INVALID && type >= SANDBOX_TAG_PERMISSION,
278        return NULL, "Invalid type %{public}u", type);
279    APPSPAWN_CHECK(name != NULL && strlen(name) > 0, return NULL, "Invalid name %{public}u", type);
280    APPSPAWN_CHECK(dataLen >= sizeof(SandboxSection), return NULL, "Invalid dataLen %{public}u", dataLen);
281    APPSPAWN_CHECK(dataLen <= sizeof(SandboxNameGroupNode), return NULL, "Invalid dataLen %{public}u", dataLen);
282    SandboxSection *section = (SandboxSection *)calloc(1, dataLen);
283    APPSPAWN_CHECK(section != NULL, return NULL, "Failed to create base node");
284    InitSandboxSection(section, type);
285    section->name = strdup(name);
286    if (section->name == NULL) {
287        ClearSandboxSection(section);
288        free(section);
289        return NULL;
290    }
291    return section;
292}
293
294static int SandboxConditionalNodeCompareName(ListNode *node, void *data)
295{
296    SandboxSection *tmpNode = (SandboxSection *)ListEntry(node, SandboxMountNode, node);
297    return strcmp(tmpNode->name, (char *)data);
298}
299
300static int SandboxConditionalNodeCompareNode(ListNode *node, ListNode *newNode)
301{
302    SandboxSection *tmpNode = (SandboxSection *)ListEntry(node, SandboxMountNode, node);
303    SandboxSection *tmpNewNode = (SandboxSection *)ListEntry(newNode, SandboxMountNode, node);
304    return strcmp(tmpNode->name, tmpNewNode->name);
305}
306
307SandboxSection *GetSandboxSection(const SandboxQueue *queue, const char *name)
308{
309    APPSPAWN_CHECK_ONLY_EXPER(name != NULL && queue != NULL, return NULL);
310    ListNode *node = OH_ListFind(&queue->front, (void *)name, SandboxConditionalNodeCompareName);
311    if (node == NULL) {
312        return NULL;
313    }
314    return (SandboxSection *)ListEntry(node, SandboxMountNode, node);
315}
316
317void AddSandboxSection(SandboxSection *node, SandboxQueue *queue)
318{
319    APPSPAWN_CHECK_ONLY_EXPER(node != NULL && queue != NULL, return);
320    if (ListEmpty(node->sandboxNode.node)) {
321        OH_ListAddWithOrder(&queue->front, &node->sandboxNode.node, SandboxConditionalNodeCompareNode);
322    }
323}
324
325void DeleteSandboxSection(SandboxSection *section)
326{
327    APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return);
328    // delete node
329    OH_ListRemove(&section->sandboxNode.node);
330    OH_ListInit(&section->sandboxNode.node);
331    ClearSandboxSection(section);
332    free(section);
333}
334
335static void SandboxQueueClear(SandboxQueue *queue)
336{
337    ListNode *node = queue->front.next;
338    while (node != &queue->front) {
339        SandboxSection *sandboxNode = (SandboxSection *)ListEntry(node, SandboxMountNode, node);
340        DeleteSandboxSection(sandboxNode);
341        // get first
342        node = queue->front.next;
343    }
344}
345
346static int AppSpawnExtDataCompareDataId(ListNode *node, void *data)
347{
348    AppSpawnExtData *extData = (AppSpawnExtData *)ListEntry(node, AppSpawnExtData, node);
349    return extData->dataId - *(uint32_t *)data;
350}
351
352AppSpawnSandboxCfg *GetAppSpawnSandbox(const AppSpawnMgr *content, ExtDataType type)
353{
354    APPSPAWN_CHECK_ONLY_EXPER(content != NULL, return NULL);
355    uint32_t dataId = type;
356    ListNode *node = OH_ListFind(&content->extData, (void *)&dataId, AppSpawnExtDataCompareDataId);
357    if (node == NULL) {
358        return NULL;
359    }
360    return (AppSpawnSandboxCfg *)ListEntry(node, AppSpawnSandboxCfg, extData);
361}
362
363void DeleteAppSpawnSandbox(AppSpawnSandboxCfg *sandbox)
364{
365    APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return);
366    APPSPAWN_LOGV("DeleteAppSpawnSandbox");
367    OH_ListRemove(&sandbox->extData.node);
368    OH_ListInit(&sandbox->extData.node);
369
370    // delete all queue
371    SandboxQueueClear(&sandbox->requiredQueue);
372    SandboxQueueClear(&sandbox->permissionQueue);
373    SandboxQueueClear(&sandbox->packageNameQueue);
374    SandboxQueueClear(&sandbox->spawnFlagsQueue);
375    SandboxQueueClear(&sandbox->nameGroupsQueue);
376    if (sandbox->rootPath) {
377        free(sandbox->rootPath);
378    }
379    free(sandbox->depGroupNodes);
380    sandbox->depGroupNodes = NULL;
381    free(sandbox);
382    sandbox = NULL;
383}
384
385static void DumpSandboxPermission(const SandboxMountNode *node, uint32_t index)
386{
387    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)node;
388    APPSPAPWN_DUMP("    ========================================= ");
389    APPSPAPWN_DUMP("    Section %{public}s", permissionNode->section.name);
390    APPSPAPWN_DUMP("    Section permission index %{public}d", permissionNode->permissionIndex);
391    DumpSandboxSection(&permissionNode->section);
392}
393
394static void DumpSandboxSectionNode(const SandboxMountNode *node, uint32_t index)
395{
396    SandboxSection *section = (SandboxSection *)node;
397    APPSPAPWN_DUMP("    ========================================= ");
398    APPSPAPWN_DUMP("    Section %{public}s", section->name);
399    DumpSandboxSection(section);
400}
401
402static void DumpSandboxNameGroupNode(const SandboxMountNode *node, uint32_t index)
403{
404    SandboxNameGroupNode *nameGroupNode = (SandboxNameGroupNode *)node;
405    APPSPAPWN_DUMP("    ========================================= ");
406    APPSPAPWN_DUMP("    Section %{public}s", nameGroupNode->section.name);
407    APPSPAPWN_DUMP("    Section dep mode %{public}s",
408        nameGroupNode->depMode == MOUNT_MODE_ALWAYS ? "always" : "not-exists");
409    if (nameGroupNode->depNode != NULL) {
410        APPSPAPWN_DUMP("    mount-paths-deps: ");
411        DumpMountPathMountNode(nameGroupNode->depNode);
412    }
413    DumpSandboxSection(&nameGroupNode->section);
414}
415
416
417static void DumpSandbox(struct TagAppSpawnExtData *data)
418{
419    AppSpawnSandboxCfg *sandbox = (AppSpawnSandboxCfg *)data;
420    DumpAppSpawnSandboxCfg(sandbox);
421}
422
423static inline void InitSandboxQueue(SandboxQueue *queue, uint32_t type)
424{
425    OH_ListInit(&queue->front);
426    queue->type = type;
427}
428
429static void FreeAppSpawnSandbox(struct TagAppSpawnExtData *data)
430{
431    AppSpawnSandboxCfg *sandbox = ListEntry(data, AppSpawnSandboxCfg, extData);
432    // delete all var
433    DeleteAppSpawnSandbox(sandbox);
434}
435
436AppSpawnSandboxCfg *CreateAppSpawnSandbox(ExtDataType type)
437{
438    // create sandbox
439    AppSpawnSandboxCfg *sandbox = (AppSpawnSandboxCfg *)calloc(1, sizeof(AppSpawnSandboxCfg));
440    APPSPAWN_CHECK(sandbox != NULL, return NULL, "Failed to create sandbox");
441
442    // ext data init
443    OH_ListInit(&sandbox->extData.node);
444    sandbox->extData.dataId = type;
445    sandbox->extData.freeNode = FreeAppSpawnSandbox;
446    sandbox->extData.dumpNode = DumpSandbox;
447
448    // queue
449    InitSandboxQueue(&sandbox->requiredQueue, SANDBOX_TAG_REQUIRED);
450    InitSandboxQueue(&sandbox->permissionQueue, SANDBOX_TAG_PERMISSION);
451    InitSandboxQueue(&sandbox->packageNameQueue, SANDBOX_TAG_PACKAGE_NAME);
452    InitSandboxQueue(&sandbox->spawnFlagsQueue, SANDBOX_TAG_SPAWN_FLAGS);
453    InitSandboxQueue(&sandbox->nameGroupsQueue, SANDBOX_TAG_NAME_GROUP);
454
455    sandbox->topSandboxSwitch = 0;
456    sandbox->appFullMountEnable = 0;
457    sandbox->topSandboxSwitch = 0;
458    sandbox->pidNamespaceSupport = 0;
459    sandbox->sandboxNsFlags = 0;
460    sandbox->maxPermissionIndex = -1;
461    sandbox->depNodeCount = 0;
462    sandbox->depGroupNodes = NULL;
463
464    AddDefaultVariable();
465    AddDefaultExpandAppSandboxConfigHandle();
466    return sandbox;
467}
468
469void DumpAppSpawnSandboxCfg(AppSpawnSandboxCfg *sandbox)
470{
471    APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return);
472    APPSPAPWN_DUMP("Sandbox root path: %{public}s", sandbox->rootPath);
473    APPSPAPWN_DUMP("Sandbox sandboxNsFlags: %{public}x ", sandbox->sandboxNsFlags);
474    APPSPAPWN_DUMP("Sandbox topSandboxSwitch: %{public}s", sandbox->topSandboxSwitch ? "true" : "false");
475    APPSPAPWN_DUMP("Sandbox appFullMountEnable: %{public}s", sandbox->appFullMountEnable ? "true" : "false");
476    APPSPAPWN_DUMP("Sandbox pidNamespaceSupport: %{public}s", sandbox->pidNamespaceSupport ? "true" : "false");
477    APPSPAPWN_DUMP("Sandbox common info: ");
478    DumpSandboxQueue(&sandbox->requiredQueue.front, DumpSandboxSectionNode);
479    DumpSandboxQueue(&sandbox->packageNameQueue.front, DumpSandboxSectionNode);
480    DumpSandboxQueue(&sandbox->permissionQueue.front, DumpSandboxPermission);
481    DumpSandboxQueue(&sandbox->spawnFlagsQueue.front, DumpSandboxSectionNode);
482    DumpSandboxQueue(&sandbox->nameGroupsQueue.front, DumpSandboxNameGroupNode);
483}
484
485APPSPAWN_STATIC int PreLoadIsoLatedSandboxCfg(AppSpawnMgr *content)
486{
487    if (IsNWebSpawnMode(content)) {
488        return 0;
489    }
490
491    AppSpawnSandboxCfg *sandbox = GetAppSpawnSandbox(content, EXT_DATA_ISOLATED_SANDBOX);
492    APPSPAWN_CHECK(sandbox == NULL, return 0, "Isolated sandbox has been load");
493
494    sandbox = CreateAppSpawnSandbox(EXT_DATA_ISOLATED_SANDBOX);
495    APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_SYSTEM_ERROR);
496    OH_ListAddTail(&content->extData, &sandbox->extData.node);
497
498    // load app sandbox config
499    LoadAppSandboxConfig(sandbox, MODE_FOR_NATIVE_SPAWN);
500    sandbox->maxPermissionIndex = PermissionRenumber(&sandbox->permissionQueue);
501
502    content->content.sandboxNsFlags = 0;
503    if (sandbox->pidNamespaceSupport) {
504        content->content.sandboxNsFlags = sandbox->sandboxNsFlags;
505    }
506    return 0;
507}
508
509APPSPAWN_STATIC int PreLoadSandboxCfg(AppSpawnMgr *content)
510{
511    AppSpawnSandboxCfg *sandbox = GetAppSpawnSandbox(content, EXT_DATA_SANDBOX);
512    APPSPAWN_CHECK(sandbox == NULL, return 0, "Sandbox has been load");
513
514    sandbox = CreateAppSpawnSandbox(EXT_DATA_SANDBOX);
515    APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_SYSTEM_ERROR);
516    OH_ListAddTail(&content->extData, &sandbox->extData.node);
517
518    // load app sandbox config
519    LoadAppSandboxConfig(sandbox, content->content.mode);
520    sandbox->maxPermissionIndex = PermissionRenumber(&sandbox->permissionQueue);
521
522    content->content.sandboxNsFlags = 0;
523    if (IsNWebSpawnMode(content) || sandbox->pidNamespaceSupport) {
524        content->content.sandboxNsFlags = sandbox->sandboxNsFlags;
525    }
526    return 0;
527}
528
529APPSPAWN_STATIC int IsolatedSandboxHandleServerExit(AppSpawnMgr *content)
530{
531    AppSpawnSandboxCfg *sandbox = GetAppSpawnSandbox(content, EXT_DATA_ISOLATED_SANDBOX);
532    APPSPAWN_CHECK(sandbox != NULL, return 0, "Isolated sandbox not load");
533
534    return 0;
535}
536
537APPSPAWN_STATIC int SandboxHandleServerExit(AppSpawnMgr *content)
538{
539    AppSpawnSandboxCfg *sandbox = GetAppSpawnSandbox(content, EXT_DATA_SANDBOX);
540    APPSPAWN_CHECK(sandbox != NULL, return 0, "Sandbox not load");
541
542    return 0;
543}
544
545int SpawnBuildSandboxEnv(AppSpawnMgr *content, AppSpawningCtx *property)
546{
547    ExtDataType type = CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? EXT_DATA_ISOLATED_SANDBOX :
548        EXT_DATA_SANDBOX;
549    AppSpawnSandboxCfg *appSandbox = GetAppSpawnSandbox(content, type);
550    APPSPAWN_CHECK(appSandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
551    // no sandbox
552    if (CheckAppMsgFlagsSet(property, APP_FLAGS_NO_SANDBOX)) {
553        return 0;
554    }
555    // CLONE_NEWPID 0x20000000
556    // CLONE_NEWNET 0x40000000
557    if ((content->content.sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID) {
558        int ret = getprocpid();
559        if (ret < 0) {
560            return ret;
561        }
562    }
563    int ret = MountSandboxConfigs(appSandbox, property, IsNWebSpawnMode(content));
564    appSandbox->mounted = 1;
565    // for module test do not create sandbox, use APP_FLAGS_IGNORE_SANDBOX to ignore sandbox result
566    if (CheckAppMsgFlagsSet(property, APP_FLAGS_IGNORE_SANDBOX)) {
567        APPSPAWN_LOGW("Do not care sandbox result %{public}d", ret);
568        return 0;
569    }
570    return ret == 0 ? 0 : APPSPAWN_SANDBOX_MOUNT_FAIL;
571}
572
573static int AppendPermissionGid(const AppSpawnSandboxCfg *sandbox, AppSpawningCtx *property)
574{
575    AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
576    APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
577        "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property));
578
579    APPSPAWN_LOGV("AppendPermissionGid %{public}s", GetProcessName(property));
580    ListNode *node = sandbox->permissionQueue.front.next;
581    while (node != &sandbox->permissionQueue.front) {
582        SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
583        if (!CheckAppPermissionFlagSet(property, (uint32_t)permissionNode->permissionIndex)) {
584            node = node->next;
585            continue;
586        }
587        if (permissionNode->section.gidCount == 0) {
588            node = node->next;
589            continue;
590        }
591        APPSPAWN_LOGV("Add permission %{public}s gid %{public}d to %{public}s",
592            permissionNode->section.name, permissionNode->section.gidTable[0], GetProcessName(property));
593
594        size_t copyLen = permissionNode->section.gidCount;
595        if ((permissionNode->section.gidCount + dacInfo->gidCount) > APP_MAX_GIDS) {
596            APPSPAWN_LOGW("More gid for %{public}s msg count %{public}u permission %{public}u",
597                GetProcessName(property), dacInfo->gidCount, permissionNode->section.gidCount);
598            copyLen = APP_MAX_GIDS - dacInfo->gidCount;
599        }
600        int ret = memcpy_s(&dacInfo->gidTable[dacInfo->gidCount], sizeof(gid_t) * copyLen,
601            permissionNode->section.gidTable, sizeof(gid_t) * copyLen);
602        if (ret != EOK) {
603            APPSPAWN_LOGW("Failed to append permission %{public}s gid to %{public}s",
604                permissionNode->section.name, GetProcessName(property));
605            node = node->next;
606            continue;
607        }
608        dacInfo->gidCount += copyLen;
609        node = node->next;
610    }
611    return 0;
612}
613
614static int AppendPackageNameGids(const AppSpawnSandboxCfg *sandbox, AppSpawningCtx *property)
615{
616    AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
617    APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
618        "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property));
619
620    SandboxPackageNameNode *sandboxNode =
621        (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, GetProcessName(property));
622    if (sandboxNode == NULL || sandboxNode->section.gidCount == 0) {
623        return 0;
624    }
625
626    size_t copyLen = sandboxNode->section.gidCount;
627    if ((sandboxNode->section.gidCount + dacInfo->gidCount) > APP_MAX_GIDS) {
628        APPSPAWN_LOGW("More gid for %{public}s msg count %{public}u permission %{public}u",
629                      GetProcessName(property),
630                      dacInfo->gidCount,
631                      sandboxNode->section.gidCount);
632        copyLen = APP_MAX_GIDS - dacInfo->gidCount;
633    }
634    int ret = memcpy_s(&dacInfo->gidTable[dacInfo->gidCount], sizeof(gid_t) * copyLen,
635                       sandboxNode->section.gidTable, sizeof(gid_t) * copyLen);
636    if (ret != EOK) {
637        APPSPAWN_LOGW("Failed to append permission %{public}s gid to %{public}s",
638                      sandboxNode->section.name,
639                      GetProcessName(property));
640    }
641    dacInfo->gidCount += copyLen;
642
643    return 0;
644}
645
646int SpawnPrepareSandboxCfg(AppSpawnMgr *content, AppSpawningCtx *property)
647{
648    APPSPAWN_CHECK_ONLY_EXPER(content != NULL, return -1);
649    APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
650    APPSPAWN_LOGV("Prepare sandbox config %{public}s", GetProcessName(property));
651    ExtDataType type = CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? EXT_DATA_ISOLATED_SANDBOX :
652        EXT_DATA_SANDBOX;
653    AppSpawnSandboxCfg *sandbox = GetAppSpawnSandbox(content, type);
654    APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
655
656    int32_t index = 0;
657    if (sandbox->appFullMountEnable) {
658        index = GetPermissionIndexInQueue(&sandbox->permissionQueue, FILE_CROSS_APP_MODE);
659    } else {
660        index = GetPermissionIndexInQueue(&sandbox->permissionQueue, FILE_ACCESS_COMMON_DIR_MODE);
661    }
662
663    int32_t fileMgrIndex = GetPermissionIndexInQueue(&sandbox->permissionQueue, FILE_ACCESS_MANAGER_MODE);
664    if (index > 0 && (CheckAppMsgFlagsSet(property, (uint32_t)fileMgrIndex) == 0)) {
665        if (SetAppPermissionFlags(property, index) != 0) {
666            return -1;
667        }
668    }
669
670    int ret = AppendPermissionGid(sandbox, property);
671    APPSPAWN_CHECK(ret == 0, return ret, "Failed to add gid for %{public}s", GetProcessName(property));
672    ret = AppendPackageNameGids(sandbox, property);
673    APPSPAWN_CHECK(ret == 0, return ret, "Failed to add gid for %{public}s", GetProcessName(property));
674    ret = StagedMountSystemConst(sandbox, property, IsNWebSpawnMode(content));
675    APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount system-const for %{public}s", GetProcessName(property));
676    return 0;
677}
678
679APPSPAWN_STATIC int SandboxUnmountPath(const AppSpawnMgr *content, const AppSpawnedProcessInfo *appInfo)
680{
681    APPSPAWN_CHECK_ONLY_EXPER(content != NULL, return -1);
682    APPSPAWN_CHECK_ONLY_EXPER(appInfo != NULL, return -1);
683    AppSpawnSandboxCfg *sandbox = NULL;
684    APPSPAWN_LOGV("Sandbox process %{public}s %{public}u exit", appInfo->name, appInfo->uid);
685    if (content->content.mode == MODE_FOR_NATIVE_SPAWN) {
686        sandbox = GetAppSpawnSandbox(content, EXT_DATA_ISOLATED_SANDBOX);
687    } else {
688        sandbox = GetAppSpawnSandbox(content, EXT_DATA_SANDBOX);
689    }
690    return UnmountDepPaths(sandbox, appInfo->uid);
691}
692
693#ifdef APPSPAWN_SANDBOX_NEW
694MODULE_CONSTRUCTOR(void)
695{
696    APPSPAWN_LOGV("Load sandbox module ...");
697    (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX, PreLoadSandboxCfg);
698    (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX, PreLoadIsoLatedSandboxCfg);
699    (void)AddServerStageHook(STAGE_SERVER_EXIT, HOOK_PRIO_SANDBOX, SandboxHandleServerExit);
700    (void)AddServerStageHook(STAGE_SERVER_EXIT, HOOK_PRIO_SANDBOX, IsolatedSandboxHandleServerExit);
701    (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_SANDBOX, SpawnPrepareSandboxCfg);
702    (void)AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_SANDBOX, SpawnBuildSandboxEnv);
703    (void)AddProcessMgrHook(STAGE_SERVER_APP_DIED, 0, SandboxUnmountPath);
704}
705
706MODULE_DESTRUCTOR(void)
707{
708    ClearVariable();
709    ClearExpandAppSandboxConfigHandle();
710}
711#endif
712