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 
57 struct SandboxMountFlags {
58     const char *flag;
59     unsigned long value;
60 };
61 
62 static 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 
81 static sandbox_t g_systemSandbox = {};
82 static sandbox_t g_chipsetSandbox = {};
83 #ifdef STARTUP_INIT_TEST
84 static sandbox_t g_testSandbox = {};
85 #endif
86 
87 struct SandboxMap {
88     const char *name;
89     sandbox_t *sandbox;
90     const char *configfile;
91 };
92 
93 static 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 
GetSandboxMountFlags(cJSON * item)113 static 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 
FreeSandboxMountInfo(ListNode * list)126 static 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 
FreeSandboxLinkInfo(ListNode * list)148 static 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 
CompareSandboxListForMountTarget(ListNode * list,void * data)170 static 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 
RemoveOldSandboxMountListNode(ListNode * head,const char * targetMount)183 static 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 
CompareSandboxListForLinkName(ListNode * list,void * data)196 static 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 
RemoveOldSandboxLinkListNode(ListNode * head,const char * linkName)209 static 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 
222 typedef int (*AddInfoToSandboxCallback)(sandbox_t *sandbox, cJSON *item, const char *type);
223 
AddMountInfoToSandbox(sandbox_t * sandbox,cJSON * item,const char * type)224 static 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 
AddSymbolLinksToSandbox(sandbox_t * sandbox,cJSON * item,const char * type)267 static 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 
GetSandboxInfo(sandbox_t * sandbox,cJSON * root,const char * itemName)287 static 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 
ParseSandboxConfig(cJSON * root,sandbox_t * sandbox)316 static 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 
GetSandboxMapByName(const char * name)341 static 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 
ParseInitSandboxConfigFile(sandbox_t * sandbox,const char * sandboxConfigFile,const char * name)353 static 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 
ParseInitSandboxConfigPath(sandbox_t * sandbox,const char * sandboxConfig,const char * name)371 static 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 
InitSandbox(sandbox_t * sandbox,const char * sandboxConfig,const char * name)385 static 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 
CheckAndMakeDir(const char * dir,mode_t mode)412 static 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 
BindMount(const char * source,const char * target,unsigned long flags,SandboxTag tag)431 static 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     BEGET_WARNING_CHECK((tmpflags & MS_REC) != 0, tmpflags |= MS_REC,
452         "Not configure mount rec, must configure mount rec flag.");
453 
454     // do mount
455     if (mount(source, target, NULL, tmpflags, NULL) != 0) {
456         BEGET_LOGE("Failed to bind mount \' %s \' to \' %s \', err = %d", source, target, errno);
457         if (errno != ENOTDIR) {  // mount errno is 'Not a directory' can ignore
458             return -1;
459         }
460     }
461 
462     return 0;
463 }
464 
IsValidSandbox(sandbox_t * sandbox)465 static bool IsValidSandbox(sandbox_t *sandbox)
466 {
467     BEGET_ERROR_CHECK(sandbox != NULL, return false, "preparing sandbox with invalid argument");
468 
469     if (sandbox->rootPath == NULL) {
470         return false;
471     }
472 
473     return true;
474 }
475 
MountSandboxNode(ListNode * list,void * data)476 static int MountSandboxNode(ListNode *list, void *data)
477 {
478     if ((list == NULL) || (data == NULL)) {
479         return 0;
480     }
481     const char *rootPath = (const char *)data;
482     mountlist_t *info = ListEntry(list, mountlist_t, node);
483     char target[PATH_MAX] = {};
484     BEGET_ERROR_CHECK(snprintf_s(target, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->target) > 0,
485         return -1, "Failed snprintf_s err=%d", errno);
486     int rc = BindMount(info->source, target, info->flags, info->tag);
487     if (rc != 0) {
488         BEGET_LOGW("Failed bind mount %s to %s.", info->source, target);
489         if (info->ignoreErrors == false) {
490             return -1;
491         }
492     }
493     return 0;
494 }
495 
MountSandboxInfo(struct ListNode * head,const char * rootPath,SandboxTag tag)496 static int MountSandboxInfo(struct ListNode *head, const char *rootPath, SandboxTag tag)
497 {
498     if ((head == NULL) || (rootPath == NULL)) {
499         return 0;
500     }
501     int ret = OH_ListTraversal(head, (void *)rootPath, MountSandboxNode, 1);
502     return ret;
503 }
504 
LinkSandboxNode(ListNode * list,void * data)505 static int LinkSandboxNode(ListNode *list, void *data)
506 {
507     if ((list == NULL) || (data == NULL)) {
508         return 0;
509     }
510     const char *rootPath = (const char *)data;
511     linklist_t *info = ListEntry(list, linklist_t, node);
512     char linkName[PATH_MAX] = {0};
513     BEGET_ERROR_CHECK(!(snprintf_s(linkName, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->linkName) < 0),
514         return -1, "snprintf_s failed, err=%d", errno);
515     int rc = symlink(info->target, linkName);
516     if (rc != 0) {
517         if (errno == EEXIST) {
518             BEGET_LOGW("symbol link name \' %s \' already exist", linkName);
519         } else {
520             BEGET_LOGE("Failed to link \' %s \' to \' %s \', err = %d", info->target, linkName, errno);
521             return -1;
522         }
523     }
524     return 0;
525 }
526 
LinkSandboxInfo(struct ListNode * head,const char * rootPath)527 static int LinkSandboxInfo(struct ListNode *head, const char *rootPath)
528 {
529     if ((head == NULL) || (rootPath == NULL)) {
530         return 0;
531     }
532     int ret = OH_ListTraversal(head, (void *)rootPath, LinkSandboxNode, 1);
533     return ret;
534 }
535 
PrepareSandbox(const char * name)536 int PrepareSandbox(const char *name)
537 {
538     BEGET_ERROR_CHECK(name != NULL, return -1, "Prepare sandbox name is NULL.");
539     BEGET_ERROR_CHECK(getuid() == 0, return -1, "Current process uid is not root, exit.");
540     const struct SandboxMap *map = GetSandboxMapByName(name);
541     BEGET_ERROR_CHECK(map != NULL, return -1, "Cannot get sandbox map by name %s.", name);
542     sandbox_t *sandbox = map->sandbox;
543     BEGET_CHECK(IsValidSandbox(sandbox) == true, return -1);
544     BEGET_INFO_CHECK(sandbox->isCreated == false, return 0, "Sandbox %s already created", sandbox->name);
545     BEGET_CHECK(sandbox->rootPath != NULL, return -1);
546     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
547     BEGET_ERROR_CHECK(CheckAndMakeDir(sandbox->rootPath, mode) == 0, return -1, "Failed root %s.", sandbox->rootPath);
548     int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
549     BEGET_ERROR_CHECK(rc == 0, return -1, "Failed set mount slave err = %d", errno);
550     rc = BindMount(sandbox->rootPath, sandbox->rootPath, MS_BIND | MS_REC, SANDBOX_TAG_MOUNT_PATH);
551     BEGET_ERROR_CHECK(rc == 0, return -1, "Failed to mount rootpath bind err = %d", errno);
552 
553     // 1) walk through all mounts and do bind mount
554     rc = MountSandboxInfo(&sandbox->pathMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_PATH);
555     BEGET_CHECK(rc == 0, return -1);
556 
557     rc = MountSandboxInfo(&sandbox->fileMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_FILE);
558     BEGET_CHECK(rc == 0, return -1);
559 
560     // 2) walk through all links and do symbol link
561     rc = LinkSandboxInfo(&sandbox->linksHead, sandbox->rootPath);
562     BEGET_CHECK(rc == 0, return -1);
563 
564     BEGET_ERROR_CHECK(chdir(sandbox->rootPath) == 0, return -1, "Change to %s, err = %d", sandbox->rootPath, errno);
565     BEGET_ERROR_CHECK(syscall(SYS_pivot_root, sandbox->rootPath, sandbox->rootPath) == 0, return -1,
566         "Failed system call pivot root, err=%d", errno);
567     BEGET_ERROR_CHECK(umount2(".", MNT_DETACH) == 0, return -1, "Failed umount2 MNT_DETACH, err=%d", errno);
568     sandbox->isCreated = true;
569     return 0;
570 }
571 
InitSandboxWithName(const char * name)572 bool InitSandboxWithName(const char *name)
573 {
574     bool isFound = false;
575     if (name == NULL) {
576         BEGET_LOGE("Init sandbox name is NULL.");
577         return isFound;
578     }
579     const struct SandboxMap *map = GetSandboxMapByName(name);
580     if (map != NULL) {
581         InitSandbox(map->sandbox, map->configfile, name);
582         isFound = true;
583     }
584 
585     if (!isFound) {
586         BEGET_LOGE("Cannot find sandbox with name %s.", name);
587     }
588     return isFound;
589 }
590 
DestroySandbox(const char * name)591 void DestroySandbox(const char *name)
592 {
593     if (name == NULL) {
594         BEGET_LOGE("Destroy sandbox name is NULL.");
595         return;
596     }
597     const struct SandboxMap *map = GetSandboxMapByName(name);
598     if (map == NULL) {
599         BEGET_LOGE("Cannot get sandbox map by name %s.", name);
600         return;
601     }
602     sandbox_t *sandbox = map->sandbox;
603 
604     BEGET_CHECK(sandbox != NULL, return);
605 
606     if (sandbox->rootPath != NULL) {
607         free(sandbox->rootPath);
608         sandbox->rootPath = NULL;
609     }
610     OH_ListRemoveAll(&sandbox->linksHead, FreeSandboxLinkInfo);
611     OH_ListRemoveAll(&sandbox->fileMountsHead, FreeSandboxMountInfo);
612     OH_ListRemoveAll(&sandbox->pathMountsHead, FreeSandboxMountInfo);
613 
614     if (sandbox->ns > 0) {
615         (void)close(sandbox->ns);
616     }
617     sandbox->isCreated = false;
618     return;
619 }
620 
EnterSandbox(const char * name)621 int EnterSandbox(const char *name)
622 {
623     if (name == NULL) {
624         BEGET_LOGE("Sandbox name is NULL.");
625         return -1;
626     }
627     const struct SandboxMap *map = GetSandboxMapByName(name);
628     if (map == NULL) {
629         BEGET_LOGE("Cannot get sandbox map by name %s.", name);
630         return -1;
631     }
632     sandbox_t *sandbox = map->sandbox;
633 
634     BEGET_CHECK(sandbox != NULL, return -1);
635     if (sandbox->isCreated == false) {
636         BEGET_LOGE("Sandbox %s has not been created.", name);
637         return -1;
638     }
639     if (sandbox->ns > 0) {
640         BEGET_ERROR_CHECK(!(SetNamespace(sandbox->ns, CLONE_NEWNS) < 0), return -1,
641             "Cannot enter mount namespace for sandbox \' %s \', err=%d.", name, errno);
642     } else {
643         BEGET_LOGE("Sandbox \' %s \' namespace fd is invalid.", name);
644         return -1;
645     }
646     return 0;
647 }
648 
DumpSandboxMountInfo(ListNode * list,void * data)649 static int DumpSandboxMountInfo(ListNode *list, void *data)
650 {
651     if (list == NULL) {
652         return -1;
653     }
654     mountlist_t *info = ListEntry(list, mountlist_t, node);
655     if (info != NULL) {
656         if (info->source != NULL) {
657             printf("Sandbox mounts list source: %s \n", info->source);
658         }
659         if (info->target != NULL) {
660             printf("Sandbox mounts list target: %s \n", info->target);
661         }
662     }
663     return 0;
664 }
665 
DumpSandboxLinkInfo(ListNode * list,void * data)666 static int DumpSandboxLinkInfo(ListNode *list, void *data)
667 {
668     if (list == NULL) {
669         return -1;
670     }
671     linklist_t *info = ListEntry(list, linklist_t, node);
672     if (info != NULL) {
673         if (info->linkName != NULL) {
674             printf("Sandbox link list name: %s \n", info->linkName);
675         }
676         if (info->target != NULL) {
677             printf("Sandbox link list target: %s \n", info->target);
678         }
679     }
680     return 0;
681 }
682 
DumpSandboxByName(const char * name)683 void DumpSandboxByName(const char *name)
684 {
685     if (name == NULL) {
686         BEGET_LOGE("Init sandbox name is NULL.");
687         return;
688     }
689     const struct SandboxMap *map = GetSandboxMapByName(name);
690     if (map == NULL) {
691         return;
692     }
693     printf("Sandbox Map name: %s \n", map->name);
694     printf("Sandbox Map config file: %s. \n", map->configfile);
695     printf("Sandbox name: %s. \n", map->sandbox->name);
696     printf("Sandbox root path is %s. \n", map->sandbox->rootPath);
697     printf("Sandbox mounts info: \n");
698     OH_ListTraversal(&map->sandbox->pathMountsHead, NULL, DumpSandboxMountInfo, 0);
699     OH_ListTraversal(&map->sandbox->fileMountsHead, NULL, DumpSandboxMountInfo, 0);
700     printf("Sandbox links info: \n");
701     OH_ListTraversal(&map->sandbox->linksHead, NULL, DumpSandboxLinkInfo, 0);
702     return;
703 }
704