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