• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     {"PREINSTALLED_HAP", (unsigned long)APP_FLAGS_PRE_INSTALLED_HAP},
50     {"CUSTOM_SANDBOX_HAP", (unsigned long)APP_FLAGS_CUSTOM_SANDBOX}
51 };
52 
53 static const SandboxFlagInfo MOUNT_MODE_MAP[] = {
54     {"not-exists", (unsigned long)MOUNT_MODE_NOT_EXIST},
55     {"always", (unsigned long)MOUNT_MODE_ALWAYS}
56 };
57 
58 static const SandboxFlagInfo NAME_GROUP_TYPE_MAP[] = {
59     {"system-const", (unsigned long)SANDBOX_TAG_SYSTEM_CONST},
60     {"app-variable", (unsigned long)SANDBOX_TAG_APP_VARIABLE}
61 };
62 
CreatePathMountNode(uint32_t type,uint32_t hasDemandInfo)63 static inline PathMountNode *CreatePathMountNode(uint32_t type, uint32_t hasDemandInfo)
64 {
65     uint32_t len = hasDemandInfo ? sizeof(PathDemandInfo) : 0;
66     return (PathMountNode *)CreateSandboxMountNode(sizeof(PathMountNode) + len, type);
67 }
68 
CreateSymbolLinkNode(void)69 static inline SymbolLinkNode *CreateSymbolLinkNode(void)
70 {
71     return (SymbolLinkNode *)CreateSandboxMountNode(sizeof(SymbolLinkNode), SANDBOX_TAG_SYMLINK);
72 }
73 
CreateSandboxPackageNameNode(const char * name)74 static inline SandboxPackageNameNode *CreateSandboxPackageNameNode(const char *name)
75 {
76     return (SandboxPackageNameNode *)CreateSandboxSection(name,
77         sizeof(SandboxPackageNameNode), SANDBOX_TAG_PACKAGE_NAME);
78 }
79 
CreateSandboxFlagsNode(const char * name)80 static inline SandboxFlagsNode *CreateSandboxFlagsNode(const char *name)
81 {
82     return (SandboxFlagsNode *)CreateSandboxSection(name, sizeof(SandboxFlagsNode), SANDBOX_TAG_SPAWN_FLAGS);
83 }
84 
CreateSandboxNameGroupNode(const char * name)85 static inline SandboxNameGroupNode *CreateSandboxNameGroupNode(const char *name)
86 {
87     return (SandboxNameGroupNode *)CreateSandboxSection(name, sizeof(SandboxNameGroupNode), SANDBOX_TAG_NAME_GROUP);
88 }
89 
CreateSandboxPermissionNode(const char * name)90 static inline SandboxPermissionNode *CreateSandboxPermissionNode(const char *name)
91 {
92     size_t len = sizeof(SandboxPermissionNode);
93     SandboxPermissionNode *node = (SandboxPermissionNode *)CreateSandboxSection(name, len, SANDBOX_TAG_PERMISSION);
94     APPSPAWN_CHECK(node != NULL, return NULL, "Failed to create permission node");
95     node->permissionIndex = 0;
96     return node;
97 }
98 
GetBoolParameter(const char * param,bool value)99 static inline bool GetBoolParameter(const char *param, bool value)
100 {
101     char tmp[32] = {0};  // 32 max
102     int ret = GetParameter(param, "", tmp, sizeof(tmp));
103     APPSPAWN_LOGV("GetBoolParameter key %{public}s ret %{public}d result: %{public}s", param, ret, tmp);
104     if (ret > 0 && strcmp(tmp, "false") == 0) {
105         return false;
106     }
107     if (ret > 0 && strcmp(tmp, "true") == 0) {
108         return true;
109     }
110     return value;
111 }
112 
AppSandboxPidNsIsSupport(void)113 static inline bool AppSandboxPidNsIsSupport(void)
114 {
115     // only set false, return false
116     return GetBoolParameter("const.sandbox.pidns.support", true);
117 }
118 
CheckAppFullMountEnable(void)119 static inline bool CheckAppFullMountEnable(void)
120 {
121     return GetBoolParameter("const.filemanager.full_mount.enable", false);
122 }
123 
GetMountModeFromConfig(const cJSON * config,const char * key,unsigned long def)124 APPSPAWN_STATIC unsigned long GetMountModeFromConfig(const cJSON *config, const char *key, unsigned long def)
125 {
126     char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key));
127     if (value == NULL) {
128         return def;
129     }
130     const SandboxFlagInfo *info = GetSandboxFlagInfo(value, MOUNT_MODE_MAP, ARRAY_LENGTH(MOUNT_MODE_MAP));
131     if (info != NULL) {
132         return info->flags;
133     }
134     return def;
135 }
136 
GetNameGroupTypeFromConfig(const cJSON * config,const char * key,unsigned long def)137 static uint32_t GetNameGroupTypeFromConfig(const cJSON *config, const char *key, unsigned long def)
138 {
139     char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key));
140     if (value == NULL) {
141         return def;
142     }
143     const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAME_GROUP_TYPE_MAP, ARRAY_LENGTH(NAME_GROUP_TYPE_MAP));
144     if (info != NULL) {
145         return (uint32_t)info->flags;
146     }
147     return def;
148 }
149 
GetSandboxNsFlags(const cJSON * appConfig)150 static uint32_t GetSandboxNsFlags(const cJSON *appConfig)
151 {
152     uint32_t nsFlags = 0;
153     cJSON *obj = cJSON_GetObjectItemCaseSensitive(appConfig, "sandbox-ns-flags");
154     if (obj == NULL || !cJSON_IsArray(obj)) {
155         return nsFlags;
156     }
157     int count = cJSON_GetArraySize(obj);
158     for (int i = 0; i < count; i++) {
159         char *value = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
160         const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAMESPACE_FLAGS_MAP, ARRAY_LENGTH(NAMESPACE_FLAGS_MAP));
161         if (info != NULL) {
162             nsFlags |= info->flags;
163         }
164     }
165     return nsFlags;
166 }
167 
SetMode(const char * str,void * context)168 static int SetMode(const char *str, void *context)
169 {
170     mode_t *mode = (mode_t *)context;
171     *mode |= GetPathMode(str);
172     return 0;
173 }
174 
GetChmodFromJson(const cJSON * config)175 static mode_t GetChmodFromJson(const cJSON *config)
176 {
177     mode_t mode = 0;
178     char *modeStrs = GetStringFromJsonObj(config, "dest-mode");
179     if (modeStrs == NULL) {
180         return mode;
181     }
182     (void)StringSplit(modeStrs, "|", (void *)&mode, SetMode);
183     return mode;
184 }
185 
GetFlagIndexFromJson(const cJSON * config)186 APPSPAWN_STATIC uint32_t GetFlagIndexFromJson(const cJSON *config)
187 {
188     char *flagStr = GetStringFromJsonObj(config, "name");
189     if (flagStr == NULL) {
190         return 0;
191     }
192     const SandboxFlagInfo *info = GetSandboxFlagInfo(flagStr, FLAGE_POINT_MAP, ARRAY_LENGTH(FLAGE_POINT_MAP));
193     if (info != NULL) {
194         return info->flags;
195     }
196     return 0;
197 }
198 
FillPathDemandInfo(const cJSON * config,PathMountNode * sandboxNode)199 static void FillPathDemandInfo(const cJSON *config, PathMountNode *sandboxNode)
200 {
201     APPSPAWN_CHECK_ONLY_EXPER(config != NULL, return);
202     sandboxNode->demandInfo->uid = GetIntValueFromJsonObj(config, "uid", -1);
203     sandboxNode->demandInfo->gid = GetIntValueFromJsonObj(config, "gid", -1);
204     sandboxNode->demandInfo->mode = GetIntValueFromJsonObj(config, "ugo", -1);
205 }
206 
DecodeDecPolicyPaths(const cJSON * config,PathMountNode * sandboxNode)207 static int32_t DecodeDecPolicyPaths(const cJSON *config, PathMountNode *sandboxNode)
208 {
209     if (config == NULL || sandboxNode == NULL) {
210         return APPSPAWN_ARG_INVALID;
211     }
212 
213     sandboxNode->decPolicyPaths.decPathCount = 0;
214     sandboxNode->decPolicyPaths.decPath = NULL;
215 
216     cJSON *pathArray = cJSON_GetObjectItemCaseSensitive(config, "dec-paths");
217     if (pathArray == NULL || !cJSON_IsArray(pathArray)) {
218         return 0;
219     }
220 
221     int pathCount = cJSON_GetArraySize(pathArray);
222     if (pathCount == 0) {
223         return 0;
224     }
225     size_t decPathSize = pathCount * sizeof(char *);
226     sandboxNode->decPolicyPaths.decPath = (char **)malloc(decPathSize);
227     if (sandboxNode->decPolicyPaths.decPath == NULL) {
228         return APPSPAWN_ERROR_UTILS_MEM_FAIL;
229     }
230 
231     for (int i = 0; i < pathCount; i++) {
232         cJSON *pathItem = cJSON_GetArrayItem(pathArray, i);
233         if (!cJSON_IsString(pathItem)) {
234             APPSPAWN_LOGE("path parse failed");
235             goto ERROR;
236         }
237         sandboxNode->decPolicyPaths.decPath[i] = strdup(pathItem->valuestring);
238         if (sandboxNode->decPolicyPaths.decPath[i] == NULL) {
239             goto ERROR;
240         }
241         sandboxNode->decPolicyPaths.decPathCount++;
242     }
243     return 0;
244 
245 ERROR:
246     for (int i = 0; i < pathCount; i++) {
247         if (sandboxNode->decPolicyPaths.decPath[i] != NULL) {
248             free(sandboxNode->decPolicyPaths.decPath[i]);
249             sandboxNode->decPolicyPaths.decPath[i] = NULL;
250         }
251     }
252     sandboxNode->decPolicyPaths.decPathCount = 0;
253     free(sandboxNode->decPolicyPaths.decPath);
254     sandboxNode->decPolicyPaths.decPath = NULL;
255     return -1;
256 }
257 
DecodeMountPathConfig(const SandboxSection * section,const cJSON * config,uint32_t type)258 static PathMountNode *DecodeMountPathConfig(const SandboxSection *section, const cJSON *config, uint32_t type)
259 {
260     char *srcPath = GetStringFromJsonObj(config, "src-path");
261     char *dstPath = GetStringFromJsonObj(config, "sandbox-path");
262     if (srcPath == NULL || dstPath == NULL) {
263         return NULL;
264     }
265 
266     PathMountNode *tmp = GetPathMountNode(section, type, srcPath, dstPath);
267     if (tmp != NULL) { // 删除老的节点,保存新的节点
268         DeleteSandboxMountNode((SandboxMountNode *)tmp);
269         APPSPAWN_LOGW("path %{public}s %{public}s repeat config, delete old", srcPath, dstPath);
270     }
271 
272     cJSON *demandInfo = cJSON_GetObjectItemCaseSensitive(config, "create-on-demand");
273     PathMountNode *sandboxNode = CreatePathMountNode(type, demandInfo != NULL);
274     APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return NULL);
275     sandboxNode->createDemand = demandInfo != NULL;
276     sandboxNode->source = strdup(srcPath);
277     sandboxNode->target = strdup(dstPath);
278 
279     sandboxNode->destMode = GetChmodFromJson(config);
280     sandboxNode->mountSharedFlag = GetBoolValueFromJsonObj(config, "mount-shared-flag", false);
281     sandboxNode->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
282     sandboxNode->createSandboxPath = GetBoolValueFromJsonObj(config, "create-sandbox-path", true);
283     sandboxNode->category = GetMountCategory(GetStringFromJsonObj(config, "category"));
284     const char *value = GetStringFromJsonObj(config, "app-apl-name");
285     if (value != NULL) {
286         sandboxNode->appAplName = strdup(value);
287     }
288     FillPathDemandInfo(demandInfo, sandboxNode);
289 
290     int ret = DecodeDecPolicyPaths(config, sandboxNode);
291     if (ret != 0) {
292         APPSPAWN_LOGE("DecodeDecPolicyPaths failed %{public}d", ret);
293     }
294 
295     if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
296         APPSPAWN_LOGE("Failed to get sourc or target path");
297         DeleteSandboxMountNode((SandboxMountNode *)sandboxNode);
298         return NULL;
299     }
300     return sandboxNode;
301 }
302 
ParseMountPathsConfig(AppSpawnSandboxCfg * sandbox,const cJSON * mountConfigs,SandboxSection * section,uint32_t type)303 APPSPAWN_STATIC int ParseMountPathsConfig(AppSpawnSandboxCfg *sandbox,
304     const cJSON *mountConfigs, SandboxSection *section, uint32_t type)
305 {
306     APPSPAWN_CHECK_ONLY_EXPER(mountConfigs != NULL && cJSON_IsArray(mountConfigs), return -1);
307 
308     uint32_t mountPointSize = cJSON_GetArraySize(mountConfigs);
309     for (uint32_t i = 0; i < mountPointSize; i++) {
310         cJSON *mntJson = cJSON_GetArrayItem(mountConfigs, i);
311         if (mntJson == NULL) {
312             continue;
313         }
314         PathMountNode *sandboxNode = DecodeMountPathConfig(section, mntJson, type);
315         APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, continue);
316         AddSandboxMountNode(&sandboxNode->sandboxNode, section);
317     }
318     return 0;
319 }
320 
DecodeSymbolLinksConfig(const SandboxSection * section,const cJSON * config)321 static SymbolLinkNode *DecodeSymbolLinksConfig(const SandboxSection *section, const cJSON *config)
322 {
323     const char *target = GetStringFromJsonObj(config, "target-name");
324     const char *linkName = GetStringFromJsonObj(config, "link-name");
325     if (target == NULL || linkName == NULL) {
326         return NULL;
327     }
328 
329     SymbolLinkNode *tmp = GetSymbolLinkNode(section, target, linkName);
330     if (tmp != NULL) { // 删除老的节点,保存新的节点
331         DeleteSandboxMountNode((SandboxMountNode *)tmp);
332         APPSPAWN_LOGW("SymbolLink %{public}s %{public}s repeat config, delete old", target, linkName);
333     }
334 
335     SymbolLinkNode *node = CreateSymbolLinkNode();
336     APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
337     node->destMode = GetChmodFromJson(config);
338     node->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
339     node->target = strdup(target);
340     node->linkName = strdup(linkName);
341     if (node->target == NULL || node->linkName == NULL) {
342         APPSPAWN_LOGE("Failed to get sourc or target path");
343         DeleteSandboxMountNode((SandboxMountNode *)node);
344         return NULL;
345     }
346     return node;
347 }
348 
ParseSymbolLinksConfig(AppSpawnSandboxCfg * sandbox,const cJSON * symbolLinkConfigs,SandboxSection * section)349 APPSPAWN_STATIC int ParseSymbolLinksConfig(AppSpawnSandboxCfg *sandbox, const cJSON *symbolLinkConfigs,
350     SandboxSection *section)
351 {
352     APPSPAWN_CHECK_ONLY_EXPER(symbolLinkConfigs != NULL && cJSON_IsArray(symbolLinkConfigs), return -1);
353     uint32_t symlinkPointSize = cJSON_GetArraySize(symbolLinkConfigs);
354     for (uint32_t i = 0; i < symlinkPointSize; i++) {
355         cJSON *symConfig = cJSON_GetArrayItem(symbolLinkConfigs, i);
356         if (symConfig == NULL) {
357             continue;
358         }
359         SymbolLinkNode *node = DecodeSymbolLinksConfig(section, symConfig);
360         APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
361         AddSandboxMountNode(&node->sandboxNode, section);
362     }
363     return 0;
364 }
365 
ParseGidTableConfig(AppSpawnSandboxCfg * sandbox,const cJSON * configs,SandboxSection * section)366 APPSPAWN_STATIC int ParseGidTableConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, SandboxSection *section)
367 {
368     APPSPAWN_CHECK_LOGV(cJSON_IsArray(configs), return 0, "json is not array.");
369     uint32_t arrayLen = (uint32_t)cJSON_GetArraySize(configs);
370     APPSPAWN_CHECK_ONLY_EXPER(arrayLen > 0, return 0);
371     APPSPAWN_CHECK(arrayLen < APP_MAX_GIDS, arrayLen = APP_MAX_GIDS, "More gid in gids json.");
372 
373     // 配置存在,以后面的配置为准
374     if (section->gidTable) {
375         free(section->gidTable);
376         section->gidTable = NULL;
377         section->gidCount = 0;
378     }
379     section->gidTable = (gid_t *)calloc(1, sizeof(gid_t) * arrayLen);
380     APPSPAWN_CHECK(section->gidTable != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory.");
381 
382     for (uint32_t i = 0; i < arrayLen; i++) {
383         cJSON *item = cJSON_GetArrayItem(configs, i);
384         gid_t gid = 0;
385         if (cJSON_IsNumber(item)) {
386             gid = (gid_t)cJSON_GetNumberValue(item);
387         } else {
388             char *value = cJSON_GetStringValue(item);
389             gid = DecodeGid(value);
390         }
391         if (gid <= 0) {
392             continue;
393         }
394         section->gidTable[section->gidCount++] = gid;
395     }
396     return 0;
397 }
398 
ParseMountGroupsConfig(AppSpawnSandboxCfg * sandbox,const cJSON * groupConfig,SandboxSection * section)399 static int ParseMountGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig, SandboxSection *section)
400 {
401     APPSPAWN_CHECK(cJSON_IsArray(groupConfig),
402         return APPSPAWN_SANDBOX_INVALID, "Invalid mount-groups config %{public}s", section->name);
403 
404     // 合并name-group
405     uint32_t count = (uint32_t)cJSON_GetArraySize(groupConfig);
406     APPSPAWN_LOGV("mount-group in section %{public}s  %{public}u", section->name, count);
407     APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
408     count += section->number;
409     SandboxMountNode **nameGroups = (SandboxMountNode **)calloc(1, sizeof(SandboxMountNode *) * count);
410     APPSPAWN_CHECK(nameGroups != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory for group name");
411 
412     uint32_t j = 0;
413     uint32_t number = 0;
414     for (j = 0; j < section->number; j++) { // copy old
415         if (section->nameGroups[j] == NULL) {
416             continue;
417         }
418         nameGroups[number++] = section->nameGroups[j];
419     }
420 
421     SandboxNameGroupNode *mountNode = NULL;
422     for (uint32_t i = 0; i < count; i++) {
423         nameGroups[number] = NULL;
424 
425         char *name = cJSON_GetStringValue(cJSON_GetArrayItem(groupConfig, i));
426         mountNode = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
427         if (mountNode == NULL) {
428             APPSPAWN_LOGE("Can not find name-group %{public}s", name);
429             continue;
430         }
431         // check type
432         if (strcmp(section->name, "system-const") == 0 && mountNode->destType != SANDBOX_TAG_SYSTEM_CONST) {
433             APPSPAWN_LOGE("Invalid name-group %{public}s", name);
434             continue;
435         }
436         // 过滤重复的节点
437         for (j = 0; j < section->number; j++) {
438             if (section->nameGroups[j] != NULL && section->nameGroups[j] == (SandboxMountNode *)mountNode) {
439                 APPSPAWN_LOGE("Name-group %{public}s bas been set", name);
440                 break;
441             }
442         }
443         if (j < section->number) {
444             continue;
445         }
446         nameGroups[number++] = (SandboxMountNode *)mountNode;
447         APPSPAWN_LOGV("Name-group %{public}d %{public}s set", section->number, name);
448     }
449     if (section->nameGroups != NULL) {
450         free(section->nameGroups);
451     }
452     section->nameGroups = nameGroups;
453     section->number = number;
454     APPSPAWN_LOGV("mount-group in section %{public}s  %{public}u", section->name, section->number);
455     return 0;
456 }
457 
ParseBaseConfig(AppSpawnSandboxCfg * sandbox,SandboxSection * section,const cJSON * configs)458 static int ParseBaseConfig(AppSpawnSandboxCfg *sandbox, SandboxSection *section, const cJSON *configs)
459 {
460     APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
461     APPSPAWN_CHECK(cJSON_IsObject(configs),
462         return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", section->name);
463     APPSPAWN_LOGV("Parse sandbox %{public}s", section->name);
464 
465     // "sandbox-switch": "ON", default sandbox switch is on
466     section->sandboxSwitch = GetBoolValueFromJsonObj(configs, "sandbox-switch", true);
467     // "sandbox-shared"
468     section->sandboxShared = GetBoolValueFromJsonObj(configs, "sandbox-shared", false);
469 
470     int ret = 0;
471     cJSON *gidTabJson = cJSON_GetObjectItemCaseSensitive(configs, "gids");
472     if (gidTabJson) {
473         ret = ParseGidTableConfig(sandbox, gidTabJson, section);
474         APPSPAWN_CHECK(ret == 0, return ret, "Parse gids for %{public}s", section->name);
475     }
476 
477     cJSON *pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-paths");
478     if (pathConfigs != NULL) {  // mount-paths
479         ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_PATH);
480         APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
481     }
482 
483     pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-files");
484     if (pathConfigs != NULL) {  // mount-files
485         ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_FILE);
486         APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
487     }
488 
489     pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "symbol-links");
490     if (pathConfigs != NULL) {  // symbol-links
491         ret = ParseSymbolLinksConfig(sandbox, pathConfigs, section);
492         APPSPAWN_CHECK(ret == 0, return ret, "Parse symbol-links for %{public}s", section->name);
493     }
494 
495     cJSON *groupConfig = cJSON_GetObjectItemCaseSensitive(configs, "mount-groups");
496     if (groupConfig != NULL) {
497         ret = ParseMountGroupsConfig(sandbox, groupConfig, section);
498         APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-groups for %{public}s", section->name);
499     }
500     return 0;
501 }
502 
ParsePackageNameConfig(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * packageNameConfigs)503 static int ParsePackageNameConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *packageNameConfigs)
504 {
505     APPSPAWN_LOGV("Parse package-name config %{public}s", name);
506     SandboxPackageNameNode *node = (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, name);
507     if (node == NULL) {
508         node = CreateSandboxPackageNameNode(name);
509     }
510     APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
511 
512     int ret = ParseBaseConfig(sandbox, &node->section, packageNameConfigs);
513     if (ret != 0) {
514         DeleteSandboxSection((SandboxSection *)node);
515         return ret;
516     }
517     // success, insert section
518     AddSandboxSection(&node->section, &sandbox->packageNameQueue);
519     return 0;
520 }
521 
ParseSpawnFlagsConfig(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * flagsConfig)522 static int ParseSpawnFlagsConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *flagsConfig)
523 {
524     uint32_t flagIndex = GetFlagIndexFromJson(flagsConfig);
525     APPSPAWN_LOGV("Parse spawn-flags config %{public}s flagIndex %{public}u", name, flagIndex);
526     SandboxFlagsNode *node = (SandboxFlagsNode *)GetSandboxSection(&sandbox->spawnFlagsQueue, name);
527     if (node == NULL) {
528         node = CreateSandboxFlagsNode(name);
529     }
530     APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
531     node->flagIndex = flagIndex;
532 
533     int ret = ParseBaseConfig(sandbox, &node->section, flagsConfig);
534     if (ret != 0) {
535         DeleteSandboxSection((SandboxSection *)node);
536         return ret;
537     }
538     // success, insert section
539     AddSandboxSection(&node->section, &sandbox->spawnFlagsQueue);
540     return 0;
541 }
542 
ParsePermissionConfig(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * permissionConfig)543 static int ParsePermissionConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *permissionConfig)
544 {
545     APPSPAWN_LOGV("Parse permission config %{public}s", name);
546     SandboxPermissionNode *node = (SandboxPermissionNode *)GetSandboxSection(&sandbox->permissionQueue, name);
547     if (node == NULL) {
548         node = CreateSandboxPermissionNode(name);
549     }
550     APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
551 
552     int ret = ParseBaseConfig(sandbox, &node->section, permissionConfig);
553     if (ret != 0) {
554         DeleteSandboxSection((SandboxSection *)node);
555         return ret;
556     }
557     // success, insert section
558     AddSandboxSection(&node->section, &sandbox->permissionQueue);
559     return 0;
560 }
561 
AddSpawnerPermissionNode(AppSpawnSandboxCfg * sandbox)562 static int AddSpawnerPermissionNode(AppSpawnSandboxCfg *sandbox)
563 {
564     uint32_t permissionCount = ARRAY_LENGTH(g_spawnerPermissionList);
565     for (uint32_t i = 0; i < permissionCount; i++) {
566         SandboxPermissionNode *node =
567             (SandboxPermissionNode *)GetSandboxSection(&sandbox->permissionQueue, g_spawnerPermissionList[i]);
568         if (node == NULL) {
569             node = CreateSandboxPermissionNode(g_spawnerPermissionList[i]);
570         }
571         APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
572 
573         // success, insert section
574         AddSandboxSection(&node->section, &sandbox->permissionQueue);
575     }
576     return 0;
577 }
578 
ParseNameGroup(AppSpawnSandboxCfg * sandbox,const cJSON * groupConfig)579 static SandboxNameGroupNode *ParseNameGroup(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig)
580 {
581     char *name = GetStringFromJsonObj(groupConfig, "name");
582     APPSPAWN_CHECK(name != NULL, return NULL, "No name in name group config");
583     APPSPAWN_LOGV("Parse name-group config %{public}s", name);
584     SandboxNameGroupNode *node = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
585     if (node == NULL) {
586         node = CreateSandboxNameGroupNode(name);
587     }
588     APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
589 
590     cJSON *obj = cJSON_GetObjectItemCaseSensitive(groupConfig, "mount-paths-deps");
591     if (obj) {
592         if (node->depNode) { // free repeat
593             DeleteSandboxMountNode((SandboxMountNode *)node->depNode);
594         }
595         node->depNode = DecodeMountPathConfig(NULL, obj, SANDBOX_TAG_MOUNT_PATH);
596         if (node->depNode == NULL) {
597             DeleteSandboxSection((SandboxSection *)node);
598             return NULL;
599         }
600         // "deps-mode": "not-exists"
601         node->depMode = GetMountModeFromConfig(groupConfig, "deps-mode", MOUNT_MODE_ALWAYS);
602     }
603 
604     int ret = ParseBaseConfig(sandbox, &node->section, groupConfig);
605     if (ret != 0) {
606         DeleteSandboxSection((SandboxSection *)node);
607         return NULL;
608     }
609     // "type": "system-const",
610     // "caps": ["shared"],
611     node->destType = GetNameGroupTypeFromConfig(groupConfig, "type", SANDBOX_TAG_INVALID);
612     node->depMounted = 0;
613     // success, insert section
614     AddSandboxSection(&node->section, &sandbox->nameGroupsQueue);
615     return node;
616 }
617 
ParseNameGroupsConfig(AppSpawnSandboxCfg * sandbox,const cJSON * root)618 static int ParseNameGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
619 {
620     APPSPAWN_CHECK(root != NULL, return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
621     cJSON *configs = cJSON_GetObjectItemCaseSensitive(root, "name-groups");
622     APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
623     APPSPAWN_CHECK(cJSON_IsArray(configs), return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
624     int count = cJSON_GetArraySize(configs);
625     APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
626 
627     sandbox->depNodeCount = 0;
628     for (int i = 0; i < count; i++) {
629         cJSON *json = cJSON_GetArrayItem(configs, i);
630         if (json == NULL) {
631             continue;
632         }
633         SandboxNameGroupNode *node = ParseNameGroup(sandbox, json);
634         APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return APPSPAWN_SANDBOX_INVALID);
635         if (node->depNode) {
636             sandbox->depNodeCount++;
637         }
638     }
639     APPSPAWN_LOGV("ParseNameGroupsConfig depNodeCount %{public}d", sandbox->depNodeCount);
640     return 0;
641 }
642 
ParseConditionalConfig(AppSpawnSandboxCfg * sandbox,const cJSON * configs,const char * configName,int (* parseConfig)(AppSpawnSandboxCfg * sandbox,const char * name,const cJSON * configs))643 static int ParseConditionalConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, const char *configName,
644     int (*parseConfig)(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *configs))
645 {
646     APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
647     APPSPAWN_CHECK(cJSON_IsArray(configs),
648         return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", configName);
649     int ret = 0;
650     int count = cJSON_GetArraySize(configs);
651     for (int i = 0; i < count; i++) {
652         cJSON *json = cJSON_GetArrayItem(configs, i);
653         if (json == NULL) {
654             continue;
655         }
656         char *name = GetStringFromJsonObj(json, "name");
657         if (name == NULL) {
658             APPSPAWN_LOGE("No name in %{public}s configs", configName);
659             continue;
660         }
661         ret = parseConfig(sandbox, name, json);
662         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
663     }
664     return 0;
665 }
666 
ParseGlobalSandboxConfig(AppSpawnSandboxCfg * sandbox,const cJSON * root)667 static int ParseGlobalSandboxConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
668 {
669     cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "global");
670     if (json) {
671         sandbox->sandboxNsFlags = GetSandboxNsFlags(json);
672         char *rootPath = GetStringFromJsonObj(json, "sandbox-root");
673         APPSPAWN_CHECK(rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "No root path in config");
674         if (sandbox->rootPath) {
675             free(sandbox->rootPath);
676         }
677         sandbox->rootPath = strdup(rootPath);
678         APPSPAWN_CHECK(sandbox->rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to copy root path");
679         sandbox->topSandboxSwitch = GetBoolValueFromJsonObj(json, "top-sandbox-switch", true);
680     }
681     return 0;
682 }
683 
684 typedef struct TagParseJsonContext {
685     AppSpawnSandboxCfg *sandboxCfg;
686 }ParseJsonContext;
687 
ParseAppSandboxConfig(const cJSON * root,ParseJsonContext * context)688 APPSPAWN_STATIC int ParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context)
689 {
690     APPSPAWN_CHECK(root != NULL && context != NULL && context->sandboxCfg != NULL,
691         return APPSPAWN_SYSTEM_ERROR, "Invalid json");
692     AppSpawnSandboxCfg *sandbox = context->sandboxCfg;
693     int ret = ParseGlobalSandboxConfig(sandbox, root);  // "global":
694     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
695     ret = ParseNameGroupsConfig(sandbox, root);  // name-groups
696     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
697 
698     // "required"
699     cJSON *required = cJSON_GetObjectItemCaseSensitive(root, "required");
700     if (required) {
701         cJSON *config = NULL;
702         cJSON_ArrayForEach(config, required)
703         {
704             APPSPAWN_LOGI("Sandbox required config: %{public}s", config->string);
705             SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, config->string);
706             if (section == NULL) {
707                 section = CreateSandboxSection(config->string, sizeof(SandboxSection), SANDBOX_TAG_REQUIRED);
708             }
709             APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return -1);
710 
711             ret = ParseBaseConfig(sandbox, section, config);
712             if (ret != 0) {
713                 DeleteSandboxSection(section);
714                 return ret;
715             }
716             // success, insert section
717             AddSandboxSection(section, &sandbox->requiredQueue);
718         }
719     }
720 
721     // conditional
722     cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional");
723     if (json != NULL) {
724         // sandbox permission
725         cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission");
726         ret = ParseConditionalConfig(sandbox, config, "permission", ParsePermissionConfig);
727         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
728         // spawning permission
729         ret = AddSpawnerPermissionNode(sandbox);
730         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
731         // spawn-flag
732         config = cJSON_GetObjectItemCaseSensitive(json, "spawn-flag");
733         ret = ParseConditionalConfig(sandbox, config, "spawn-flag", ParseSpawnFlagsConfig);
734         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
735         // package-name
736         config = cJSON_GetObjectItemCaseSensitive(json, "package-name");
737         ret = ParseConditionalConfig(sandbox, config, "package-name", ParsePackageNameConfig);
738         APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
739     }
740     return ret;
741 }
742 
GetSandboxNameByType(ExtDataType type)743 APPSPAWN_STATIC const char *GetSandboxNameByType(ExtDataType type)
744 {
745     if (type >= EXT_DATA_COUNT || type < EXT_DATA_APP_SANDBOX) {
746         return NULL;
747     }
748     const char *fileName = NULL;
749     switch (type) {
750         case EXT_DATA_APP_SANDBOX:
751             fileName = APP_SANDBOX_FILE_NAME;
752             break;
753         case EXT_DATA_ISOLATED_SANDBOX:
754             fileName = ISOLATED_SANDBOX_FILE_NAME;
755             break;
756         case EXT_DATA_RENDER_SANDBOX:
757             fileName = RENDER_SANDBOX_FILE_NAME;
758             break;
759         case EXT_DATA_GPU_SANDBOX:
760             fileName = GPU_SANDBOX_FILE_NAME;
761             break;
762         case EXT_DATA_DEBUG_HAP_SANDBOX:
763             fileName = DEBUG_SANDBOX_FILE_NAME;
764             break;
765         default:
766             break;
767     }
768     return fileName;
769 }
770 
LoadAppSandboxConfig(AppSpawnSandboxCfg * sandbox,ExtDataType type)771 int LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, ExtDataType type)
772 {
773     APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_ARG_INVALID);
774     const char *sandboxName = GetSandboxNameByType(type);
775     APPSPAWN_LOGV("Get sandboxName %{public}s by type %{public}d", sandboxName, type);
776     if (sandbox->depGroupNodes != NULL) {
777         APPSPAWN_LOGW("Sandbox has been load");
778         return 0;
779     }
780     ParseJsonContext context = {};
781     context.sandboxCfg = sandbox;
782     (void)ParseJsonConfig("etc/sandbox", sandboxName, ParseAppSandboxConfig, &context);
783     sandbox->pidNamespaceSupport = AppSandboxPidNsIsSupport();
784     sandbox->appFullMountEnable = CheckAppFullMountEnable();
785     APPSPAWN_LOGI("Sandbox pidNamespaceSupport: %{public}d appFullMountEnable: %{public}d",
786         sandbox->pidNamespaceSupport, sandbox->appFullMountEnable);
787 
788     uint32_t depNodeCount = sandbox->depNodeCount;
789     APPSPAWN_CHECK_ONLY_EXPER(depNodeCount > 0, return 0);
790 
791     sandbox->depGroupNodes = (SandboxNameGroupNode **)calloc(1, sizeof(SandboxNameGroupNode *) * depNodeCount);
792     APPSPAWN_CHECK(sandbox->depGroupNodes != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed alloc memory ");
793     sandbox->depNodeCount = 0;
794     ListNode *node = sandbox->nameGroupsQueue.front.next;
795     while (node != &sandbox->nameGroupsQueue.front) {
796         SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)ListEntry(node, SandboxMountNode, node);
797         if (groupNode->depNode) {
798             sandbox->depGroupNodes[sandbox->depNodeCount++] = groupNode;
799         }
800         node = node->next;
801     }
802     APPSPAWN_LOGI("LoadAppSandboxConfig depNodeCount %{public}d", sandbox->depNodeCount);
803 
804     return 0;
805 }
806