1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <ctype.h>
16 #include <stdbool.h>
17 #include <stdlib.h>
18 #ifndef _GNU_SOURCE
19 #define _GNU_SOURCE
20 #endif
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sched.h>
24 #include <stdio.h>
25 #include <unistd.h>
26
27 #include <sys/mount.h>
28 #include <sys/types.h>
29
30 #include "appspawn_msg.h"
31 #include "appspawn_permission.h"
32 #include "appspawn_sandbox.h"
33 #include "appspawn_utils.h"
34 #include "cJSON.h"
35 #include "init_utils.h"
36 #include "json_utils.h"
37 #include "parameter.h"
38 #include "securec.h"
39
40 static const SandboxFlagInfo NAMESPACE_FLAGS_MAP[] = {
41 {"pid", CLONE_NEWPID}, {"net", CLONE_NEWNET}
42 };
43
44 static const SandboxFlagInfo FLAGE_POINT_MAP[] = {
45 {"0", 0},
46 {"START_FLAGS_BACKUP", (unsigned long)APP_FLAGS_BACKUP_EXTENSION},
47 {"DLP_MANAGER", (unsigned long)APP_FLAGS_DLP_MANAGER},
48 {"DEVELOPER_MODE", (unsigned long)APP_FLAGS_DEVELOPER_MODE}
49 };
50
51 static const SandboxFlagInfo MOUNT_MODE_MAP[] = {
52 {"not-exists", (unsigned long)MOUNT_MODE_NOT_EXIST},
53 {"always", (unsigned long)MOUNT_MODE_ALWAYS}
54 };
55
56 static const SandboxFlagInfo NAME_GROUP_TYPE_MAP[] = {
57 {"system-const", (unsigned long)SANDBOX_TAG_SYSTEM_CONST},
58 {"app-variable", (unsigned long)SANDBOX_TAG_APP_VARIABLE}
59 };
60
CreatePathMountNode(uint32_t type, uint32_t hasDemandInfo)61 static inline PathMountNode *CreatePathMountNode(uint32_t type, uint32_t hasDemandInfo)
62 {
63 uint32_t len = hasDemandInfo ? sizeof(PathDemandInfo) : 0;
64 return (PathMountNode *)CreateSandboxMountNode(sizeof(PathMountNode) + len, type);
65 }
66
CreateSymbolLinkNode(void)67 static inline SymbolLinkNode *CreateSymbolLinkNode(void)
68 {
69 return (SymbolLinkNode *)CreateSandboxMountNode(sizeof(SymbolLinkNode), SANDBOX_TAG_SYMLINK);
70 }
71
CreateSandboxPackageNameNode(const char *name)72 static inline SandboxPackageNameNode *CreateSandboxPackageNameNode(const char *name)
73 {
74 return (SandboxPackageNameNode *)CreateSandboxSection(name,
75 sizeof(SandboxPackageNameNode), SANDBOX_TAG_PACKAGE_NAME);
76 }
77
CreateSandboxFlagsNode(const char *name)78 static inline SandboxFlagsNode *CreateSandboxFlagsNode(const char *name)
79 {
80 return (SandboxFlagsNode *)CreateSandboxSection(name, sizeof(SandboxFlagsNode), SANDBOX_TAG_SPAWN_FLAGS);
81 }
82
CreateSandboxNameGroupNode(const char *name)83 static inline SandboxNameGroupNode *CreateSandboxNameGroupNode(const char *name)
84 {
85 return (SandboxNameGroupNode *)CreateSandboxSection(name, sizeof(SandboxNameGroupNode), SANDBOX_TAG_NAME_GROUP);
86 }
87
CreateSandboxPermissionNode(const char *name)88 static inline SandboxPermissionNode *CreateSandboxPermissionNode(const char *name)
89 {
90 size_t len = sizeof(SandboxPermissionNode);
91 SandboxPermissionNode *node = (SandboxPermissionNode *)CreateSandboxSection(name, len, SANDBOX_TAG_PERMISSION);
92 APPSPAWN_CHECK(node != NULL, return NULL, "Failed to create permission node");
93 node->permissionIndex = 0;
94 return node;
95 }
96
GetBoolParameter(const char *param, bool value)97 static inline bool GetBoolParameter(const char *param, bool value)
98 {
99 char tmp[32] = {0}; // 32 max
100 int ret = GetParameter(param, "", tmp, sizeof(tmp));
101 APPSPAWN_LOGV("GetBoolParameter key %{public}s ret %{public}d result: %{public}s", param, ret, tmp);
102 if (ret > 0 && strcmp(tmp, "false") == 0) {
103 return false;
104 }
105 if (ret > 0 && strcmp(tmp, "true") == 0) {
106 return true;
107 }
108 return value;
109 }
110
AppSandboxPidNsIsSupport(void)111 static inline bool AppSandboxPidNsIsSupport(void)
112 {
113 // only set false, return false
114 return GetBoolParameter("const.sandbox.pidns.support", true);
115 }
116
CheckAppFullMountEnable(void)117 static inline bool CheckAppFullMountEnable(void)
118 {
119 return GetBoolParameter("const.filemanager.full_mount.enable", false);
120 }
121
GetMountModeFromConfig(const cJSON *config, const char *key, unsigned long def)122 APPSPAWN_STATIC unsigned long GetMountModeFromConfig(const cJSON *config, const char *key, unsigned long def)
123 {
124 char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key));
125 if (value == NULL) {
126 return def;
127 }
128 const SandboxFlagInfo *info = GetSandboxFlagInfo(value, MOUNT_MODE_MAP, ARRAY_LENGTH(MOUNT_MODE_MAP));
129 if (info != NULL) {
130 return info->flags;
131 }
132 return def;
133 }
134
GetNameGroupTypeFromConfig(const cJSON *config, const char *key, unsigned long def)135 static uint32_t GetNameGroupTypeFromConfig(const cJSON *config, const char *key, unsigned long def)
136 {
137 char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key));
138 if (value == NULL) {
139 return def;
140 }
141 const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAME_GROUP_TYPE_MAP, ARRAY_LENGTH(NAME_GROUP_TYPE_MAP));
142 if (info != NULL) {
143 return (uint32_t)info->flags;
144 }
145 return def;
146 }
147
GetSandboxNsFlags(const cJSON *appConfig)148 static uint32_t GetSandboxNsFlags(const cJSON *appConfig)
149 {
150 uint32_t nsFlags = 0;
151 cJSON *obj = cJSON_GetObjectItemCaseSensitive(appConfig, "sandbox-ns-flags");
152 if (obj == NULL || !cJSON_IsArray(obj)) {
153 return nsFlags;
154 }
155 int count = cJSON_GetArraySize(obj);
156 for (int i = 0; i < count; i++) {
157 char *value = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
158 const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAMESPACE_FLAGS_MAP, ARRAY_LENGTH(NAMESPACE_FLAGS_MAP));
159 if (info != NULL) {
160 nsFlags |= info->flags;
161 }
162 }
163 return nsFlags;
164 }
165
SetMode(const char *str, void *context)166 static int SetMode(const char *str, void *context)
167 {
168 mode_t *mode = (mode_t *)context;
169 *mode |= GetPathMode(str);
170 return 0;
171 }
172
GetChmodFromJson(const cJSON *config)173 static mode_t GetChmodFromJson(const cJSON *config)
174 {
175 mode_t mode = 0;
176 char *modeStrs = GetStringFromJsonObj(config, "dest-mode");
177 if (modeStrs == NULL) {
178 return mode;
179 }
180 (void)StringSplit(modeStrs, "|", (void *)&mode, SetMode);
181 return mode;
182 }
183
GetFlagIndexFromJson(const cJSON *config)184 APPSPAWN_STATIC uint32_t GetFlagIndexFromJson(const cJSON *config)
185 {
186 char *flagStr = GetStringFromJsonObj(config, "name");
187 if (flagStr == NULL) {
188 return 0;
189 }
190 const SandboxFlagInfo *info = GetSandboxFlagInfo(flagStr, FLAGE_POINT_MAP, ARRAY_LENGTH(FLAGE_POINT_MAP));
191 if (info != NULL) {
192 return info->flags;
193 }
194 return 0;
195 }
196
FillPathDemandInfo(const cJSON *config, PathMountNode *sandboxNode)197 static void FillPathDemandInfo(const cJSON *config, PathMountNode *sandboxNode)
198 {
199 APPSPAWN_CHECK_ONLY_EXPER(config != NULL, return);
200 sandboxNode->demandInfo->uid = GetIntValueFromJsonObj(config, "uid", -1);
201 sandboxNode->demandInfo->gid = GetIntValueFromJsonObj(config, "gid", -1);
202 sandboxNode->demandInfo->mode = GetIntValueFromJsonObj(config, "ugo", -1);
203 }
204
DecodeMountPathConfig(const SandboxSection *section, const cJSON *config, uint32_t type)205 static PathMountNode *DecodeMountPathConfig(const SandboxSection *section, const cJSON *config, uint32_t type)
206 {
207 char *srcPath = GetStringFromJsonObj(config, "src-path");
208 char *dstPath = GetStringFromJsonObj(config, "sandbox-path");
209 if (srcPath == NULL || dstPath == NULL) {
210 return NULL;
211 }
212
213 PathMountNode *tmp = GetPathMountNode(section, type, srcPath, dstPath);
214 if (tmp != NULL) { // 删除老的节点,保存新的节点
215 DeleteSandboxMountNode((SandboxMountNode *)tmp);
216 APPSPAWN_LOGW("path %{public}s %{public}s repeat config, delete old", srcPath, dstPath);
217 }
218
219 cJSON *demandInfo = cJSON_GetObjectItemCaseSensitive(config, "create-on-demand");
220 PathMountNode *sandboxNode = CreatePathMountNode(type, demandInfo != NULL);
221 APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return NULL);
222 sandboxNode->createDemand = demandInfo != NULL;
223 sandboxNode->source = strdup(srcPath);
224 sandboxNode->target = strdup(dstPath);
225
226 sandboxNode->destMode = GetChmodFromJson(config);
227 sandboxNode->mountSharedFlag = GetBoolValueFromJsonObj(config, "mount-shared-flag", false);
228 sandboxNode->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
229
230 sandboxNode->category = GetMountCategory(GetStringFromJsonObj(config, "category"));
231 const char *value = GetStringFromJsonObj(config, "app-apl-name");
232 if (value != NULL) {
233 sandboxNode->appAplName = strdup(value);
234 }
235 FillPathDemandInfo(demandInfo, sandboxNode);
236
237 if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
238 APPSPAWN_LOGE("Failed to get sourc or target path");
239 DeleteSandboxMountNode((SandboxMountNode *)sandboxNode);
240 return NULL;
241 }
242 return sandboxNode;
243 }
244
ParseMountPathsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *mountConfigs, SandboxSection *section, uint32_t type)245 APPSPAWN_STATIC int ParseMountPathsConfig(AppSpawnSandboxCfg *sandbox,
246 const cJSON *mountConfigs, SandboxSection *section, uint32_t type)
247 {
248 APPSPAWN_CHECK_ONLY_EXPER(mountConfigs != NULL && cJSON_IsArray(mountConfigs), return -1);
249
250 uint32_t mountPointSize = cJSON_GetArraySize(mountConfigs);
251 for (uint32_t i = 0; i < mountPointSize; i++) {
252 cJSON *mntJson = cJSON_GetArrayItem(mountConfigs, i);
253 if (mntJson == NULL) {
254 continue;
255 }
256 PathMountNode *sandboxNode = DecodeMountPathConfig(section, mntJson, type);
257 APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, continue);
258 AddSandboxMountNode(&sandboxNode->sandboxNode, section);
259 }
260 return 0;
261 }
262
DecodeSymbolLinksConfig(const SandboxSection *section, const cJSON *config)263 static SymbolLinkNode *DecodeSymbolLinksConfig(const SandboxSection *section, const cJSON *config)
264 {
265 const char *target = GetStringFromJsonObj(config, "target-name");
266 const char *linkName = GetStringFromJsonObj(config, "link-name");
267 if (target == NULL || linkName == NULL) {
268 return NULL;
269 }
270
271 SymbolLinkNode *tmp = GetSymbolLinkNode(section, target, linkName);
272 if (tmp != NULL) { // 删除老的节点,保存新的节点
273 DeleteSandboxMountNode((SandboxMountNode *)tmp);
274 APPSPAWN_LOGW("SymbolLink %{public}s %{public}s repeat config, delete old", target, linkName);
275 }
276
277 SymbolLinkNode *node = CreateSymbolLinkNode();
278 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
279 node->destMode = GetChmodFromJson(config);
280 node->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
281 node->target = strdup(target);
282 node->linkName = strdup(linkName);
283 if (node->target == NULL || node->linkName == NULL) {
284 APPSPAWN_LOGE("Failed to get sourc or target path");
285 DeleteSandboxMountNode((SandboxMountNode *)node);
286 return NULL;
287 }
288 return node;
289 }
290
ParseSymbolLinksConfig(AppSpawnSandboxCfg *sandbox, const cJSON *symbolLinkConfigs, SandboxSection *section)291 APPSPAWN_STATIC int ParseSymbolLinksConfig(AppSpawnSandboxCfg *sandbox, const cJSON *symbolLinkConfigs,
292 SandboxSection *section)
293 {
294 APPSPAWN_CHECK_ONLY_EXPER(symbolLinkConfigs != NULL && cJSON_IsArray(symbolLinkConfigs), return -1);
295 uint32_t symlinkPointSize = cJSON_GetArraySize(symbolLinkConfigs);
296 for (uint32_t i = 0; i < symlinkPointSize; i++) {
297 cJSON *symConfig = cJSON_GetArrayItem(symbolLinkConfigs, i);
298 if (symConfig == NULL) {
299 continue;
300 }
301 SymbolLinkNode *node = DecodeSymbolLinksConfig(section, symConfig);
302 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
303 AddSandboxMountNode(&node->sandboxNode, section);
304 }
305 return 0;
306 }
307
ParseGidTableConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, SandboxSection *section)308 APPSPAWN_STATIC int ParseGidTableConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, SandboxSection *section)
309 {
310 APPSPAWN_CHECK(cJSON_IsArray(configs), return 0, "json is not array.");
311 uint32_t arrayLen = (uint32_t)cJSON_GetArraySize(configs);
312 APPSPAWN_CHECK_ONLY_EXPER(arrayLen > 0, return 0);
313 APPSPAWN_CHECK(arrayLen < APP_MAX_GIDS, arrayLen = APP_MAX_GIDS, "More gid in gids json.");
314
315 // 配置存在,以后面的配置为准
316 if (section->gidTable) {
317 free(section->gidTable);
318 section->gidTable = NULL;
319 section->gidCount = 0;
320 }
321 section->gidTable = (gid_t *)calloc(1, sizeof(gid_t) * arrayLen);
322 APPSPAWN_CHECK(section->gidTable != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory.");
323
324 for (uint32_t i = 0; i < arrayLen; i++) {
325 cJSON *item = cJSON_GetArrayItem(configs, i);
326 gid_t gid = 0;
327 if (cJSON_IsNumber(item)) {
328 gid = (gid_t)cJSON_GetNumberValue(item);
329 } else {
330 char *value = cJSON_GetStringValue(item);
331 gid = DecodeGid(value);
332 }
333 if (gid <= 0) {
334 continue;
335 }
336 section->gidTable[section->gidCount++] = gid;
337 }
338 return 0;
339 }
340
ParseMountGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig, SandboxSection *section)341 static int ParseMountGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig, SandboxSection *section)
342 {
343 APPSPAWN_CHECK(cJSON_IsArray(groupConfig),
344 return APPSPAWN_SANDBOX_INVALID, "Invalid mount-groups config %{public}s", section->name);
345
346 // 合并name-group
347 uint32_t count = (uint32_t)cJSON_GetArraySize(groupConfig);
348 APPSPAWN_LOGV("mount-group in section %{public}s %{public}u", section->name, count);
349 APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
350 count += section->number;
351 SandboxMountNode **nameGroups = (SandboxMountNode **)calloc(1, sizeof(SandboxMountNode *) * count);
352 APPSPAWN_CHECK(nameGroups != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory for group name");
353
354 uint32_t j = 0;
355 uint32_t number = 0;
356 for (j = 0; j < section->number; j++) { // copy old
357 if (section->nameGroups[j] == NULL) {
358 continue;
359 }
360 nameGroups[number++] = section->nameGroups[j];
361 }
362
363 SandboxNameGroupNode *mountNode = NULL;
364 for (uint32_t i = 0; i < count; i++) {
365 nameGroups[number] = NULL;
366
367 char *name = cJSON_GetStringValue(cJSON_GetArrayItem(groupConfig, i));
368 mountNode = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
369 if (mountNode == NULL) {
370 APPSPAWN_LOGE("Can not find name-group %{public}s", name);
371 continue;
372 }
373 // check type
374 if (strcmp(section->name, "system-const") == 0 && mountNode->destType != SANDBOX_TAG_SYSTEM_CONST) {
375 APPSPAWN_LOGE("Invalid name-group %{public}s", name);
376 continue;
377 }
378 // 过滤重复的节点
379 for (j = 0; j < section->number; j++) {
380 if (section->nameGroups[j] != NULL && section->nameGroups[j] == (SandboxMountNode *)mountNode) {
381 APPSPAWN_LOGE("Name-group %{public}s bas been set", name);
382 break;
383 }
384 }
385 if (j < section->number) {
386 continue;
387 }
388 nameGroups[number++] = (SandboxMountNode *)mountNode;
389 APPSPAWN_LOGV("Name-group %{public}d %{public}s set", section->number, name);
390 }
391 if (section->nameGroups != NULL) {
392 free(section->nameGroups);
393 }
394 section->nameGroups = nameGroups;
395 section->number = number;
396 APPSPAWN_LOGV("mount-group in section %{public}s %{public}u", section->name, section->number);
397 return 0;
398 }
399
ParseBaseConfig(AppSpawnSandboxCfg *sandbox, SandboxSection *section, const cJSON *configs)400 static int ParseBaseConfig(AppSpawnSandboxCfg *sandbox, SandboxSection *section, const cJSON *configs)
401 {
402 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
403 APPSPAWN_CHECK(cJSON_IsObject(configs),
404 return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", section->name);
405 APPSPAWN_LOGV("Parse sandbox %{public}s", section->name);
406
407 // "sandbox-switch": "ON", default sandbox switch is on
408 section->sandboxSwitch = GetBoolValueFromJsonObj(configs, "sandbox-switch", true);
409 // "sandbox-shared"
410 section->sandboxShared = GetBoolValueFromJsonObj(configs, "sandbox-shared", false);
411
412 int ret = 0;
413 cJSON *gidTabJson = cJSON_GetObjectItemCaseSensitive(configs, "gids");
414 if (gidTabJson) {
415 ret = ParseGidTableConfig(sandbox, gidTabJson, section);
416 APPSPAWN_CHECK(ret == 0, return ret, "Parse gids for %{public}s", section->name);
417 }
418
419 cJSON *pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-paths");
420 if (pathConfigs != NULL) { // mount-paths
421 ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_PATH);
422 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
423 }
424
425 pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-files");
426 if (pathConfigs != NULL) { // mount-files
427 ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_FILE);
428 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
429 }
430
431 pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "symbol-links");
432 if (pathConfigs != NULL) { // symbol-links
433 ret = ParseSymbolLinksConfig(sandbox, pathConfigs, section);
434 APPSPAWN_CHECK(ret == 0, return ret, "Parse symbol-links for %{public}s", section->name);
435 }
436
437 cJSON *groupConfig = cJSON_GetObjectItemCaseSensitive(configs, "mount-groups");
438 if (groupConfig != NULL) {
439 ret = ParseMountGroupsConfig(sandbox, groupConfig, section);
440 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-groups for %{public}s", section->name);
441 }
442 return 0;
443 }
444
ParsePackageNameConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *packageNameConfigs)445 static int ParsePackageNameConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *packageNameConfigs)
446 {
447 APPSPAWN_LOGV("Parse package-name config %{public}s", name);
448 SandboxPackageNameNode *node = (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, name);
449 if (node == NULL) {
450 node = CreateSandboxPackageNameNode(name);
451 }
452 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
453
454 int ret = ParseBaseConfig(sandbox, &node->section, packageNameConfigs);
455 if (ret != 0) {
456 DeleteSandboxSection((SandboxSection *)node);
457 return ret;
458 }
459 // success, insert section
460 AddSandboxSection(&node->section, &sandbox->packageNameQueue);
461 return 0;
462 }
463
ParseSpawnFlagsConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *flagsConfig)464 static int ParseSpawnFlagsConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *flagsConfig)
465 {
466 uint32_t flagIndex = GetFlagIndexFromJson(flagsConfig);
467 APPSPAWN_LOGV("Parse spawn-flags config %{public}s flagIndex %{public}u", name, flagIndex);
468 SandboxFlagsNode *node = (SandboxFlagsNode *)GetSandboxSection(&sandbox->spawnFlagsQueue, name);
469 if (node == NULL) {
470 node = CreateSandboxFlagsNode(name);
471 }
472 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
473 node->flagIndex = flagIndex;
474
475 int ret = ParseBaseConfig(sandbox, &node->section, flagsConfig);
476 if (ret != 0) {
477 DeleteSandboxSection((SandboxSection *)node);
478 return ret;
479 }
480 // success, insert section
481 AddSandboxSection(&node->section, &sandbox->spawnFlagsQueue);
482 return 0;
483 }
484
ParsePermissionConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *permissionConfig)485 static int ParsePermissionConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *permissionConfig)
486 {
487 APPSPAWN_LOGV("Parse permission config %{public}s", name);
488 SandboxPermissionNode *node = (SandboxPermissionNode *)GetSandboxSection(&sandbox->permissionQueue, name);
489 if (node == NULL) {
490 node = CreateSandboxPermissionNode(name);
491 }
492 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
493
494 int ret = ParseBaseConfig(sandbox, &node->section, permissionConfig);
495 if (ret != 0) {
496 DeleteSandboxSection((SandboxSection *)node);
497 return ret;
498 }
499 // success, insert section
500 AddSandboxSection(&node->section, &sandbox->permissionQueue);
501 return 0;
502 }
503
ParseNameGroup(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig)504 static SandboxNameGroupNode *ParseNameGroup(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig)
505 {
506 char *name = GetStringFromJsonObj(groupConfig, "name");
507 APPSPAWN_CHECK(name != NULL, return NULL, "No name in name group config");
508 APPSPAWN_LOGV("Parse name-group config %{public}s", name);
509 SandboxNameGroupNode *node = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
510 if (node == NULL) {
511 node = CreateSandboxNameGroupNode(name);
512 }
513 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
514
515 cJSON *obj = cJSON_GetObjectItemCaseSensitive(groupConfig, "mount-paths-deps");
516 if (obj) {
517 if (node->depNode) { // free repeat
518 DeleteSandboxMountNode((SandboxMountNode *)node->depNode);
519 }
520 node->depNode = DecodeMountPathConfig(NULL, obj, SANDBOX_TAG_MOUNT_PATH);
521 if (node->depNode == NULL) {
522 DeleteSandboxSection((SandboxSection *)node);
523 return NULL;
524 }
525 // "deps-mode": "not-exists"
526 node->depMode = GetMountModeFromConfig(groupConfig, "deps-mode", MOUNT_MODE_ALWAYS);
527 }
528
529 int ret = ParseBaseConfig(sandbox, &node->section, groupConfig);
530 if (ret != 0) {
531 DeleteSandboxSection((SandboxSection *)node);
532 return NULL;
533 }
534 // "type": "system-const",
535 // "caps": ["shared"],
536 node->destType = GetNameGroupTypeFromConfig(groupConfig, "type", SANDBOX_TAG_INVALID);
537 node->depMounted = 0;
538 // success, insert section
539 AddSandboxSection(&node->section, &sandbox->nameGroupsQueue);
540 return node;
541 }
542
ParseNameGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)543 static int ParseNameGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
544 {
545 APPSPAWN_CHECK(root != NULL, return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
546 cJSON *configs = cJSON_GetObjectItemCaseSensitive(root, "name-groups");
547 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
548 APPSPAWN_CHECK(cJSON_IsArray(configs), return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
549 int count = cJSON_GetArraySize(configs);
550 APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
551
552 sandbox->depNodeCount = 0;
553 for (int i = 0; i < count; i++) {
554 cJSON *json = cJSON_GetArrayItem(configs, i);
555 if (json == NULL) {
556 continue;
557 }
558 SandboxNameGroupNode *node = ParseNameGroup(sandbox, json);
559 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return APPSPAWN_SANDBOX_INVALID);
560 if (node->depNode) {
561 sandbox->depNodeCount++;
562 }
563 }
564 APPSPAWN_LOGV("ParseNameGroupsConfig depNodeCount %{public}d", sandbox->depNodeCount);
565 return 0;
566 }
567
ParseConditionalConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, const char *configName, int (*parseConfig)(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *configs))568 static int ParseConditionalConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, const char *configName,
569 int (*parseConfig)(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *configs))
570 {
571 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
572 APPSPAWN_CHECK(cJSON_IsArray(configs),
573 return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", configName);
574 int ret = 0;
575 int count = cJSON_GetArraySize(configs);
576 for (int i = 0; i < count; i++) {
577 cJSON *json = cJSON_GetArrayItem(configs, i);
578 if (json == NULL) {
579 continue;
580 }
581 char *name = GetStringFromJsonObj(json, "name");
582 if (name == NULL) {
583 APPSPAWN_LOGE("No name in %{public}s configs", configName);
584 continue;
585 }
586 ret = parseConfig(sandbox, name, json);
587 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
588 }
589 return 0;
590 }
591
ParseGlobalSandboxConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)592 static int ParseGlobalSandboxConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
593 {
594 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "global");
595 if (json) {
596 sandbox->sandboxNsFlags = GetSandboxNsFlags(json);
597 char *rootPath = GetStringFromJsonObj(json, "sandbox-root");
598 APPSPAWN_CHECK(rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "No root path in config");
599 if (sandbox->rootPath) {
600 free(sandbox->rootPath);
601 }
602 sandbox->rootPath = strdup(rootPath);
603 APPSPAWN_CHECK(sandbox->rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to copy root path");
604 sandbox->topSandboxSwitch = GetBoolValueFromJsonObj(json, "top-sandbox-switch", true);
605 }
606 return 0;
607 }
608
609 typedef struct TagParseJsonContext {
610 AppSpawnSandboxCfg *sandboxCfg;
611 }ParseJsonContext;
612
ParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context)613 APPSPAWN_STATIC int ParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context)
614 {
615 APPSPAWN_CHECK(root != NULL && context != NULL && context->sandboxCfg != NULL,
616 return APPSPAWN_SYSTEM_ERROR, "Invalid json");
617 AppSpawnSandboxCfg *sandbox = context->sandboxCfg;
618 int ret = ParseGlobalSandboxConfig(sandbox, root); // "global":
619 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
620 ret = ParseNameGroupsConfig(sandbox, root); // name-groups
621 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
622
623 // "required"
624 cJSON *required = cJSON_GetObjectItemCaseSensitive(root, "required");
625 if (required) {
626 cJSON *config = NULL;
627 cJSON_ArrayForEach(config, required)
628 {
629 APPSPAWN_LOGI("Sandbox required config: %{public}s", config->string);
630 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, config->string);
631 if (section == NULL) {
632 section = CreateSandboxSection(config->string, sizeof(SandboxSection), SANDBOX_TAG_REQUIRED);
633 }
634 APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return -1);
635
636 ret = ParseBaseConfig(sandbox, section, config);
637 if (ret != 0) {
638 DeleteSandboxSection(section);
639 return ret;
640 }
641 // success, insert section
642 AddSandboxSection(section, &sandbox->requiredQueue);
643 }
644 }
645
646 // conditional
647 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional");
648 if (json != NULL) {
649 // permission
650 cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission");
651 ret = ParseConditionalConfig(sandbox, config, "permission", ParsePermissionConfig);
652 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
653 // spawn-flag
654 config = cJSON_GetObjectItemCaseSensitive(json, "spawn-flag");
655 ret = ParseConditionalConfig(sandbox, config, "spawn-flag", ParseSpawnFlagsConfig);
656 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
657 // package-name
658 config = cJSON_GetObjectItemCaseSensitive(json, "package-name");
659 ret = ParseConditionalConfig(sandbox, config, "package-name", ParsePackageNameConfig);
660 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
661 }
662 return ret;
663 }
664
GetSandboxNameByMode(RunMode mode)665 APPSPAWN_STATIC const char *GetSandboxNameByMode(RunMode mode)
666 {
667 if (mode == MODE_FOR_NATIVE_SPAWN) {
668 return ISOLATED_SANDBOX_FILE_NAME;
669 }
670 if (mode == MODE_FOR_NWEB_SPAWN || mode == MODE_FOR_NWEB_COLD_RUN) {
671 return WEB_SANDBOX_FILE_NAME;
672 }
673 return APP_SANDBOX_FILE_NAME;
674 }
675
LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, RunMode mode)676 int LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, RunMode mode)
677 {
678 APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_ARG_INVALID);
679 const char *sandboxName = GetSandboxNameByMode(mode);
680 if (sandbox->depGroupNodes != NULL) {
681 APPSPAWN_LOGW("Sandbox has been load");
682 return 0;
683 }
684 ParseJsonContext context = {};
685 context.sandboxCfg = sandbox;
686 int ret = ParseJsonConfig("etc/sandbox", sandboxName, ParseAppSandboxConfig, &context);
687 if (ret == APPSPAWN_SANDBOX_NONE) {
688 APPSPAWN_LOGW("No sandbox config");
689 ret = 0;
690 }
691 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
692 sandbox->pidNamespaceSupport = AppSandboxPidNsIsSupport();
693 sandbox->appFullMountEnable = CheckAppFullMountEnable();
694 APPSPAWN_LOGI("Sandbox pidNamespaceSupport: %{public}d appFullMountEnable: %{public}d",
695 sandbox->pidNamespaceSupport, sandbox->appFullMountEnable);
696
697 uint32_t depNodeCount = sandbox->depNodeCount;
698 APPSPAWN_CHECK_ONLY_EXPER(depNodeCount > 0, return ret);
699
700 sandbox->depGroupNodes = (SandboxNameGroupNode **)calloc(1, sizeof(SandboxNameGroupNode *) * depNodeCount);
701 APPSPAWN_CHECK(sandbox->depGroupNodes != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed alloc memory ");
702 sandbox->depNodeCount = 0;
703 ListNode *node = sandbox->nameGroupsQueue.front.next;
704 while (node != &sandbox->nameGroupsQueue.front) {
705 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)ListEntry(node, SandboxMountNode, node);
706 if (groupNode->depNode) {
707 sandbox->depGroupNodes[sandbox->depNodeCount++] = groupNode;
708 }
709 node = node->next;
710 }
711 APPSPAWN_LOGI("LoadAppSandboxConfig depNodeCount %{public}d", sandbox->depNodeCount);
712
713 return 0;
714 }
715