xref: /base/startup/init/services/sandbox/sandbox.c (revision d9f0492f)
1/*
2* Copyright (c) 2022 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 "sandbox.h"
17
18#include <limits.h>
19#include <string.h>
20#include <unistd.h>
21#include <sched.h>
22#include <sys/mount.h>
23#include <sys/stat.h>
24#include <sys/syscall.h>
25#include <errno.h>
26#include "beget_ext.h"
27#include "config_policy_utils.h"
28#include "init_utils.h"
29#include "cJSON.h"
30#include "list.h"
31#include "sandbox_namespace.h"
32#include "securec.h"
33
34#define SANDBOX_ROOT_TAG "sandbox-root"
35#define SANDBOX_MOUNT_PATH_TAG "mount-bind-paths"
36#define SANDBOX_MOUNT_FILE_TAG "mount-bind-files"
37#define SANDBOX_SOURCE "src-path"
38#define SANDBOX_TARGET "sandbox-path"
39#define SANDBOX_FLAGS "sandbox-flags"
40#define SANDBOX_IGNORE_ERRORS "ignore"
41#define SANDBOX_SYMLINK_TAG "symbol-links"
42#define SANDBOX_SYMLINK_TARGET "target-name"
43#define SANDBOX_SYMLINK_NAME "link-name"
44
45#define SANDBOX_SYSTEM_CONFIG_FILE "etc/sandbox/system-sandbox.json"
46#define SANDBOX_CHIPSET_CONFIG_FILE "etc/sandbox/chipset-sandbox.json"
47
48#ifdef STARTUP_INIT_TEST
49#define SANDBOX_TEST_CONFIG_FILE "/data/init_ut/test-sandbox.json"
50#endif
51
52#define SANDBOX_MOUNT_FLAGS_MS_BIND "bind"
53#define SANDBOX_MOUNT_FLAGS_MS_PRIVATE "private"
54#define SANDBOX_MOUNT_FLAGS_MS_REC "rec"
55#define SANDBOX_MOUNT_FLAGS_MS_MOVE "move"
56
57struct SandboxMountFlags {
58    const char *flag;
59    unsigned long value;
60};
61
62static const struct SandboxMountFlags FLAGS[] = {
63    {
64        .flag = "bind",
65        .value = MS_BIND,
66    },
67    {
68        .flag = "private",
69        .value = MS_PRIVATE,
70    },
71    {
72        .flag = "rec",
73        .value = MS_REC,
74    },
75    {
76        .flag = "move",
77        .value = MS_MOVE,
78    }
79};
80
81static sandbox_t g_systemSandbox = {};
82static sandbox_t g_chipsetSandbox = {};
83#ifdef STARTUP_INIT_TEST
84static sandbox_t g_testSandbox = {};
85#endif
86
87struct SandboxMap {
88    const char *name;
89    sandbox_t *sandbox;
90    const char *configfile;
91};
92
93static const struct SandboxMap MAP[] = {
94    {
95        .name = "system",
96        .sandbox = &g_systemSandbox,
97        .configfile = SANDBOX_SYSTEM_CONFIG_FILE,
98    },
99    {
100        .name = "chipset",
101        .sandbox = &g_chipsetSandbox,
102        .configfile = SANDBOX_CHIPSET_CONFIG_FILE,
103    },
104#ifdef STARTUP_INIT_TEST
105    {
106        .name = "test",
107        .sandbox = &g_testSandbox,
108        .configfile = SANDBOX_TEST_CONFIG_FILE,
109    }
110#endif
111};
112
113static unsigned long GetSandboxMountFlags(cJSON *item)
114{
115    BEGET_ERROR_CHECK(item != NULL, return 0, "Invalid parameter.");
116    char *str = cJSON_GetStringValue(item);
117    BEGET_CHECK(str != NULL, return 0);
118    for (size_t i = 0; i < ARRAY_LENGTH(FLAGS); i++) {
119        if (strcmp(str, FLAGS[i].flag) == 0) {
120            return FLAGS[i].value;
121        }
122    }
123    return 0;
124}
125
126static void FreeSandboxMountInfo(ListNode *list)
127{
128    if (list == NULL) {
129        return;
130    }
131    mountlist_t *info = ListEntry(list, mountlist_t, node);
132    if (info == NULL) {
133        return;
134    }
135    if (info->source != NULL) {
136        free(info->source);
137        info->source = NULL;
138    }
139    if (info->target != NULL) {
140        free(info->target);
141        info->target = NULL;
142    }
143    free(info);
144    info = NULL;
145    return;
146}
147
148static void FreeSandboxLinkInfo(ListNode *list)
149{
150    if (list == NULL) {
151        return;
152    }
153    linklist_t *info = ListEntry(list, linklist_t, node);
154    if (info == NULL) {
155        return;
156    }
157    if (info->target != NULL) {
158        free(info->target);
159        info->target = NULL;
160    }
161    if (info->linkName != NULL) {
162        free(info->linkName);
163        info->linkName = NULL;
164    }
165    free(info);
166    info = NULL;
167    return;
168}
169
170static int CompareSandboxListForMountTarget(ListNode *list, void *data)
171{
172    if ((list == NULL) || (data == NULL)) {
173        return -1;
174    }
175    mountlist_t *info = ListEntry(list, mountlist_t, node);
176    if (info == NULL) {
177        return -1;
178    }
179    const char *mountTarget = (const char *)data;
180    return strcmp(info->target, mountTarget);
181}
182
183static void RemoveOldSandboxMountListNode(ListNode *head, const char *targetMount)
184{
185    if ((head == NULL) || (targetMount == NULL)) {
186        return;
187    }
188    ListNode *node = OH_ListFind(head, (void *)targetMount, CompareSandboxListForMountTarget);
189    if (node == NULL) {
190        return;
191    }
192    OH_ListRemove(node);
193    FreeSandboxMountInfo(node);
194}
195
196static int CompareSandboxListForLinkName(ListNode *list, void *data)
197{
198    if ((list == NULL) || (data == NULL)) {
199        return -1;
200    }
201    linklist_t *info = ListEntry(list, linklist_t, node);
202    if (info == NULL) {
203        return -1;
204    }
205    const char *linkName = (const char *)data;
206    return strcmp(info->linkName, linkName);
207}
208
209static void RemoveOldSandboxLinkListNode(ListNode *head, const char *linkName)
210{
211    if ((head == NULL) || (linkName == NULL)) {
212        return;
213    }
214    ListNode *node = OH_ListFind(head, (void *)linkName, CompareSandboxListForLinkName);
215    if (node == NULL) {
216        return;
217    }
218    OH_ListRemove(node);
219    FreeSandboxLinkInfo(node);
220}
221
222typedef int (*AddInfoToSandboxCallback)(sandbox_t *sandbox, cJSON *item, const char *type);
223
224static int AddMountInfoToSandbox(sandbox_t *sandbox, cJSON *item, const char *type)
225{
226    BEGET_CHECK(sandbox != NULL && item != NULL && type != NULL, return -1);
227    char *srcPath = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SOURCE));
228    BEGET_INFO_CHECK(srcPath != NULL, return 0, "Get src-path is null");
229    char *dstPath = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_TARGET));
230    BEGET_INFO_CHECK(dstPath != NULL, return 0, "Get sandbox-path is null");
231    cJSON *obj = cJSON_GetObjectItem(item, SANDBOX_FLAGS);
232    BEGET_INFO_CHECK(obj != NULL, return 0, "Get sandbox-flags is null");
233    int ret = cJSON_IsArray(obj);
234    BEGET_INFO_CHECK(ret, return 0, "Sandbox-flags is not array");
235    int count = cJSON_GetArraySize(obj);
236    BEGET_INFO_CHECK(count > 0, return 0, "Get sandbox-flags array size is zero");
237    mountlist_t *tmpMount = (mountlist_t *)calloc(1, sizeof(mountlist_t));
238    BEGET_ERROR_CHECK(tmpMount != NULL, return -1, "Failed calloc err=%d", errno);
239    tmpMount->source = strdup(srcPath);
240    BEGET_ERROR_CHECK(tmpMount->source != NULL, free(tmpMount); return -1, "Failed to dup source");
241    tmpMount->target = strdup(dstPath);
242    BEGET_ERROR_CHECK(tmpMount->target != NULL, free(tmpMount); return -1, "Failed to dup target");
243    for (int i = 0; i < count; i++) {
244        cJSON *item = cJSON_GetArrayItem(obj, i);
245        tmpMount->flags |= GetSandboxMountFlags(item);
246    }
247    tmpMount->ignoreErrors = false;
248    obj = cJSON_GetObjectItem(item, SANDBOX_IGNORE_ERRORS);
249    if (obj != NULL) {
250        if (cJSON_GetNumberValue(obj) == 1) {
251            tmpMount->ignoreErrors = true;
252        }
253    }
254    OH_ListInit(&tmpMount->node);
255    if (strcmp(type, SANDBOX_MOUNT_PATH_TAG) == 0) {
256        tmpMount->tag = SANDBOX_TAG_MOUNT_PATH;
257        RemoveOldSandboxMountListNode(&sandbox->pathMountsHead, dstPath);
258        OH_ListAddTail(&sandbox->pathMountsHead, &tmpMount->node);
259    } else if (strcmp(type, SANDBOX_MOUNT_FILE_TAG) == 0) {
260        tmpMount->tag = SANDBOX_TAG_MOUNT_FILE;
261        RemoveOldSandboxMountListNode(&sandbox->fileMountsHead, dstPath);
262        OH_ListAddTail(&sandbox->fileMountsHead, &tmpMount->node);
263    }
264    return 0;
265}
266
267static int AddSymbolLinksToSandbox(sandbox_t *sandbox, cJSON *item, const char *type)
268{
269    BEGET_CHECK(!(sandbox == NULL || item == NULL || type == NULL), return -1);
270    BEGET_ERROR_CHECK(strcmp(type, SANDBOX_SYMLINK_TAG) == 0, return -1, "Type is not sandbox symbolLink.");
271    char *target = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_TARGET));
272    BEGET_ERROR_CHECK(target != NULL, return 0, "Get target-name is null");
273    char *name = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_NAME));
274    BEGET_ERROR_CHECK(name != NULL, return 0, "Get link-name is null");
275    linklist_t *tmpLink = (linklist_t *)calloc(1, sizeof(linklist_t));
276    BEGET_ERROR_CHECK(tmpLink != NULL, return -1, "Failed calloc err=%d", errno);
277    tmpLink->target = strdup(target);
278    BEGET_ERROR_CHECK(tmpLink->target != NULL, free(tmpLink); return -1, "Failed to dup target");
279    tmpLink->linkName = strdup(name);
280    BEGET_ERROR_CHECK(tmpLink->linkName != NULL, free(tmpLink); return -1, "Failed to dup linkName");
281    OH_ListInit(&tmpLink->node);
282    RemoveOldSandboxLinkListNode(&sandbox->linksHead, tmpLink->linkName);
283    OH_ListAddTail(&sandbox->linksHead, &tmpLink->node);
284    return 0;
285}
286
287static int GetSandboxInfo(sandbox_t *sandbox, cJSON *root, const char *itemName)
288{
289    BEGET_ERROR_CHECK(!(sandbox == NULL || root == NULL || itemName == NULL), return -1,
290        "Get sandbox mount info with invalid argument");
291    cJSON *obj = cJSON_GetObjectItem(root, itemName);
292    BEGET_WARNING_CHECK(obj != NULL, return 0, "Cannot find item \' %s \' in sandbox config", itemName);
293    BEGET_WARNING_CHECK(cJSON_IsArray(obj), return 0, "ItemName %s with invalid type, should be array", itemName);
294
295    int counts = cJSON_GetArraySize(obj);
296    BEGET_WARNING_CHECK(counts > 0, return 0, "Item %s array size is zero.", itemName);
297    AddInfoToSandboxCallback func = NULL;
298    if (strcmp(itemName, SANDBOX_MOUNT_PATH_TAG) == 0) {
299        func = AddMountInfoToSandbox;
300    } else if (strcmp(itemName, SANDBOX_MOUNT_FILE_TAG) == 0) {
301        func = AddMountInfoToSandbox;
302    } else if (strcmp(itemName, SANDBOX_SYMLINK_TAG) == 0) {
303        func = AddSymbolLinksToSandbox;
304    } else {
305        BEGET_LOGE("Item %s is not support.", itemName);
306        return -1;
307    }
308    for (int i = 0; i < counts; i++) {
309        cJSON *item = cJSON_GetArrayItem(obj, i);
310        BEGET_ERROR_CHECK(item != NULL, return -1, "Failed get json array item %d", i);
311        BEGET_ERROR_CHECK(func(sandbox, item, itemName) == 0, return -1, "Failed add info to sandbox.");
312    }
313    return 0;
314}
315
316static int ParseSandboxConfig(cJSON *root, sandbox_t *sandbox)
317{
318    BEGET_ERROR_CHECK(!(root == NULL || sandbox == NULL), return -1, "Invalid parameter.");
319    // sandbox rootpath must initialize according to the system configuration, and it can only be initialized once.
320    if (sandbox->rootPath == NULL) {
321        cJSON *sandboxRoot = cJSON_GetObjectItem(root, SANDBOX_ROOT_TAG);
322        BEGET_ERROR_CHECK(sandboxRoot != NULL, return -1,
323            "Cannot find item \' %s \' in sandbox config", SANDBOX_ROOT_TAG);
324
325        char *rootdir = cJSON_GetStringValue(sandboxRoot);
326        if (rootdir != NULL) {
327            sandbox->rootPath = strdup(rootdir);
328            BEGET_ERROR_CHECK(sandbox->rootPath != NULL, return -1,
329                "Get sandbox root path out of memory");
330        }
331    }
332    BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_PATH_TAG) == 0, return -1,
333        "config info %s error", SANDBOX_MOUNT_PATH_TAG);
334    BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_FILE_TAG) == 0, return -1,
335        "config info %s error", SANDBOX_MOUNT_FILE_TAG);
336    BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_SYMLINK_TAG) == 0, return -1,
337        "config info %s error", SANDBOX_SYMLINK_TAG);
338    return 0;
339}
340
341static const struct SandboxMap *GetSandboxMapByName(const char *name)
342{
343    BEGET_ERROR_CHECK(name != NULL, return NULL, "Sandbox map name is NULL.");
344    int len = ARRAY_LENGTH(MAP);
345    for (int i = 0; i < len; i++) {
346        if (strcmp(MAP[i].name, name) == 0) {
347            return &MAP[i];
348        }
349    }
350    return NULL;
351}
352
353static int ParseInitSandboxConfigFile(sandbox_t *sandbox, const char *sandboxConfigFile, const char *name)
354{
355    char *contents = ReadFileToBuf(sandboxConfigFile);
356    if (contents == NULL) {
357        return 0;
358    }
359    cJSON *root = cJSON_Parse(contents);
360    free(contents);
361    BEGET_ERROR_CHECK(root != NULL, return -1, "Parse sandbox config \' %s \' failed", sandboxConfigFile);
362    int ret = ParseSandboxConfig(root, sandbox);
363    cJSON_Delete(root);
364    if (ret < 0) {
365        DestroySandbox(name);
366        return -1;
367    }
368    return 0;
369}
370
371static void ParseInitSandboxConfigPath(sandbox_t *sandbox, const char *sandboxConfig, const char *name)
372{
373    CfgFiles *files = GetCfgFiles(sandboxConfig);
374    for (int i = 0; files && i < MAX_CFG_POLICY_DIRS_CNT; i++) {
375        if (files->paths[i]) {
376            BEGET_LOGI("Parse sandbox cfg file is %s", files->paths[i]);
377            if (ParseInitSandboxConfigFile(sandbox, files->paths[i], name) < 0) {
378                break;
379            }
380        }
381    }
382    FreeCfgFiles(files);
383}
384
385static void InitSandbox(sandbox_t *sandbox, const char *sandboxConfig, const char *name)
386{
387    BEGET_ERROR_CHECK(!(sandbox == NULL || sandboxConfig == NULL || name == NULL), return,
388        "Init sandbox with invalid arguments");
389    if (sandbox->isCreated) {
390        BEGET_LOGE("Sandbox %s has created.", name);
391        return;
392    }
393    if (UnshareNamespace(CLONE_NEWNS) < 0) {
394        return;
395    }
396    sandbox->ns = GetNamespaceFd("/proc/self/ns/mnt");
397    BEGET_ERROR_CHECK(!(sandbox->ns < 0), return, "Get sandbox namespace fd is failed");
398
399    BEGET_ERROR_CHECK(strcpy_s(sandbox->name, MAX_BUFFER_LEN - 1, name) == 0, return, "Failed to copy sandbox name");
400    OH_ListInit(&sandbox->pathMountsHead);
401    OH_ListInit(&sandbox->fileMountsHead);
402    OH_ListInit(&sandbox->linksHead);
403    // parse json config
404#ifdef STARTUP_INIT_TEST
405    (void)ParseInitSandboxConfigFile(sandbox, sandboxConfig, name);
406#else
407    ParseInitSandboxConfigPath(sandbox, sandboxConfig, name);
408#endif
409    return;
410}
411
412static int CheckAndMakeDir(const char *dir, mode_t mode)
413{
414    struct stat sb;
415
416    if ((stat(dir, &sb) == 0) && S_ISDIR(sb.st_mode)) {
417        BEGET_LOGI("Mount point \' %s \' already exist, no need to mkdir", dir);
418        return 0;
419    } else {
420        if (errno == ENOENT) {
421            BEGET_ERROR_CHECK(MakeDirRecursive(dir, mode) == 0, return -1,
422                "Failed MakeDirRecursive %s, err=%d", dir, errno);
423        } else {
424            BEGET_LOGW("Failed to access mount point \' %s \', err = %d", dir, errno);
425            return -1;
426        }
427    }
428    return 0;
429}
430
431static int BindMount(const char *source, const char *target, unsigned long flags, SandboxTag tag)
432{
433    if (source == NULL || target == NULL) {
434        BEGET_LOGE("Mount with invalid arguments");
435        errno = EINVAL;
436        return -1;
437    }
438    unsigned long tmpflags = flags;
439    mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
440    if (tag == SANDBOX_TAG_MOUNT_PATH) {
441        BEGET_ERROR_CHECK(CheckAndMakeDir(target, mode) == 0, return -1, "Failed make %s dir.", target);
442    } else if (tag == SANDBOX_TAG_MOUNT_FILE) {
443        BEGET_ERROR_CHECK(CheckAndCreatFile(target, mode) == 0, return -1, "Failed make %s file.", target);
444    } else {
445        BEGET_LOGE("Tag is error.");
446        return -1;
447    }
448
449    BEGET_WARNING_CHECK((tmpflags & MS_BIND) != 0, tmpflags |= MS_BIND,
450        "Not configure mount bind, must configure mount bind flag.");
451
452    // do mount
453    if (mount(source, target, NULL, tmpflags, NULL) != 0) {
454        BEGET_LOGE("Failed to bind mount \' %s \' to \' %s \', err = %d", source, target, errno);
455        if (errno != ENOTDIR) {  // mount errno is 'Not a directory' can ignore
456            return -1;
457        }
458    }
459
460    return 0;
461}
462
463static bool IsValidSandbox(sandbox_t *sandbox)
464{
465    BEGET_ERROR_CHECK(sandbox != NULL, return false, "preparing sandbox with invalid argument");
466
467    if (sandbox->rootPath == NULL) {
468        return false;
469    }
470
471    return true;
472}
473
474static int MountSandboxNode(ListNode *list, void *data)
475{
476    if ((list == NULL) || (data == NULL)) {
477        return 0;
478    }
479    const char *rootPath = (const char *)data;
480    mountlist_t *info = ListEntry(list, mountlist_t, node);
481    char target[PATH_MAX] = {};
482    BEGET_ERROR_CHECK(snprintf_s(target, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->target) > 0,
483        return -1, "Failed snprintf_s err=%d", errno);
484    int rc = BindMount(info->source, target, info->flags, info->tag);
485    if (rc != 0) {
486        BEGET_LOGW("Failed bind mount %s to %s.", info->source, target);
487        if (info->ignoreErrors == false) {
488            return -1;
489        }
490    }
491    return 0;
492}
493
494static int MountSandboxInfo(struct ListNode *head, const char *rootPath, SandboxTag tag)
495{
496    if ((head == NULL) || (rootPath == NULL)) {
497        return 0;
498    }
499    int ret = OH_ListTraversal(head, (void *)rootPath, MountSandboxNode, 1);
500    return ret;
501}
502
503static int LinkSandboxNode(ListNode *list, void *data)
504{
505    if ((list == NULL) || (data == NULL)) {
506        return 0;
507    }
508    const char *rootPath = (const char *)data;
509    linklist_t *info = ListEntry(list, linklist_t, node);
510    char linkName[PATH_MAX] = {0};
511    BEGET_ERROR_CHECK(!(snprintf_s(linkName, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->linkName) < 0),
512        return -1, "snprintf_s failed, err=%d", errno);
513    int rc = symlink(info->target, linkName);
514    if (rc != 0) {
515        if (errno == EEXIST) {
516            BEGET_LOGW("symbol link name \' %s \' already exist", linkName);
517        } else {
518            BEGET_LOGE("Failed to link \' %s \' to \' %s \', err = %d", info->target, linkName, errno);
519            return -1;
520        }
521    }
522    return 0;
523}
524
525static int LinkSandboxInfo(struct ListNode *head, const char *rootPath)
526{
527    if ((head == NULL) || (rootPath == NULL)) {
528        return 0;
529    }
530    int ret = OH_ListTraversal(head, (void *)rootPath, LinkSandboxNode, 1);
531    return ret;
532}
533
534int PrepareSandbox(const char *name)
535{
536    BEGET_ERROR_CHECK(name != NULL, return -1, "Prepare sandbox name is NULL.");
537    BEGET_ERROR_CHECK(getuid() == 0, return -1, "Current process uid is not root, exit.");
538    const struct SandboxMap *map = GetSandboxMapByName(name);
539    BEGET_ERROR_CHECK(map != NULL, return -1, "Cannot get sandbox map by name %s.", name);
540    sandbox_t *sandbox = map->sandbox;
541    BEGET_CHECK(IsValidSandbox(sandbox) == true, return -1);
542    BEGET_INFO_CHECK(sandbox->isCreated == false, return 0, "Sandbox %s already created", sandbox->name);
543    BEGET_CHECK(sandbox->rootPath != NULL, return -1);
544    mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
545    BEGET_ERROR_CHECK(CheckAndMakeDir(sandbox->rootPath, mode) == 0, return -1, "Failed root %s.", sandbox->rootPath);
546    int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
547    BEGET_ERROR_CHECK(rc == 0, return -1, "Failed set mount slave err = %d", errno);
548    rc = BindMount(sandbox->rootPath, sandbox->rootPath, MS_BIND | MS_REC, SANDBOX_TAG_MOUNT_PATH);
549    BEGET_ERROR_CHECK(rc == 0, return -1, "Failed to mount rootpath bind err = %d", errno);
550
551    // 1) walk through all mounts and do bind mount
552    rc = MountSandboxInfo(&sandbox->pathMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_PATH);
553    BEGET_CHECK(rc == 0, return -1);
554
555    rc = MountSandboxInfo(&sandbox->fileMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_FILE);
556    BEGET_CHECK(rc == 0, return -1);
557
558    // 2) walk through all links and do symbol link
559    rc = LinkSandboxInfo(&sandbox->linksHead, sandbox->rootPath);
560    BEGET_CHECK(rc == 0, return -1);
561
562    BEGET_ERROR_CHECK(chdir(sandbox->rootPath) == 0, return -1, "Change to %s, err = %d", sandbox->rootPath, errno);
563    BEGET_ERROR_CHECK(syscall(SYS_pivot_root, sandbox->rootPath, sandbox->rootPath) == 0, return -1,
564        "Failed system call pivot root, err=%d", errno);
565    BEGET_ERROR_CHECK(umount2(".", MNT_DETACH) == 0, return -1, "Failed umount2 MNT_DETACH, err=%d", errno);
566    sandbox->isCreated = true;
567    return 0;
568}
569
570bool InitSandboxWithName(const char *name)
571{
572    bool isFound = false;
573    if (name == NULL) {
574        BEGET_LOGE("Init sandbox name is NULL.");
575        return isFound;
576    }
577    const struct SandboxMap *map = GetSandboxMapByName(name);
578    if (map != NULL) {
579        InitSandbox(map->sandbox, map->configfile, name);
580        isFound = true;
581    }
582
583    if (!isFound) {
584        BEGET_LOGE("Cannot find sandbox with name %s.", name);
585    }
586    return isFound;
587}
588
589void DestroySandbox(const char *name)
590{
591    if (name == NULL) {
592        BEGET_LOGE("Destroy sandbox name is NULL.");
593        return;
594    }
595    const struct SandboxMap *map = GetSandboxMapByName(name);
596    if (map == NULL) {
597        BEGET_LOGE("Cannot get sandbox map by name %s.", name);
598        return;
599    }
600    sandbox_t *sandbox = map->sandbox;
601
602    BEGET_CHECK(sandbox != NULL, return);
603
604    if (sandbox->rootPath != NULL) {
605        free(sandbox->rootPath);
606        sandbox->rootPath = NULL;
607    }
608    OH_ListRemoveAll(&sandbox->linksHead, FreeSandboxLinkInfo);
609    OH_ListRemoveAll(&sandbox->fileMountsHead, FreeSandboxMountInfo);
610    OH_ListRemoveAll(&sandbox->pathMountsHead, FreeSandboxMountInfo);
611
612    if (sandbox->ns > 0) {
613        (void)close(sandbox->ns);
614    }
615    sandbox->isCreated = false;
616    return;
617}
618
619int EnterSandbox(const char *name)
620{
621    if (name == NULL) {
622        BEGET_LOGE("Sandbox name is NULL.");
623        return -1;
624    }
625    const struct SandboxMap *map = GetSandboxMapByName(name);
626    if (map == NULL) {
627        BEGET_LOGE("Cannot get sandbox map by name %s.", name);
628        return -1;
629    }
630    sandbox_t *sandbox = map->sandbox;
631
632    BEGET_CHECK(sandbox != NULL, return -1);
633    if (sandbox->isCreated == false) {
634        BEGET_LOGE("Sandbox %s has not been created.", name);
635        return -1;
636    }
637    if (sandbox->ns > 0) {
638        BEGET_ERROR_CHECK(!(SetNamespace(sandbox->ns, CLONE_NEWNS) < 0), return -1,
639            "Cannot enter mount namespace for sandbox \' %s \', err=%d.", name, errno);
640    } else {
641        BEGET_LOGE("Sandbox \' %s \' namespace fd is invalid.", name);
642        return -1;
643    }
644    return 0;
645}
646
647static int DumpSandboxMountInfo(ListNode *list, void *data)
648{
649    if (list == NULL) {
650        return -1;
651    }
652    mountlist_t *info = ListEntry(list, mountlist_t, node);
653    if (info != NULL) {
654        if (info->source != NULL) {
655            printf("Sandbox mounts list source: %s \n", info->source);
656        }
657        if (info->target != NULL) {
658            printf("Sandbox mounts list target: %s \n", info->target);
659        }
660    }
661    return 0;
662}
663
664static int DumpSandboxLinkInfo(ListNode *list, void *data)
665{
666    if (list == NULL) {
667        return -1;
668    }
669    linklist_t *info = ListEntry(list, linklist_t, node);
670    if (info != NULL) {
671        if (info->linkName != NULL) {
672            printf("Sandbox link list name: %s \n", info->linkName);
673        }
674        if (info->target != NULL) {
675            printf("Sandbox link list target: %s \n", info->target);
676        }
677    }
678    return 0;
679}
680
681void DumpSandboxByName(const char *name)
682{
683    if (name == NULL) {
684        BEGET_LOGE("Init sandbox name is NULL.");
685        return;
686    }
687    const struct SandboxMap *map = GetSandboxMapByName(name);
688    if (map == NULL) {
689        return;
690    }
691    printf("Sandbox Map name: %s \n", map->name);
692    printf("Sandbox Map config file: %s. \n", map->configfile);
693    printf("Sandbox name: %s. \n", map->sandbox->name);
694    printf("Sandbox root path is %s. \n", map->sandbox->rootPath);
695    printf("Sandbox mounts info: \n");
696    OH_ListTraversal(&map->sandbox->pathMountsHead, NULL, DumpSandboxMountInfo, 0);
697    OH_ListTraversal(&map->sandbox->fileMountsHead, NULL, DumpSandboxMountInfo, 0);
698    printf("Sandbox links info: \n");
699    OH_ListTraversal(&map->sandbox->linksHead, NULL, DumpSandboxLinkInfo, 0);
700    return;
701}
702