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 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 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 PathMountNode *tmp = GetPathMountNode(section, type, srcPath, dstPath);
213 if (tmp != NULL) { // 删除老的节点,保存新的节点
214 DeleteSandboxMountNode((SandboxMountNode *)tmp);
215 APPSPAWN_LOGW("path %{public}s %{public}s repeat config, delete old", srcPath, dstPath);
216 }
217
218 cJSON *demandInfo = cJSON_GetObjectItemCaseSensitive(config, "create-on-demand");
219 PathMountNode *sandboxNode = CreatePathMountNode(type, demandInfo != NULL);
220 APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return NULL);
221 sandboxNode->createDemand = demandInfo != NULL;
222 sandboxNode->source = strdup(srcPath);
223 sandboxNode->target = strdup(dstPath);
224
225 sandboxNode->destMode = GetChmodFromJson(config);
226 sandboxNode->mountSharedFlag = GetBoolValueFromJsonObj(config, "mount-shared-flag", false);
227 sandboxNode->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
228
229 sandboxNode->category = GetMountCategory(GetStringFromJsonObj(config, "category"));
230 const char *value = GetStringFromJsonObj(config, "app-apl-name");
231 if (value != NULL) {
232 sandboxNode->appAplName = strdup(value);
233 }
234 FillPathDemandInfo(demandInfo, sandboxNode);
235
236 if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
237 APPSPAWN_LOGE("Failed to get sourc or target path");
238 DeleteSandboxMountNode((SandboxMountNode *)sandboxNode);
239 return NULL;
240 }
241 return sandboxNode;
242 }
243
ParseMountPathsConfig(AppSpawnSandboxCfg * sandbox,const cJSON * mountConfigs,SandboxSection * section,uint32_t type)244 static int ParseMountPathsConfig(AppSpawnSandboxCfg *sandbox,
245 const cJSON *mountConfigs, SandboxSection *section, uint32_t type)
246 {
247 APPSPAWN_CHECK_ONLY_EXPER(mountConfigs != NULL && cJSON_IsArray(mountConfigs), return -1);
248
249 uint32_t mountPointSize = cJSON_GetArraySize(mountConfigs);
250 for (uint32_t i = 0; i < mountPointSize; i++) {
251 cJSON *mntJson = cJSON_GetArrayItem(mountConfigs, i);
252 if (mntJson == NULL) {
253 continue;
254 }
255 PathMountNode *sandboxNode = DecodeMountPathConfig(section, mntJson, type);
256 APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, continue);
257 AddSandboxMountNode(&sandboxNode->sandboxNode, section);
258 }
259 return 0;
260 }
261
DecodeSymbolLinksConfig(const SandboxSection * section,const cJSON * config)262 static SymbolLinkNode *DecodeSymbolLinksConfig(const SandboxSection *section, const cJSON *config)
263 {
264 const char *target = GetStringFromJsonObj(config, "target-name");
265 const char *linkName = GetStringFromJsonObj(config, "link-name");
266 if (target == NULL || linkName == NULL) {
267 return NULL;
268 }
269
270 SymbolLinkNode *tmp = GetSymbolLinkNode(section, target, linkName);
271 if (tmp != NULL) { // 删除老的节点,保存新的节点
272 DeleteSandboxMountNode((SandboxMountNode *)tmp);
273 APPSPAWN_LOGW("SymbolLink %{public}s %{public}s repeat config, delete old", target, linkName);
274 }
275
276 SymbolLinkNode *node = CreateSymbolLinkNode();
277 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
278 node->destMode = GetChmodFromJson(config);
279 node->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
280 node->target = strdup(target);
281 node->linkName = strdup(linkName);
282 if (node->target == NULL || node->linkName == NULL) {
283 APPSPAWN_LOGE("Failed to get sourc or target path");
284 DeleteSandboxMountNode((SandboxMountNode *)node);
285 return NULL;
286 }
287 return node;
288 }
289
ParseSymbolLinksConfig(AppSpawnSandboxCfg * sandbox,const cJSON * symbolLinkConfigs,SandboxSection * section)290 static int ParseSymbolLinksConfig(AppSpawnSandboxCfg *sandbox, const cJSON *symbolLinkConfigs, SandboxSection *section)
291 {
292 APPSPAWN_CHECK_ONLY_EXPER(symbolLinkConfigs != NULL && cJSON_IsArray(symbolLinkConfigs), return -1);
293 uint32_t symlinkPointSize = cJSON_GetArraySize(symbolLinkConfigs);
294 for (uint32_t i = 0; i < symlinkPointSize; i++) {
295 cJSON *symConfig = cJSON_GetArrayItem(symbolLinkConfigs, i);
296 if (symConfig == NULL) {
297 continue;
298 }
299 SymbolLinkNode *node = DecodeSymbolLinksConfig(section, symConfig);
300 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
301 AddSandboxMountNode(&node->sandboxNode, section);
302 }
303 return 0;
304 }
305
ParseGidTableConfig(AppSpawnSandboxCfg * sandbox,const cJSON * configs,SandboxSection * section)306 static int ParseGidTableConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, SandboxSection *section)
307 {
308 APPSPAWN_CHECK(cJSON_IsArray(configs), return 0, "json is not array.");
309 uint32_t arrayLen = (uint32_t)cJSON_GetArraySize(configs);
310 APPSPAWN_CHECK_ONLY_EXPER(arrayLen > 0, return 0);
311 APPSPAWN_CHECK(arrayLen < APP_MAX_GIDS, arrayLen = APP_MAX_GIDS, "More gid in gids json.");
312
313 // 配置存在,以后面的配置为准
314 if (section->gidTable) {
315 free(section->gidTable);
316 section->gidTable = NULL;
317 section->gidCount = 0;
318 }
319 section->gidTable = (gid_t *)calloc(1, sizeof(gid_t) * arrayLen);
320 APPSPAWN_CHECK(section->gidTable != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory.");
321
322 for (uint32_t i = 0; i < arrayLen; i++) {
323 cJSON *item = cJSON_GetArrayItem(configs, i);
324 gid_t gid = 0;
325 if (cJSON_IsNumber(item)) {
326 gid = (gid_t)cJSON_GetNumberValue(item);
327 } else {
328 char *value = cJSON_GetStringValue(item);
329 gid = DecodeGid(value);
330 }
331 if (gid <= 0) {
332 continue;
333 }
334 section->gidTable[section->gidCount++] = gid;
335 }
336 return 0;
337 }
338
ParseMountGroupsConfig(AppSpawnSandboxCfg * sandbox,const cJSON * groupConfig,SandboxSection * section)339 static int ParseMountGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig, SandboxSection *section)
340 {
341 APPSPAWN_CHECK(cJSON_IsArray(groupConfig),
342 return APPSPAWN_SANDBOX_INVALID, "Invalid mount-groups config %{public}s", section->name);
343
344 // 合并name-group
345 uint32_t count = (uint32_t)cJSON_GetArraySize(groupConfig);
346 APPSPAWN_LOGV("mount-group in section %{public}s %{public}u", section->name, count);
347 APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
348 count += section->number;
349 SandboxMountNode **nameGroups = (SandboxMountNode **)calloc(1, sizeof(SandboxMountNode *) * count);
350 APPSPAWN_CHECK(nameGroups != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory for group name");
351
352 uint32_t j = 0;
353 uint32_t number = 0;
354 for (j = 0; j < section->number; j++) { // copy old
355 if (section->nameGroups[j] == NULL) {
356 continue;
357 }
358 nameGroups[number++] = section->nameGroups[j];
359 }
360
361 SandboxNameGroupNode *mountNode = NULL;
362 for (uint32_t i = 0; i < count; i++) {
363 nameGroups[number] = NULL;
364
365 char *name = cJSON_GetStringValue(cJSON_GetArrayItem(groupConfig, i));
366 mountNode = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
367 if (mountNode == NULL) {
368 APPSPAWN_LOGE("Can not find name-group %{public}s", name);
369 continue;
370 }
371 // check type
372 if (strcmp(section->name, "system-const") == 0 && mountNode->destType != SANDBOX_TAG_SYSTEM_CONST) {
373 APPSPAWN_LOGE("Invalid name-group %{public}s", name);
374 continue;
375 }
376 // 过滤重复的节点
377 for (j = 0; j < section->number; j++) {
378 if (section->nameGroups[j] != NULL && section->nameGroups[j] == (SandboxMountNode *)mountNode) {
379 APPSPAWN_LOGE("Name-group %{public}s bas been set", name);
380 break;
381 }
382 }
383 if (j < section->number) {
384 continue;
385 }
386 nameGroups[number++] = (SandboxMountNode *)mountNode;
387 APPSPAWN_LOGV("Name-group %{public}d %{public}s set", section->number, name);
388 }
389 if (section->nameGroups != NULL) {
390 free(section->nameGroups);
391 }
392 section->nameGroups = nameGroups;
393 section->number = number;
394 APPSPAWN_LOGV("mount-group in section %{public}s %{public}u", section->name, section->number);
395 return 0;
396 }
397
ParseBaseConfig(AppSpawnSandboxCfg * sandbox,SandboxSection * section,const cJSON * configs)398 static int ParseBaseConfig(AppSpawnSandboxCfg *sandbox, SandboxSection *section, const cJSON *configs)
399 {
400 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
401 APPSPAWN_CHECK(cJSON_IsObject(configs),
402 return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", section->name);
403 APPSPAWN_LOGV("Parse sandbox %{public}s", section->name);
404 // "sandbox-switch": "ON", default sandbox switch is on
405 section->sandboxSwitch = GetBoolValueFromJsonObj(configs, "sandbox-switch", true);
406 // "sandbox-shared"
407 section->sandboxShared = GetBoolValueFromJsonObj(configs, "sandbox-shared", false);
408
409 int ret = 0;
410 cJSON *gidTabJson = cJSON_GetObjectItemCaseSensitive(configs, "gids");
411 if (gidTabJson) {
412 ret = ParseGidTableConfig(sandbox, gidTabJson, section);
413 APPSPAWN_CHECK(ret == 0, return ret, "Parse gids for %{public}s", section->name);
414 }
415 cJSON *pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-paths");
416 if (pathConfigs != NULL) { // mount-paths
417 ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_PATH);
418 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
419 }
420 pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-files");
421 if (pathConfigs != NULL) { // mount-files
422 ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_FILE);
423 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
424 }
425 pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "symbol-links");
426 if (pathConfigs != NULL) { // symbol-links
427 ret = ParseSymbolLinksConfig(sandbox, pathConfigs, section);
428 APPSPAWN_CHECK(ret == 0, return ret, "Parse symbol-links for %{public}s", section->name);
429 }
430 cJSON *groupConfig = cJSON_GetObjectItemCaseSensitive(configs, "mount-groups");
431 if (groupConfig != NULL) {
432 ret = ParseMountGroupsConfig(sandbox, groupConfig, section);
433 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-groups for %{public}s", section->name);
434 }
435 return 0;
436 }
437
ParsePackageNameConfig(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * packageNameConfigs)438 static int ParsePackageNameConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *packageNameConfigs)
439 {
440 APPSPAWN_LOGV("Parse package-name config %{public}s", name);
441 SandboxPackageNameNode *node = (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, name);
442 if (node == NULL) {
443 node = CreateSandboxPackageNameNode(name);
444 }
445 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
446
447 int ret = ParseBaseConfig(sandbox, &node->section, packageNameConfigs);
448 if (ret != 0) {
449 DeleteSandboxSection((SandboxSection *)node);
450 return ret;
451 }
452 // success, insert section
453 AddSandboxSection(&node->section, &sandbox->packageNameQueue);
454 return 0;
455 }
456
ParseSpawnFlagsConfig(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * flagsConfig)457 static int ParseSpawnFlagsConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *flagsConfig)
458 {
459 uint32_t flagIndex = GetFlagIndexFromJson(flagsConfig);
460 APPSPAWN_LOGV("Parse spawn-flags config %{public}s flagIndex %{public}u", name, flagIndex);
461 SandboxFlagsNode *node = (SandboxFlagsNode *)GetSandboxSection(&sandbox->spawnFlagsQueue, name);
462 if (node == NULL) {
463 node = CreateSandboxFlagsNode(name);
464 }
465 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
466 node->flagIndex = flagIndex;
467
468 int ret = ParseBaseConfig(sandbox, &node->section, flagsConfig);
469 if (ret != 0) {
470 DeleteSandboxSection((SandboxSection *)node);
471 return ret;
472 }
473 // success, insert section
474 AddSandboxSection(&node->section, &sandbox->spawnFlagsQueue);
475 return 0;
476 }
477
ParsePermissionConfig(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * permissionConfig)478 static int ParsePermissionConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *permissionConfig)
479 {
480 APPSPAWN_LOGV("Parse permission config %{public}s", name);
481 SandboxPermissionNode *node = (SandboxPermissionNode *)GetSandboxSection(&sandbox->permissionQueue, name);
482 if (node == NULL) {
483 node = CreateSandboxPermissionNode(name);
484 }
485 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
486
487 int ret = ParseBaseConfig(sandbox, &node->section, permissionConfig);
488 if (ret != 0) {
489 DeleteSandboxSection((SandboxSection *)node);
490 return ret;
491 }
492 // success, insert section
493 AddSandboxSection(&node->section, &sandbox->permissionQueue);
494 return 0;
495 }
496
ParseNameGroup(AppSpawnSandboxCfg * sandbox,const cJSON * groupConfig)497 static SandboxNameGroupNode *ParseNameGroup(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig)
498 {
499 char *name = GetStringFromJsonObj(groupConfig, "name");
500 APPSPAWN_CHECK(name != NULL, return NULL, "No name in name group config");
501 APPSPAWN_LOGV("Parse name-group config %{public}s", name);
502 SandboxNameGroupNode *node = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
503 if (node == NULL) {
504 node = CreateSandboxNameGroupNode(name);
505 }
506 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
507
508 cJSON *obj = cJSON_GetObjectItemCaseSensitive(groupConfig, "mount-paths-deps");
509 if (obj) {
510 if (node->depNode) { // free repeat
511 DeleteSandboxMountNode((SandboxMountNode *)node->depNode);
512 }
513 node->depNode = DecodeMountPathConfig(NULL, obj, SANDBOX_TAG_MOUNT_PATH);
514 if (node->depNode == NULL) {
515 DeleteSandboxSection((SandboxSection *)node);
516 return NULL;
517 }
518 // "deps-mode": "not-exists"
519 node->depMode = GetMountModeFromConfig(groupConfig, "deps-mode", MOUNT_MODE_ALWAYS);
520 }
521
522 int ret = ParseBaseConfig(sandbox, &node->section, groupConfig);
523 if (ret != 0) {
524 DeleteSandboxSection((SandboxSection *)node);
525 return NULL;
526 }
527 // "type": "system-const",
528 // "caps": ["shared"],
529 node->destType = GetNameGroupTypeFromConfig(groupConfig, "type", SANDBOX_TAG_INVALID);
530 // success, insert section
531 AddSandboxSection(&node->section, &sandbox->nameGroupsQueue);
532 return node;
533 }
534
ParseNameGroupsConfig(AppSpawnSandboxCfg * sandbox,const cJSON * root)535 static int ParseNameGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
536 {
537 APPSPAWN_CHECK(root != NULL, return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
538 cJSON *configs = cJSON_GetObjectItemCaseSensitive(root, "name-groups");
539 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
540 APPSPAWN_CHECK(cJSON_IsArray(configs), return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
541 int count = cJSON_GetArraySize(configs);
542 APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
543
544 sandbox->depNodeCount = 0;
545 for (int i = 0; i < count; i++) {
546 cJSON *json = cJSON_GetArrayItem(configs, i);
547 if (json == NULL) {
548 continue;
549 }
550 SandboxNameGroupNode *node = ParseNameGroup(sandbox, json);
551 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return APPSPAWN_SANDBOX_INVALID);
552 if (node->depNode) {
553 sandbox->depNodeCount++;
554 }
555 }
556 APPSPAWN_LOGV("ParseNameGroupsConfig depNodeCount %{public}d", sandbox->depNodeCount);
557 return 0;
558 }
559
ParseConditionalConfig(AppSpawnSandboxCfg * sandbox,const cJSON * configs,const char * configName,int (* parseConfig)(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * configs))560 static int ParseConditionalConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, const char *configName,
561 int (*parseConfig)(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *configs))
562 {
563 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
564 APPSPAWN_CHECK(cJSON_IsArray(configs),
565 return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", configName);
566 int ret = 0;
567 int count = cJSON_GetArraySize(configs);
568 for (int i = 0; i < count; i++) {
569 cJSON *json = cJSON_GetArrayItem(configs, i);
570 if (json == NULL) {
571 continue;
572 }
573 char *name = GetStringFromJsonObj(json, "name");
574 if (name == NULL) {
575 APPSPAWN_LOGE("No name in %{public}s configs", configName);
576 continue;
577 }
578 ret = parseConfig(sandbox, name, json);
579 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
580 }
581 return 0;
582 }
583
ParseGlobalSandboxConfig(AppSpawnSandboxCfg * sandbox,const cJSON * root)584 static int ParseGlobalSandboxConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
585 {
586 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "global");
587 if (json) {
588 sandbox->sandboxNsFlags = GetSandboxNsFlags(json);
589 char *rootPath = GetStringFromJsonObj(json, "sandbox-root");
590 APPSPAWN_CHECK(rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "No root path in config");
591 if (sandbox->rootPath) {
592 free(sandbox->rootPath);
593 }
594 sandbox->rootPath = strdup(rootPath);
595 APPSPAWN_CHECK(sandbox->rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to copy root path");
596 sandbox->topSandboxSwitch = GetBoolValueFromJsonObj(json, "top-sandbox-switch", true);
597 }
598 return 0;
599 }
600
601 typedef struct TagParseJsonContext {
602 AppSpawnSandboxCfg *sandboxCfg;
603 }ParseJsonContext;
604
ParseAppSandboxConfig(const cJSON * root,ParseJsonContext * context)605 APPSPAWN_STATIC int ParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context)
606 {
607 APPSPAWN_CHECK(root != NULL && context != NULL && context->sandboxCfg != NULL,
608 return APPSPAWN_SYSTEM_ERROR, "Invalid json");
609 AppSpawnSandboxCfg *sandbox = context->sandboxCfg;
610 int ret = ParseGlobalSandboxConfig(sandbox, root); // "global":
611 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
612 ret = ParseNameGroupsConfig(sandbox, root); // name-groups
613 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
614
615 // "required"
616 cJSON *required = cJSON_GetObjectItemCaseSensitive(root, "required");
617 if (required) {
618 cJSON *config = NULL;
619 cJSON_ArrayForEach(config, required)
620 {
621 APPSPAWN_LOGI("Sandbox required config: %{public}s", config->string);
622 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, config->string);
623 if (section == NULL) {
624 section = CreateSandboxSection(config->string, sizeof(SandboxSection), SANDBOX_TAG_REQUIRED);
625 }
626 APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return -1);
627
628 ret = ParseBaseConfig(sandbox, section, config);
629 if (ret != 0) {
630 DeleteSandboxSection(section);
631 return ret;
632 }
633 // success, insert section
634 AddSandboxSection(section, &sandbox->requiredQueue);
635 }
636 }
637
638 // conditional
639 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional");
640 if (json != NULL) {
641 // permission
642 cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission");
643 ret = ParseConditionalConfig(sandbox, config, "permission", ParsePermissionConfig);
644 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
645 // spawn-flag
646 config = cJSON_GetObjectItemCaseSensitive(json, "spawn-flag");
647 ret = ParseConditionalConfig(sandbox, config, "spawn-flag", ParseSpawnFlagsConfig);
648 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
649 // package-name
650 config = cJSON_GetObjectItemCaseSensitive(json, "package-name");
651 ret = ParseConditionalConfig(sandbox, config, "package-name", ParsePackageNameConfig);
652 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
653 }
654 return ret;
655 }
656
GetSandboxNameByMode(RunMode mode)657 APPSPAWN_STATIC const char *GetSandboxNameByMode(RunMode mode)
658 {
659 if (mode == MODE_FOR_NATIVE_SPAWN) {
660 return ISOLATED_SANDBOX_FILE_NAME;
661 }
662
663 return APP_SANDBOX_FILE_NAME;
664 }
665
LoadAppSandboxConfig(AppSpawnSandboxCfg * sandbox,RunMode mode)666 int LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, RunMode mode)
667 {
668 APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_ARG_INVALID);
669 const char *sandboxName = GetSandboxNameByMode(mode);
670 if (sandbox->depGroupNodes != NULL) {
671 APPSPAWN_LOGW("Sandbox has been load");
672 return 0;
673 }
674 ParseJsonContext context = {};
675 context.sandboxCfg = sandbox;
676 int ret = ParseJsonConfig("etc/sandbox", sandboxName, ParseAppSandboxConfig, &context);
677 if (ret == APPSPAWN_SANDBOX_NONE) {
678 APPSPAWN_LOGW("No sandbox config");
679 ret = 0;
680 }
681 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
682 sandbox->pidNamespaceSupport = AppSandboxPidNsIsSupport();
683 sandbox->appFullMountEnable = CheckAppFullMountEnable();
684 APPSPAWN_LOGI("Sandbox pidNamespaceSupport: %{public}d appFullMountEnable: %{public}d",
685 sandbox->pidNamespaceSupport, sandbox->appFullMountEnable);
686
687 uint32_t depNodeCount = sandbox->depNodeCount;
688 APPSPAWN_CHECK_ONLY_EXPER(depNodeCount > 0, return ret);
689
690 sandbox->depGroupNodes = (SandboxNameGroupNode **)calloc(1, sizeof(SandboxNameGroupNode *) * depNodeCount);
691 APPSPAWN_CHECK(sandbox->depGroupNodes != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed alloc memory ");
692 sandbox->depNodeCount = 0;
693 ListNode *node = sandbox->nameGroupsQueue.front.next;
694 while (node != &sandbox->nameGroupsQueue.front) {
695 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)ListEntry(node, SandboxMountNode, node);
696 if (groupNode->depNode) {
697 sandbox->depGroupNodes[sandbox->depNodeCount++] = groupNode;
698 }
699 node = node->next;
700 }
701 APPSPAWN_LOGI("LoadAppSandboxConfig depNodeCount %{public}d", sandbox->depNodeCount);
702
703 return 0;
704 }
705