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