• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     tmpMount->target = strdup(dstPath);
241     for (int i = 0; i < count; i++) {
242         cJSON *item = cJSON_GetArrayItem(obj, i);
243         tmpMount->flags |= GetSandboxMountFlags(item);
244     }
245     tmpMount->ignoreErrors = false;
246     obj = cJSON_GetObjectItem(item, SANDBOX_IGNORE_ERRORS);
247     if (obj != NULL) {
248         if (cJSON_GetNumberValue(obj) == 1) {
249             tmpMount->ignoreErrors = true;
250         }
251     }
252     OH_ListInit(&tmpMount->node);
253     if (strcmp(type, SANDBOX_MOUNT_PATH_TAG) == 0) {
254         tmpMount->tag = SANDBOX_TAG_MOUNT_PATH;
255         RemoveOldSandboxMountListNode(&sandbox->pathMountsHead, dstPath);
256         OH_ListAddTail(&sandbox->pathMountsHead, &tmpMount->node);
257     } else if (strcmp(type, SANDBOX_MOUNT_FILE_TAG) == 0) {
258         tmpMount->tag = SANDBOX_TAG_MOUNT_FILE;
259         RemoveOldSandboxMountListNode(&sandbox->fileMountsHead, dstPath);
260         OH_ListAddTail(&sandbox->fileMountsHead, &tmpMount->node);
261     }
262     return 0;
263 }
264 
AddSymbolLinksToSandbox(sandbox_t * sandbox,cJSON * item,const char * type)265 static int AddSymbolLinksToSandbox(sandbox_t *sandbox, cJSON *item, const char *type)
266 {
267     BEGET_CHECK(!(sandbox == NULL || item == NULL || type == NULL), return -1);
268     BEGET_ERROR_CHECK(strcmp(type, SANDBOX_SYMLINK_TAG) == 0, return -1, "Type is not sandbox symbolLink.");
269     char *target = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_TARGET));
270     BEGET_ERROR_CHECK(target != NULL, return 0, "Get target-name is null");
271     char *name = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_NAME));
272     BEGET_ERROR_CHECK(name != NULL, return 0, "Get link-name is null");
273     linklist_t *tmpLink = (linklist_t *)calloc(1, sizeof(linklist_t));
274     BEGET_ERROR_CHECK(tmpLink != NULL, return -1, "Failed calloc err=%d", errno);
275     tmpLink->target = strdup(target);
276     tmpLink->linkName = strdup(name);
277     OH_ListInit(&tmpLink->node);
278     RemoveOldSandboxLinkListNode(&sandbox->linksHead, tmpLink->linkName);
279     OH_ListAddTail(&sandbox->linksHead, &tmpLink->node);
280     return 0;
281 }
282 
GetSandboxInfo(sandbox_t * sandbox,cJSON * root,const char * itemName)283 static int GetSandboxInfo(sandbox_t *sandbox, cJSON *root, const char *itemName)
284 {
285     BEGET_ERROR_CHECK(!(sandbox == NULL || root == NULL || itemName == NULL), return -1,
286         "Get sandbox mount info with invalid argument");
287     cJSON *obj = cJSON_GetObjectItem(root, itemName);
288     BEGET_ERROR_CHECK(obj != NULL, return 0, "Cannot find item \' %s \' in sandbox config", itemName);
289     BEGET_ERROR_CHECK(cJSON_IsArray(obj), return 0, "ItemName %s with invalid type, should be array", itemName);
290 
291     int counts = cJSON_GetArraySize(obj);
292     BEGET_ERROR_CHECK(counts > 0, return 0, "Item %s array size is zero.", itemName);
293     AddInfoToSandboxCallback func = NULL;
294     if (strcmp(itemName, SANDBOX_MOUNT_PATH_TAG) == 0) {
295         func = AddMountInfoToSandbox;
296     } else if (strcmp(itemName, SANDBOX_MOUNT_FILE_TAG) == 0) {
297         func = AddMountInfoToSandbox;
298     } else if (strcmp(itemName, SANDBOX_SYMLINK_TAG) == 0) {
299         func = AddSymbolLinksToSandbox;
300     } else {
301         BEGET_LOGE("Item %s is not support.", itemName);
302         return -1;
303     }
304     for (int i = 0; i < counts; i++) {
305         cJSON *item = cJSON_GetArrayItem(obj, i);
306         BEGET_ERROR_CHECK(item != NULL, return -1, "Failed get json array item %d", i);
307         BEGET_ERROR_CHECK(func(sandbox, item, itemName) == 0, return -1, "Failed add info to sandbox.");
308     }
309     return 0;
310 }
311 
ParseSandboxConfig(cJSON * root,sandbox_t * sandbox)312 static int ParseSandboxConfig(cJSON *root, sandbox_t *sandbox)
313 {
314     BEGET_ERROR_CHECK(!(root == NULL || sandbox == NULL), return -1, "Invalid parameter.");
315     // sandbox rootpath must initialize according to the system configuration, and it can only be initialized once.
316     if (sandbox->rootPath == NULL) {
317         cJSON *sandboxRoot = cJSON_GetObjectItem(root, SANDBOX_ROOT_TAG);
318         BEGET_ERROR_CHECK(sandboxRoot != NULL, return -1,
319             "Cannot find item \' %s \' in sandbox config", SANDBOX_ROOT_TAG);
320 
321         char *rootdir = cJSON_GetStringValue(sandboxRoot);
322         if (rootdir != NULL) {
323             sandbox->rootPath = strdup(rootdir);
324             BEGET_ERROR_CHECK(sandbox->rootPath != NULL, return -1,
325                 "Get sandbox root path out of memory");
326         }
327     }
328     BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_PATH_TAG) == 0, return -1,
329         "config info %s error", SANDBOX_MOUNT_PATH_TAG);
330     BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_FILE_TAG) == 0, return -1,
331         "config info %s error", SANDBOX_MOUNT_FILE_TAG);
332     BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_SYMLINK_TAG) == 0, return -1,
333         "config info %s error", SANDBOX_SYMLINK_TAG);
334     return 0;
335 }
336 
GetSandboxMapByName(const char * name)337 static const struct SandboxMap *GetSandboxMapByName(const char *name)
338 {
339     BEGET_ERROR_CHECK(name != NULL, return NULL, "Sandbox map name is NULL.");
340     int len = ARRAY_LENGTH(MAP);
341     for (int i = 0; i < len; i++) {
342         if (strcmp(MAP[i].name, name) == 0) {
343             return &MAP[i];
344         }
345     }
346     return NULL;
347 }
348 
ParseInitSandboxConfigFile(sandbox_t * sandbox,const char * sandboxConfigFile,const char * name)349 static int ParseInitSandboxConfigFile(sandbox_t *sandbox, const char *sandboxConfigFile, const char *name)
350 {
351     char *contents = ReadFileToBuf(sandboxConfigFile);
352     if (contents == NULL) {
353         return 0;
354     }
355     cJSON *root = cJSON_Parse(contents);
356     free(contents);
357     BEGET_ERROR_CHECK(root != NULL, return -1, "Parse sandbox config \' %s \' failed", sandboxConfigFile);
358     int ret = ParseSandboxConfig(root, sandbox);
359     cJSON_Delete(root);
360     if (ret < 0) {
361         DestroySandbox(name);
362         return -1;
363     }
364     return 0;
365 }
366 
ParseInitSandboxConfigPath(sandbox_t * sandbox,const char * sandboxConfig,const char * name)367 static void ParseInitSandboxConfigPath(sandbox_t *sandbox, const char *sandboxConfig, const char *name)
368 {
369     CfgFiles *files = GetCfgFiles(sandboxConfig);
370     for (int i = 0; files && i < MAX_CFG_POLICY_DIRS_CNT; i++) {
371         if (files->paths[i]) {
372             BEGET_LOGI("Parse sandbox cfg file is %s", files->paths[i]);
373             if (ParseInitSandboxConfigFile(sandbox, files->paths[i], name) < 0) {
374                 break;
375             }
376         }
377     }
378     FreeCfgFiles(files);
379 }
380 
InitSandbox(sandbox_t * sandbox,const char * sandboxConfig,const char * name)381 static void InitSandbox(sandbox_t *sandbox, const char *sandboxConfig, const char *name)
382 {
383     BEGET_ERROR_CHECK(!(sandbox == NULL || sandboxConfig == NULL || name == NULL), return,
384         "Init sandbox with invalid arguments");
385     if (sandbox->isCreated) {
386         BEGET_LOGE("Sandbox %s has created.", name);
387         return;
388     }
389     if (UnshareNamespace(CLONE_NEWNS) < 0) {
390         return;
391     }
392     sandbox->ns = GetNamespaceFd("/proc/self/ns/mnt");
393     BEGET_ERROR_CHECK(!(sandbox->ns < 0), return, "Get sandbox namespace fd is failed");
394 
395     BEGET_ERROR_CHECK(strcpy_s(sandbox->name, MAX_BUFFER_LEN - 1, name) == 0, return, "Failed to copy sandbox name");
396     OH_ListInit(&sandbox->pathMountsHead);
397     OH_ListInit(&sandbox->fileMountsHead);
398     OH_ListInit(&sandbox->linksHead);
399     // parse json config
400 #ifdef STARTUP_INIT_TEST
401     (void)ParseInitSandboxConfigFile(sandbox, sandboxConfig, name);
402 #else
403     ParseInitSandboxConfigPath(sandbox, sandboxConfig, name);
404 #endif
405     return;
406 }
407 
CheckAndMakeDir(const char * dir,mode_t mode)408 static int CheckAndMakeDir(const char *dir, mode_t mode)
409 {
410     struct stat sb;
411 
412     if ((stat(dir, &sb) == 0) && S_ISDIR(sb.st_mode)) {
413         BEGET_LOGI("Mount point \' %s \' already exist, no need to mkdir", dir);
414         return 0;
415     } else {
416         if (errno == ENOENT) {
417             BEGET_ERROR_CHECK(MakeDirRecursive(dir, mode) == 0, return -1,
418                 "Failed MakeDirRecursive %s, err=%d", dir, errno);
419         } else {
420             BEGET_LOGW("Failed to access mount point \' %s \', err = %d", dir, errno);
421             return -1;
422         }
423     }
424     return 0;
425 }
426 
BindMount(const char * source,const char * target,unsigned long flags,SandboxTag tag)427 static int BindMount(const char *source, const char *target, unsigned long flags, SandboxTag tag)
428 {
429     if (source == NULL || target == NULL) {
430         BEGET_LOGE("Mount with invalid arguments");
431         errno = EINVAL;
432         return -1;
433     }
434     unsigned long tmpflags = flags;
435     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
436     if (tag == SANDBOX_TAG_MOUNT_PATH) {
437         BEGET_ERROR_CHECK(CheckAndMakeDir(target, mode) == 0, return -1, "Failed make %s dir.", target);
438     } else if (tag == SANDBOX_TAG_MOUNT_FILE) {
439         BEGET_ERROR_CHECK(CheckAndCreatFile(target, mode) == 0, return -1, "Failed make %s file.", target);
440     } else {
441         BEGET_LOGE("Tag is error.");
442         return -1;
443     }
444 
445     BEGET_WARNING_CHECK((tmpflags & MS_BIND) != 0, tmpflags |= MS_BIND,
446         "Not configure mount bind, must configure mount bind flag.");
447     BEGET_WARNING_CHECK((tmpflags & MS_REC) != 0, tmpflags |= MS_REC,
448         "Not configure mount rec, must configure mount rec flag.");
449 
450     // do mount
451     if (mount(source, target, NULL, tmpflags, NULL) != 0) {
452         BEGET_LOGE("Failed to bind mount \' %s \' to \' %s \', err = %d", source, target, errno);
453         if (errno != ENOTDIR) {  // mount errno is 'Not a directory' can ignore
454             return -1;
455         }
456     }
457 
458     return 0;
459 }
460 
IsValidSandbox(sandbox_t * sandbox)461 static bool IsValidSandbox(sandbox_t *sandbox)
462 {
463     BEGET_ERROR_CHECK(sandbox != NULL, return false, "preparing sandbox with invalid argument");
464 
465     if (sandbox->rootPath == NULL) {
466         return false;
467     }
468 
469     return true;
470 }
471 
MountSandboxNode(ListNode * list,void * data)472 static int MountSandboxNode(ListNode *list, void *data)
473 {
474     if ((list == NULL) || (data == NULL)) {
475         return 0;
476     }
477     const char *rootPath = (const char *)data;
478     mountlist_t *info = ListEntry(list, mountlist_t, node);
479     char target[PATH_MAX] = {};
480     BEGET_ERROR_CHECK(snprintf_s(target, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->target) > 0,
481         return -1, "Failed snprintf_s err=%d", errno);
482     int rc = BindMount(info->source, target, info->flags, info->tag);
483     if (rc != 0) {
484         BEGET_LOGW("Failed bind mount %s to %s.", info->source, target);
485         if (info->ignoreErrors == false) {
486             return -1;
487         }
488     }
489     return 0;
490 }
491 
MountSandboxInfo(struct ListNode * head,const char * rootPath,SandboxTag tag)492 static int MountSandboxInfo(struct ListNode *head, const char *rootPath, SandboxTag tag)
493 {
494     if ((head == NULL) || (rootPath == NULL)) {
495         return 0;
496     }
497     int ret = OH_ListTraversal(head, (void *)rootPath, MountSandboxNode, 1);
498     return ret;
499 }
500 
LinkSandboxNode(ListNode * list,void * data)501 static int LinkSandboxNode(ListNode *list, void *data)
502 {
503     if ((list == NULL) || (data == NULL)) {
504         return 0;
505     }
506     const char *rootPath = (const char *)data;
507     linklist_t *info = ListEntry(list, linklist_t, node);
508     char linkName[PATH_MAX] = {0};
509     BEGET_ERROR_CHECK(!(snprintf_s(linkName, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->linkName) < 0),
510         return -1, "snprintf_s failed, err=%d", errno);
511     int rc = symlink(info->target, linkName);
512     if (rc != 0) {
513         if (errno == EEXIST) {
514             BEGET_LOGW("symbol link name \' %s \' already exist", linkName);
515         } else {
516             BEGET_LOGE("Failed to link \' %s \' to \' %s \', err = %d", info->target, linkName, errno);
517             return -1;
518         }
519     }
520     return 0;
521 }
522 
LinkSandboxInfo(struct ListNode * head,const char * rootPath)523 static int LinkSandboxInfo(struct ListNode *head, const char *rootPath)
524 {
525     if ((head == NULL) || (rootPath == NULL)) {
526         return 0;
527     }
528     int ret = OH_ListTraversal(head, (void *)rootPath, LinkSandboxNode, 1);
529     return ret;
530 }
531 
PrepareSandbox(const char * name)532 int PrepareSandbox(const char *name)
533 {
534     BEGET_ERROR_CHECK(name != NULL, return -1, "Prepare sandbox name is NULL.");
535     BEGET_ERROR_CHECK(getuid() == 0, return -1, "Current process uid is not root, exit.");
536     const struct SandboxMap *map = GetSandboxMapByName(name);
537     BEGET_ERROR_CHECK(map != NULL, return -1, "Cannot get sandbox map by name %s.", name);
538     sandbox_t *sandbox = map->sandbox;
539     BEGET_CHECK(IsValidSandbox(sandbox) == true, return -1);
540     BEGET_INFO_CHECK(sandbox->isCreated == false, return 0, "Sandbox %s already created", sandbox->name);
541     BEGET_CHECK(sandbox->rootPath != NULL, return -1);
542     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
543     BEGET_ERROR_CHECK(CheckAndMakeDir(sandbox->rootPath, mode) == 0, return -1, "Failed root %s.", sandbox->rootPath);
544     int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
545     BEGET_ERROR_CHECK(rc == 0, return -1, "Failed set mount slave err = %d", errno);
546     rc = BindMount(sandbox->rootPath, sandbox->rootPath, MS_BIND | MS_REC, SANDBOX_TAG_MOUNT_PATH);
547     BEGET_ERROR_CHECK(rc == 0, return -1, "Failed to mount rootpath bind err = %d", errno);
548 
549     // 1) walk through all mounts and do bind mount
550     rc = MountSandboxInfo(&sandbox->pathMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_PATH);
551     BEGET_CHECK(rc == 0, return -1);
552 
553     rc = MountSandboxInfo(&sandbox->fileMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_FILE);
554     BEGET_CHECK(rc == 0, return -1);
555 
556     // 2) walk through all links and do symbol link
557     rc = LinkSandboxInfo(&sandbox->linksHead, sandbox->rootPath);
558     BEGET_CHECK(rc == 0, return -1);
559 
560     BEGET_ERROR_CHECK(chdir(sandbox->rootPath) == 0, return -1, "Change to %s, err = %d", sandbox->rootPath, errno);
561     BEGET_ERROR_CHECK(syscall(SYS_pivot_root, sandbox->rootPath, sandbox->rootPath) == 0, return -1,
562         "Failed system call pivot root, err=%d", errno);
563     BEGET_ERROR_CHECK(umount2(".", MNT_DETACH) == 0, return -1, "Failed umount2 MNT_DETACH, err=%d", errno);
564     sandbox->isCreated = true;
565     return 0;
566 }
567 
InitSandboxWithName(const char * name)568 bool InitSandboxWithName(const char *name)
569 {
570     bool isFound = false;
571     if (name == NULL) {
572         BEGET_LOGE("Init sandbox name is NULL.");
573         return isFound;
574     }
575     const struct SandboxMap *map = GetSandboxMapByName(name);
576     if (map != NULL) {
577         InitSandbox(map->sandbox, map->configfile, name);
578         isFound = true;
579     }
580 
581     if (!isFound) {
582         BEGET_LOGE("Cannot find sandbox with name %s.", name);
583     }
584     return isFound;
585 }
586 
DestroySandbox(const char * name)587 void DestroySandbox(const char *name)
588 {
589     if (name == NULL) {
590         BEGET_LOGE("Destroy sandbox name is NULL.");
591         return;
592     }
593     const struct SandboxMap *map = GetSandboxMapByName(name);
594     if (map == NULL) {
595         BEGET_LOGE("Cannot get sandbox map by name %s.", name);
596         return;
597     }
598     sandbox_t *sandbox = map->sandbox;
599 
600     BEGET_CHECK(sandbox != NULL, return);
601 
602     if (sandbox->rootPath != NULL) {
603         free(sandbox->rootPath);
604         sandbox->rootPath = NULL;
605     }
606     OH_ListRemoveAll(&sandbox->linksHead, FreeSandboxLinkInfo);
607     OH_ListRemoveAll(&sandbox->fileMountsHead, FreeSandboxMountInfo);
608     OH_ListRemoveAll(&sandbox->pathMountsHead, FreeSandboxMountInfo);
609 
610     if (sandbox->ns > 0) {
611         (void)close(sandbox->ns);
612     }
613     sandbox->isCreated = false;
614     return;
615 }
616 
EnterSandbox(const char * name)617 int EnterSandbox(const char *name)
618 {
619     if (name == NULL) {
620         BEGET_LOGE("Sandbox name is NULL.");
621         return -1;
622     }
623     const struct SandboxMap *map = GetSandboxMapByName(name);
624     if (map == NULL) {
625         BEGET_LOGE("Cannot get sandbox map by name %s.", name);
626         return -1;
627     }
628     sandbox_t *sandbox = map->sandbox;
629 
630     BEGET_CHECK(sandbox != NULL, return -1);
631     if (sandbox->isCreated == false) {
632         BEGET_LOGE("Sandbox %s has not been created.", name);
633         return -1;
634     }
635     if (sandbox->ns > 0) {
636         BEGET_ERROR_CHECK(!(SetNamespace(sandbox->ns, CLONE_NEWNS) < 0), return -1,
637             "Cannot enter mount namespace for sandbox \' %s \', err=%d.", name, errno);
638     } else {
639         BEGET_LOGE("Sandbox \' %s \' namespace fd is invalid.", name);
640         return -1;
641     }
642     return 0;
643 }
644 
DumpSandboxMountInfo(ListNode * list,void * data)645 static int DumpSandboxMountInfo(ListNode *list, void *data)
646 {
647     if (list == NULL) {
648         return -1;
649     }
650     mountlist_t *info = ListEntry(list, mountlist_t, node);
651     if (info != NULL) {
652         if (info->source != NULL) {
653             printf("Sandbox mounts list source: %s \n", info->source);
654         }
655         if (info->target != NULL) {
656             printf("Sandbox mounts list target: %s \n", info->target);
657         }
658     }
659     return 0;
660 }
661 
DumpSandboxLinkInfo(ListNode * list,void * data)662 static int DumpSandboxLinkInfo(ListNode *list, void *data)
663 {
664     if (list == NULL) {
665         return -1;
666     }
667     linklist_t *info = ListEntry(list, linklist_t, node);
668     if (info != NULL) {
669         if (info->linkName != NULL) {
670             printf("Sandbox link list name: %s \n", info->linkName);
671         }
672         if (info->target != NULL) {
673             printf("Sandbox link list target: %s \n", info->target);
674         }
675     }
676     return 0;
677 }
678 
DumpSandboxByName(const char * name)679 void DumpSandboxByName(const char *name)
680 {
681     if (name == NULL) {
682         BEGET_LOGE("Init sandbox name is NULL.");
683         return;
684     }
685     const struct SandboxMap *map = GetSandboxMapByName(name);
686     if (map == NULL) {
687         return;
688     }
689     printf("Sandbox Map name: %s \n", map->name);
690     printf("Sandbox Map config file: %s. \n", map->configfile);
691     printf("Sandbox name: %s. \n", map->sandbox->name);
692     printf("Sandbox root path is %s. \n", map->sandbox->rootPath);
693     printf("Sandbox mounts info: \n");
694     OH_ListTraversal(&map->sandbox->pathMountsHead, NULL, DumpSandboxMountInfo, 0);
695     OH_ListTraversal(&map->sandbox->fileMountsHead, NULL, DumpSandboxMountInfo, 0);
696     printf("Sandbox links info: \n");
697     OH_ListTraversal(&map->sandbox->linksHead, NULL, DumpSandboxLinkInfo, 0);
698     return;
699 }
700