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
16 #include "appspawn_sandbox.h"
17 #include "sandbox_adapter.h"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <sched.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <sys/mount.h>
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include "securec.h"
32
33 #include "appspawn_msg.h"
34 #include "appspawn_utils.h"
35 #ifdef WITH_DLP
36 #include "dlp_fuse_fd.h"
37 #endif
38 #include "init_utils.h"
39 #include "parameter.h"
40 #include "appspawn_permission.h"
41
42 #ifdef WITH_SELINUX
43 #ifdef APPSPAWN_MOUNT_TMPSHM
44 #include "policycoreutils.h"
45 #endif // APPSPAWN_MOUNT_TMPSHM
46 #endif // WITH_SELINUX
47
48 #define USER_ID_SIZE 16
49 #define DIR_MODE 0711
50 #define LOCK_STATUS_PARAM_SIZE 64
51 #define LOCK_STATUS_SIZE 16
52 #define DEV_SHM_DIR "/dev/shm/"
53
SetMountPathOperation(uint32_t * operation,uint32_t index)54 static inline void SetMountPathOperation(uint32_t *operation, uint32_t index)
55 {
56 *operation |= (1 << index);
57 }
58
CheckSpawningMsgFlagSet(const SandboxContext * context,uint32_t index)59 static inline bool CheckSpawningMsgFlagSet(const SandboxContext *context, uint32_t index)
60 {
61 APPSPAWN_CHECK(context->message != NULL, return false, "Invalid property for type %{public}u", TLV_MSG_FLAGS);
62 return CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, index);
63 }
64
CheckSpawningPermissionFlagSet(const SandboxContext * context,uint32_t index)65 APPSPAWN_STATIC inline bool CheckSpawningPermissionFlagSet(const SandboxContext *context, uint32_t index)
66 {
67 APPSPAWN_CHECK(context != NULL && context->message != NULL,
68 return NULL, "Invalid property for type %{public}u", TLV_PERMISSION);
69 return CheckAppSpawnMsgFlag(context->message, TLV_PERMISSION, index);
70 }
71
CheckDirRecursive(const char * path)72 APPSPAWN_STATIC bool CheckDirRecursive(const char *path)
73 {
74 char buffer[PATH_MAX] = {0};
75 const char slash = '/';
76 const char *p = path;
77 char *curPos = strchr(path, slash);
78 while (curPos != NULL) {
79 int len = curPos - p;
80 p = curPos + 1;
81 if (len == 0) {
82 curPos = strchr(p, slash);
83 continue;
84 }
85 int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1);
86 APPSPAWN_CHECK(ret == 0, return false, "Failed to copy path");
87 ret = access(buffer, F_OK);
88 APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
89 curPos = strchr(p, slash);
90 }
91 int ret = access(path, F_OK);
92 APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
93 return true;
94 }
95
SandboxMountPath(const MountArg * arg)96 int SandboxMountPath(const MountArg *arg)
97 {
98 APPSPAWN_CHECK(arg != NULL && arg->originPath != NULL && arg->destinationPath != NULL,
99 return APPSPAWN_ARG_INVALID, "Invalid arg ");
100
101 APPSPAWN_LOGV("Bind mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s",
102 arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
103 (uint32_t)arg->mountFlags, arg->options, arg->originPath, arg->destinationPath);
104
105 int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options);
106 if (ret != 0) {
107 APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
108 errno, arg->originPath, arg->destinationPath);
109 if (strstr(arg->originPath, "/data/app/el1/") != NULL || strstr(arg->originPath, "/data/app/el2/") != NULL) {
110 CheckDirRecursive(arg->originPath);
111 }
112 return errno;
113 }
114 ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL);
115 if (ret != 0) {
116 APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
117 errno, arg->originPath, arg->destinationPath);
118 return errno;
119 }
120 return 0;
121 }
122
BuildRootPath(char * buffer,uint32_t bufferLen,const AppSpawnSandboxCfg * sandbox,uid_t uid)123 static int BuildRootPath(char *buffer, uint32_t bufferLen, const AppSpawnSandboxCfg *sandbox, uid_t uid)
124 {
125 int ret = 0;
126 int len = 0;
127 uint32_t currLen = 0;
128 uint32_t userIdLen = sizeof(PARAMETER_USER_ID) - 1;
129 uint32_t rootLen = strlen(sandbox->rootPath);
130 char *rootPath = strstr(sandbox->rootPath, PARAMETER_USER_ID);
131 if (rootPath == NULL) {
132 len = sprintf_s(buffer, bufferLen, "%s/%d", sandbox->rootPath, uid);
133 } else {
134 ret = memcpy_s(buffer, bufferLen, sandbox->rootPath, rootPath - sandbox->rootPath);
135 APPSPAWN_CHECK(ret == 0, return ret, "Failed to copy root path %{public}s", sandbox->rootPath);
136 currLen = rootPath - sandbox->rootPath;
137
138 if (rootLen > (currLen + userIdLen)) {
139 len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d%s",
140 uid, sandbox->rootPath + currLen + userIdLen);
141 } else {
142 len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d", uid);
143 }
144 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < (bufferLen - currLen)), return ret,
145 "Failed to format root path %{public}s", sandbox->rootPath);
146 currLen += (uint32_t)len;
147 }
148 buffer[currLen] = '\0';
149 return 0;
150 }
151
152 static SandboxContext *g_sandboxContext = NULL;
153
GetSandboxContext(void)154 SandboxContext *GetSandboxContext(void)
155 {
156 if (g_sandboxContext == NULL) {
157 SandboxContext *context = calloc(1, MAX_SANDBOX_BUFFER * MAX_BUFFER + sizeof(SandboxContext));
158 APPSPAWN_CHECK(context != NULL, return NULL, "Failed to get mem");
159 char *buffer = (char *)(context + 1);
160 for (int i = 0; i < MAX_BUFFER; i++) {
161 context->buffer[i].bufferLen = MAX_SANDBOX_BUFFER;
162 context->buffer[i].current = 0;
163 context->buffer[i].buffer = buffer + MAX_SANDBOX_BUFFER * i;
164 }
165 context->bundleName = NULL;
166 context->bundleHasWps = 0;
167 context->dlpBundle = 0;
168 context->appFullMountEnable = 0;
169 context->sandboxSwitch = 1;
170 context->sandboxShared = false;
171 context->message = NULL;
172 context->rootPath = NULL;
173 g_sandboxContext = context;
174 }
175 return g_sandboxContext;
176 }
177
DeleteSandboxContext(SandboxContext * context)178 void DeleteSandboxContext(SandboxContext *context)
179 {
180 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return);
181 if (context->rootPath) {
182 free(context->rootPath);
183 context->rootPath = NULL;
184 }
185 if (context == g_sandboxContext) {
186 g_sandboxContext = NULL;
187 }
188 free(context);
189 }
190
NeedNetworkIsolated(SandboxContext * context,const AppSpawningCtx * property)191 static bool NeedNetworkIsolated(SandboxContext *context, const AppSpawningCtx *property)
192 {
193 int developerMode = IsDeveloperModeOpen();
194 if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX) && !developerMode) {
195 return true;
196 }
197
198 if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_NETWORK)) {
199 uint32_t len = 0;
200 char *extensionType = GetAppPropertyExt(property, MSG_EXT_NAME_EXTENSION_TYPE, &len);
201 if (extensionType == NULL || extensionType[0] == '\0' || !developerMode) {
202 return true;
203 }
204 }
205
206 return false;
207 }
208
InitSandboxContext(SandboxContext * context,const AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property,int nwebspawn)209 static int InitSandboxContext(SandboxContext *context,
210 const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
211 {
212 AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppProperty(property, TLV_MSG_FLAGS);
213 APPSPAWN_CHECK(msgFlags != NULL, return APPSPAWN_TLV_NONE,
214 "No msg flags in msg %{public}s", GetProcessName(property));
215 context->nwebspawn = nwebspawn;
216 context->bundleName = GetBundleName(property);
217 context->bundleHasWps = strstr(context->bundleName, "wps") != NULL;
218 context->dlpBundle = strcmp(GetProcessName(property), "com.ohos.dlpmanager") == 0;
219 context->appFullMountEnable = sandbox->appFullMountEnable;
220
221 context->sandboxSwitch = 1;
222 context->sandboxShared = false;
223 SandboxPackageNameNode *packageNode = (SandboxPackageNameNode *)GetSandboxSection(
224 &sandbox->packageNameQueue, context->bundleName);
225 if (packageNode) {
226 context->sandboxShared = packageNode->section.sandboxShared;
227 }
228 context->message = property->message;
229 context->sandboxNsFlags = CLONE_NEWNS;
230 if (NeedNetworkIsolated(context, property)) {
231 context->sandboxNsFlags |= sandbox->sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0;
232 }
233
234 ListNode *node = sandbox->permissionQueue.front.next;
235 while (node != &sandbox->permissionQueue.front) {
236 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
237 if (permissionNode == NULL) {
238 return -1;
239 }
240 context->sandboxShared = permissionNode->section.sandboxShared;
241 node = node->next;
242 }
243
244 // root path
245 const char *rootPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandbox->rootPath, NULL, NULL);
246 if (rootPath) {
247 context->rootPath = strdup(rootPath);
248 }
249 if (context->rootPath == NULL) {
250 DeleteSandboxContext(context);
251 return -1;
252 }
253 return 0;
254 }
255
GetVarExtraData(const SandboxContext * context,const SandboxSection * section)256 static VarExtraData *GetVarExtraData(const SandboxContext *context, const SandboxSection *section)
257 {
258 static VarExtraData extraData;
259 (void)memset_s(&extraData, sizeof(extraData), 0, sizeof(extraData));
260 extraData.sandboxTag = GetSectionType(section);
261 if (GetSectionType(section) == SANDBOX_TAG_NAME_GROUP) {
262 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section;
263 extraData.data.depNode = groupNode->depNode;
264 }
265 return &extraData;
266 }
267
GetMountArgs(const SandboxContext * context,const PathMountNode * sandboxNode,uint32_t operation,MountArg * args)268 static uint32_t GetMountArgs(const SandboxContext *context,
269 const PathMountNode *sandboxNode, uint32_t operation, MountArg *args)
270 {
271 uint32_t category = sandboxNode->category;
272 const MountArgTemplate *tmp = GetMountArgTemplate(category);
273 if (tmp == 0) {
274 return MOUNT_TMP_DEFAULT;
275 }
276 args->fsType = tmp->fsType;
277 args->options = tmp->options;
278 args->mountFlags = tmp->mountFlags;
279 args->mountSharedFlag = (sandboxNode->mountSharedFlag) ? MS_SHARED : tmp->mountSharedFlag;
280 return category;
281 }
282
CheckSandboxMountNode(const SandboxContext * context,const SandboxSection * section,const PathMountNode * sandboxNode,uint32_t operation)283 APPSPAWN_STATIC int CheckSandboxMountNode(const SandboxContext *context,
284 const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)
285 {
286 if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
287 APPSPAWN_LOGW("Invalid mount config section %{public}s", section->name);
288 return 0;
289 }
290 // special handle wps and don't use /data/app/xxx/<Package> config
291 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) { // flags-point
292 if (context->bundleHasWps &&
293 (strstr(sandboxNode->source, "/data/app") != NULL) &&
294 (strstr(sandboxNode->source, "/base") != NULL || strstr(sandboxNode->source, "/database") != NULL) &&
295 (strstr(sandboxNode->source, PARAMETER_PACKAGE_NAME) != NULL)) {
296 APPSPAWN_LOGW("Invalid mount source %{public}s section %{public}s",
297 sandboxNode->source, section->name);
298 return 0;
299 }
300 }
301 // check apl
302 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
303 if (msgDomainInfo != NULL && sandboxNode->appAplName != NULL) {
304 if (!strcmp(sandboxNode->appAplName, msgDomainInfo->apl)) {
305 APPSPAWN_LOGW("Invalid mount app apl %{public}s %{public}s section %{public}s",
306 sandboxNode->appAplName, msgDomainInfo->apl, section->name);
307 return 0;
308 }
309 }
310 return 1;
311 }
312
SandboxMountFusePath(const SandboxContext * context,const MountArg * args)313 static int32_t SandboxMountFusePath(const SandboxContext *context, const MountArg *args)
314 {
315 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
316 APPSPAWN_CHECK(info != NULL, return APPSPAWN_TLV_NONE,
317 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
318
319 // umount fuse path, make sure that sandbox path is not a mount point
320 umount2(args->destinationPath, MNT_DETACH);
321
322 int fd = open("/dev/fuse", O_RDWR);
323 APPSPAWN_CHECK(fd != -1, return -EINVAL,
324 "open /dev/fuse failed, errno: %{public}d sandbox path %{public}s", errno, args->destinationPath);
325
326 char options[OPTIONS_MAX_LEN] = {0};
327 int ret = sprintf_s(options, sizeof(options), "fd=%d,"
328 "rootmode=40000,user_id=%d,group_id=%d,allow_other,"
329 "context=\"u:object_r:dlp_fuse_file:s0\","
330 "fscontext=u:object_r:dlp_fuse_file:s0", fd, info->uid, info->gid);
331 APPSPAWN_CHECK(ret > 0, close(fd);
332 return APPSPAWN_ERROR_UTILS_MEM_FAIL, "sprintf options fail");
333
334 APPSPAWN_LOGV("Bind mount dlp fuse \n "
335 "mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s",
336 args->fsType, args->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
337 (uint32_t)args->mountFlags, options, args->originPath, args->destinationPath);
338
339 // To make sure destinationPath exist
340 CreateSandboxDir(args->destinationPath, FILE_MODE);
341 MountArg mountArg = {args->originPath, args->destinationPath, args->fsType, args->mountFlags, options, MS_SHARED};
342 ret = SandboxMountPath(&mountArg);
343 if (ret != 0) {
344 close(fd);
345 return -1;
346 }
347 /* set DLP_FUSE_FD */
348 #ifdef WITH_DLP
349 SetDlpFuseFd(fd);
350 #endif
351 return 0;
352 }
353
CheckAndCreateSandboxFile(const char * file)354 APPSPAWN_STATIC void CheckAndCreateSandboxFile(const char *file)
355 {
356 if (access(file, F_OK) == 0) {
357 APPSPAWN_LOGI("file %{public}s already exist", file);
358 return;
359 }
360 MakeDirRec(file, FILE_MODE, 0);
361 int fd = open(file, O_CREAT, FILE_MODE);
362 if (fd < 0) {
363 APPSPAWN_LOGW("failed create %{public}s, err=%{public}d", file, errno);
364 } else {
365 close(fd);
366 }
367 return;
368 }
369
CreateDemandSrc(const SandboxContext * context,const PathMountNode * sandboxNode,const MountArg * args)370 APPSPAWN_STATIC void CreateDemandSrc(const SandboxContext *context, const PathMountNode *sandboxNode,
371 const MountArg *args)
372 {
373 if (!sandboxNode->createDemand) {
374 return;
375 }
376 CheckAndCreateSandboxFile(args->originPath);
377 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
378 APPSPAWN_CHECK(info != NULL, return,
379 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
380
381 // chmod
382 uid_t uid = sandboxNode->demandInfo->uid != INVALID_UID ? sandboxNode->demandInfo->uid : info->uid;
383 gid_t gid = sandboxNode->demandInfo->gid != INVALID_UID ? sandboxNode->demandInfo->gid : info->gid;
384 int ret = chown(args->originPath, uid, gid);
385 if (ret != 0) {
386 APPSPAWN_LOGE("Failed to chown %{public}s errno: %{public}d", args->originPath, errno);
387 }
388 if (sandboxNode->demandInfo->mode != INVALID_UID) {
389 ret = chmod(args->originPath, sandboxNode->demandInfo->mode);
390 if (ret != 0) {
391 APPSPAWN_LOGE("Failed to chmod %{public}s errno: %{public}d", args->originPath, errno);
392 }
393 }
394 }
395
GetRealSrcPath(const SandboxContext * context,const char * source,VarExtraData * extraData)396 APPSPAWN_STATIC const char *GetRealSrcPath(const SandboxContext *context, const char *source, VarExtraData *extraData)
397 {
398 bool hasPackageName = strstr(source, "<variablePackageName>") != NULL;
399 extraData->variablePackageName = (char *)context->bundleName;
400 const char *originPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, source, NULL, extraData);
401 if (originPath == NULL) {
402 return NULL;
403 }
404 if (hasPackageName && CheckSpawningMsgFlagSet(context, APP_FLAGS_ATOMIC_SERVICE)) {
405 const char *varPackageName = strrchr(originPath, '/') ? strrchr(originPath, '/') + 1 : originPath;
406 MakeAtomicServiceDir(context, originPath, varPackageName);
407 }
408 return originPath;
409 }
410
411 // 设置挂载参数options
SetMountArgsOption(const SandboxContext * context,uint32_t category,uint32_t operation,MountArg * args)412 static int32_t SetMountArgsOption(const SandboxContext *context, uint32_t category, uint32_t operation, MountArg *args)
413 {
414 if ((category != MOUNT_TMP_DAC_OVERRIDE) && (category != MOUNT_TMP_DAC_OVERRIDE_DELETE)) {
415 return 0;
416 }
417
418 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
419 if (info == NULL) {
420 APPSPAWN_LOGE("Get msg dac info failed");
421 return APPSPAWN_ARG_INVALID;
422 }
423
424 char options[OPTIONS_MAX_LEN] = {0};
425 int len = sprintf_s(options, OPTIONS_MAX_LEN, "%s%s%d", args->options, SHAREFS_OPTION_USER, info->uid / UID_BASE);
426 if (len <= 0) {
427 APPSPAWN_LOGE("sprintf_s failed");
428 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
429 }
430 args->options = options;
431 return 0;
432 }
433
434 // 根据沙盒配置文件中挂载类别进行挂载
DoSandboxMountByCategory(const SandboxContext * context,const PathMountNode * sandboxNode,MountArg * args,uint32_t operation)435 static int DoSandboxMountByCategory(const SandboxContext *context, const PathMountNode *sandboxNode,
436 MountArg *args, uint32_t operation)
437 {
438 int ret = 0;
439 uint32_t category = GetMountArgs(context, sandboxNode, operation, args);
440 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_PERMISSION) ||
441 CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) {
442 ret = SetMountArgsOption(context, category, operation, args);
443 if (ret != 0) {
444 APPSPAWN_LOGE("set mount arg option fail. ret: %{public}d", ret);
445 return ret;
446 }
447 }
448 if (category == MOUNT_TMP_DLP_FUSE || category == MOUNT_TMP_FUSE) {
449 ret = SandboxMountFusePath(context, args);
450 } else {
451 ret = SandboxMountPath(args);
452 }
453 return ret;
454 }
455
DoSandboxPathNodeMount(const SandboxContext * context,const SandboxSection * section,const PathMountNode * sandboxNode,uint32_t operation)456 static int DoSandboxPathNodeMount(const SandboxContext *context,
457 const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation)
458 {
459 if (CheckSandboxMountNode(context, section, sandboxNode, operation) == 0) {
460 return 0;
461 }
462
463 MountArg args = {};
464 uint32_t category = GetMountArgs(context, sandboxNode, operation, &args);
465 VarExtraData *extraData = GetVarExtraData(context, section);
466 args.originPath = GetRealSrcPath(context, sandboxNode->source, extraData);
467 // dest
468 extraData->operation = operation; // only destinationPath
469 // 对name group的节点,需要对目的沙盒进行特殊处理,不能带root-dir
470 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_NAME_GROUP) &&
471 CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_ONLY_SANDBOX)) {
472 args.destinationPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, sandboxNode->target, NULL, extraData);
473 } else {
474 args.destinationPath = GetSandboxRealVar(context,
475 BUFFER_FOR_TARGET, sandboxNode->target, context->rootPath, extraData);
476 }
477 APPSPAWN_CHECK(args.originPath != NULL && args.destinationPath != NULL,
478 return APPSPAWN_ARG_INVALID, "Invalid path %{public}s %{public}s", args.originPath, args.destinationPath);
479
480 if (sandboxNode->sandboxNode.type == SANDBOX_TAG_MOUNT_FILE) {
481 CheckAndCreateSandboxFile(args.destinationPath);
482 } else {
483 if (access(args.destinationPath, F_OK) != 0) {
484 CreateSandboxDir(args.destinationPath, FILE_MODE);
485 }
486 }
487
488 CreateDemandSrc(context, sandboxNode, &args);
489
490 int ret = 0;
491 if (CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_UNMOUNT)) { // unmount this deps
492 APPSPAWN_LOGV("umount2 %{public}s", args.destinationPath);
493 ret = umount2(args.destinationPath, MNT_DETACH);
494 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount %{public}s errno %{public}d", args.destinationPath, errno);
495 }
496
497 ret = DoSandboxMountByCategory(context, sandboxNode, &args, operation);
498 if (ret != 0 && sandboxNode->checkErrorFlag) {
499 APPSPAWN_LOGE("Failed to mount config, section: %{public}s result: %{public}d category: %{public}d",
500 section->name, ret, category);
501 return ret;
502 }
503 return 0;
504 }
505
DoSandboxPathSymLink(const SandboxContext * context,const SandboxSection * section,const SymbolLinkNode * sandboxNode)506 static int DoSandboxPathSymLink(const SandboxContext *context,
507 const SandboxSection *section, const SymbolLinkNode *sandboxNode)
508 {
509 // Check the validity of the symlink configuration
510 if (sandboxNode->linkName == NULL || sandboxNode->target == NULL) {
511 APPSPAWN_LOGW("Invalid symlink config, section %{public}s", section->name);
512 return 0;
513 }
514
515 const char *target = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandboxNode->target, NULL, NULL);
516 const char *linkName = GetSandboxRealVar(context, BUFFER_FOR_TARGET,
517 sandboxNode->linkName, context->rootPath, NULL);
518 APPSPAWN_LOGV("symlink from %{public}s to %{public}s", target, linkName);
519 if (access(linkName, F_OK) == 0) {
520 if (rmdir(linkName) != 0) {
521 APPSPAWN_LOGW("linkName %{public}s already exist and rmdir failed, errno %{public}d", linkName, errno);
522 }
523 }
524 int ret = symlink(target, linkName);
525 if (ret && errno != EEXIST) {
526 if (sandboxNode->checkErrorFlag) {
527 APPSPAWN_LOGE("symlink failed, errno: %{public}d link info %{public}s %{public}s",
528 errno, sandboxNode->target, sandboxNode->linkName);
529 return errno;
530 }
531 APPSPAWN_LOGV("symlink failed, errno: %{public}d link info %{public}s %{public}s",
532 errno, sandboxNode->target, sandboxNode->linkName);
533 }
534 return 0;
535 }
536
DoSandboxNodeMount(const SandboxContext * context,const SandboxSection * section,uint32_t operation)537 static int DoSandboxNodeMount(const SandboxContext *context, const SandboxSection *section, uint32_t operation)
538 {
539 ListNode *node = section->front.next;
540 while (node != §ion->front) {
541 int ret = 0;
542 SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
543 switch (sandboxNode->type) {
544 case SANDBOX_TAG_MOUNT_PATH:
545 case SANDBOX_TAG_MOUNT_FILE:
546 ret = DoSandboxPathNodeMount(context, section, (PathMountNode *)sandboxNode, operation);
547 break;
548 case SANDBOX_TAG_SYMLINK:
549 if (!CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_SYMLINK)) {
550 break;
551 }
552 ret = DoSandboxPathSymLink(context, section, (SymbolLinkNode *)sandboxNode);
553 break;
554 default:
555 break;
556 }
557 if (ret != 0) {
558 return ret;
559 }
560 node = node->next;
561 }
562 return 0;
563 }
564
IsUnlockStatus(uint32_t uid)565 static bool IsUnlockStatus(uint32_t uid)
566 {
567 const int userIdBase = UID_BASE;
568 uid = uid / userIdBase;
569 if (uid == 0) { // uid = 0 不涉及加密目录的挂载
570 return true;
571 }
572
573 char lockStatusParam[LOCK_STATUS_PARAM_SIZE] = {0};
574 char userLockStatus[LOCK_STATUS_SIZE] = {0};
575 int ret = snprintf_s(lockStatusParam, sizeof(lockStatusParam), sizeof(lockStatusParam) - 1,
576 "startup.appspawn.lockstatus_%u", uid);
577 APPSPAWN_CHECK(ret > 0, return false, "get lock status param failed, errno %{public}d", errno);
578 ret = GetParameter(lockStatusParam, "1", userLockStatus, sizeof(userLockStatus));
579 APPSPAWN_LOGI("get param %{public}s %{public}s", lockStatusParam, userLockStatus);
580 if (ret > 0 && (strcmp(userLockStatus, "0") == 0)) { // 0:解密状态 1:加密状态
581 return true;
582 }
583 return false;
584 }
585
MountDir(AppSpawnMsgDacInfo * info,const char * bundleName,const char * rootPath,const char * targetPath)586 static void MountDir(AppSpawnMsgDacInfo *info, const char *bundleName, const char *rootPath, const char *targetPath)
587 {
588 if (info == NULL || bundleName == NULL || rootPath == NULL || targetPath == NULL) {
589 return;
590 }
591
592 const int userIdBase = UID_BASE;
593 char path[MAX_SANDBOX_BUFFER] = {0};
594 int ret = snprintf_s(path, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%u/%s%s", rootPath,
595 info->uid / userIdBase, bundleName, targetPath);
596 if (ret <= 0) {
597 APPSPAWN_LOGE("snprintf_s path failed, errno %{public}d", errno);
598 return;
599 }
600
601 if (access(path, F_OK) == 0) {
602 return;
603 }
604
605 ret = MakeDirRec(path, DIR_MODE, 1);
606 APPSPAWN_CHECK(ret == 0, return, "mkdir %{public}s failed, ret %{public}d", path, ret);
607
608 if (mount(path, path, NULL, MS_BIND | MS_REC, NULL) != 0) {
609 APPSPAWN_LOGI("bind mount %{public}s failed, error %{public}d", path, errno);
610 return;
611 }
612 if (mount(NULL, path, NULL, MS_SHARED, NULL) != 0) {
613 APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno);
614 } else {
615 APPSPAWN_LOGI("mount path %{public}s to shared success", path);
616 }
617 }
618
619 static const MountSharedTemplate MOUNT_SHARED_MAP[] = {
620 {"/data/storage/el2", NULL},
621 {"/data/storage/el3", NULL},
622 {"/data/storage/el4", NULL},
623 {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"},
624 };
625
MountInShared(const AppSpawnMsgDacInfo * info,const char * rootPath,const char * src,const char * target)626 static int MountInShared(const AppSpawnMsgDacInfo *info, const char *rootPath, const char *src, const char *target)
627 {
628 if (info == NULL) {
629 return APPSPAWN_ARG_INVALID;
630 }
631
632 char path[MAX_SANDBOX_BUFFER] = {0};
633 int ret = snprintf_s(path, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%u/app-root/%s", rootPath,
634 info->uid / UID_BASE, target);
635 if (ret <= 0) {
636 APPSPAWN_LOGE("snprintf_s path failed, errno %{public}d", errno);
637 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
638 }
639
640 char currentUserPath[MAX_SANDBOX_BUFFER] = {0};
641 ret = snprintf_s(currentUserPath, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/currentUser", path);
642 if (ret <= 0) {
643 APPSPAWN_LOGE("snprintf_s currentUserPath failed, errno %{public}d", errno);
644 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
645 }
646
647 if (access(currentUserPath, F_OK) == 0) {
648 return 0;
649 }
650
651 ret = MakeDirRec(path, DIR_MODE, 1);
652 if (ret != 0) {
653 APPSPAWN_LOGE("mkdir %{public}s failed, ret %{public}d", path, ret);
654 return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL;
655 }
656
657 if (mount(src, path, NULL, MS_BIND | MS_REC, NULL) != 0) {
658 APPSPAWN_LOGI("bind mount %{public}s to %{public}s failed, error %{public}d", src, path, errno);
659 return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL;
660 }
661 if (mount(NULL, path, NULL, MS_SHARED, NULL) != 0) {
662 APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno);
663 return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL;
664 }
665
666 return 0;
667 }
668
SharedMountInSharefs(const AppSpawnMsgDacInfo * info,const char * rootPath,const char * src,const char * target)669 static int SharedMountInSharefs(const AppSpawnMsgDacInfo *info, const char *rootPath,
670 const char *src, const char *target)
671 {
672 char currentUserPath[MAX_SANDBOX_BUFFER] = {0};
673 int ret = snprintf_s(currentUserPath, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/currentUser", target);
674 if (ret <= 0) {
675 APPSPAWN_LOGE("snprintf_s currentUserPath failed, errno %{public}d", errno);
676 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
677 }
678
679 if (access(currentUserPath, F_OK) == 0) {
680 return 0;
681 }
682
683 ret = MakeDirRec(target, DIR_MODE, 1);
684 if (ret != 0) {
685 APPSPAWN_LOGE("mkdir %{public}s failed, ret %{public}d", target, ret);
686 return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL;
687 }
688
689 char options[OPTIONS_MAX_LEN] = {0};
690 ret = snprintf_s(options, OPTIONS_MAX_LEN, OPTIONS_MAX_LEN - 1, "override_support_delete,user_id=%d",
691 info->uid / UID_BASE);
692 if (ret <= 0) {
693 APPSPAWN_LOGE("snprintf_s options failed, errno %{public}d", errno);
694 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
695 }
696
697 if (mount(src, target, "sharefs", MS_NODEV, options) != 0) {
698 APPSPAWN_LOGE("sharefs mount %{public}s to %{public}s failed, error %{public}d",
699 src, target, errno);
700 return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL;
701 }
702 if (mount(NULL, target, NULL, MS_SHARED, NULL) != 0) {
703 APPSPAWN_LOGE("mount path %{public}s to shared failed, errno %{public}d", target, errno);
704 return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL;
705 }
706
707 return 0;
708 }
709
UpdateStorageDir(const SandboxContext * context,AppSpawnSandboxCfg * sandbox,const AppSpawnMsgDacInfo * info)710 static void UpdateStorageDir(const SandboxContext *context, AppSpawnSandboxCfg *sandbox, const AppSpawnMsgDacInfo *info)
711 {
712 const char mntUser[] = "/mnt/user";
713 const char nosharefsDocs[] = "nosharefs/docs";
714 const char sharefsDocs[] = "sharefs/docs";
715 const char rootPath[] = "/mnt/sandbox";
716 const char userPath[] = "/storage/Users";
717
718 /* /mnt/user/<currentUserId>/nosharefs/Docs */
719 char nosharefsDocsDir[MAX_SANDBOX_BUFFER] = {0};
720 int ret = snprintf_s(nosharefsDocsDir, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%d/%s",
721 mntUser, info->uid / UID_BASE, nosharefsDocs);
722 if (ret <= 0) {
723 APPSPAWN_LOGE("snprintf_s nosharefsDocsDir failed, errno %{public}d", errno);
724 return;
725 }
726
727 /* /mnt/user/<currentUserId>/sharefs/Docs */
728 char sharefsDocsDir[MAX_SANDBOX_BUFFER] = {0};
729 ret = snprintf_s(sharefsDocsDir, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%d/%s",
730 mntUser, info->uid / UID_BASE, sharefsDocs);
731 if (ret <= 0) {
732 APPSPAWN_LOGE("snprintf_s sharefsDocsDir failed, errno %{public}d", errno);
733 return;
734 }
735
736 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, FILE_ACCESS_MANAGER_MODE);
737 int res = CheckSpawningPermissionFlagSet(context, index);
738 if (res == 0) {
739 char storageUserPath[MAX_SANDBOX_BUFFER] = {0};
740 ret = snprintf_s(storageUserPath, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%d/app-root/%s", rootPath,
741 info->uid / UID_BASE, userPath);
742 if (ret <= 0) {
743 APPSPAWN_LOGE("snprintf_s storageUserPath failed, errno %{public}d", errno);
744 return;
745 }
746 /* mount /mnt/user/<currentUserId>/sharefs/docs to /mnt/sandbox/<currentUserId>/app-root/storage/Users */
747 ret = SharedMountInSharefs(info, rootPath, sharefsDocsDir, storageUserPath);
748 } else {
749 /* mount /mnt/user/<currentUserId>/nosharefs/docs to /mnt/sandbox/<currentUserId>/app-root/storage/Users */
750 ret = MountInShared(info, rootPath, nosharefsDocsDir, userPath);
751 }
752 if (ret != 0) {
753 APPSPAWN_LOGE("Update storage dir, ret %{public}d", ret);
754 }
755 APPSPAWN_LOGI("Update %{public}s storage dir success", res == 0 ? "sharefs dir" : "no sharefs dir");
756 }
757
MountDirToShared(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)758 static void MountDirToShared(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
759 {
760 const char rootPath[] = "/mnt/sandbox/";
761 const char nwebPath[] = "/mnt/nweb";
762 const char nwebTmpPath[] = "/mnt/nweb/tmp";
763 const char appRootName[] = "app-root";
764 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
765 if (info == NULL || context->bundleName == NULL) {
766 return;
767 }
768
769 UpdateStorageDir(context, sandbox, info);
770
771 MountDir(info, appRootName, rootPath, nwebPath);
772 MountDir(info, appRootName, rootPath, nwebTmpPath);
773
774 if (IsUnlockStatus(info->uid)) {
775 return;
776 }
777
778 int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]);
779 for (int i = 0; i < length; i++) {
780 if (MOUNT_SHARED_MAP[i].permission == NULL) {
781 MountDir(info, context->bundleName, rootPath, MOUNT_SHARED_MAP[i].sandboxPath);
782 } else {
783 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, MOUNT_SHARED_MAP[i].permission);
784 APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index);
785 if (CheckSpawningPermissionFlagSet(context, index)) {
786 MountDir(info, context->bundleName, rootPath, MOUNT_SHARED_MAP[i].sandboxPath);
787 }
788 }
789 }
790 char lockSbxPathStamp[MAX_SANDBOX_BUFFER] = { 0 };
791 int ret = 0;
792 if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX_TYPE) != 0) {
793 ret = snprintf_s(lockSbxPathStamp, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%d/isolated/%s_locked",
794 rootPath, info->uid / UID_BASE, context->bundleName);
795 } else {
796 ret = snprintf_s(lockSbxPathStamp, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%d/%s_locked",
797 rootPath, info->uid / UID_BASE, context->bundleName);
798 }
799 if (ret <= 0) {
800 APPSPAWN_LOGE("snprintf_s lock sandbox path stamp failed");
801 return;
802 }
803
804 CreateSandboxDir(lockSbxPathStamp, FILE_MODE);
805 }
806
UpdateMountPathDepsPath(const SandboxContext * context,SandboxNameGroupNode * groupNode)807 static int UpdateMountPathDepsPath(const SandboxContext *context, SandboxNameGroupNode *groupNode)
808 {
809 PathMountNode *depNode = groupNode->depNode;
810 const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, depNode->source, NULL, NULL);
811 const char *sandboxPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, depNode->target, NULL, NULL);
812 if (srcPath == NULL || sandboxPath == NULL) {
813 APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name);
814 return APPSPAWN_SANDBOX_MOUNT_FAIL;
815 }
816 free(depNode->source);
817 depNode->source = strdup(srcPath);
818 free(depNode->target);
819 depNode->target = strdup(sandboxPath);
820 if (depNode->source == NULL || depNode->target == NULL) {
821 APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name);
822 if (depNode->source) {
823 free(depNode->source);
824 depNode->source = NULL;
825 }
826 if (depNode->target) {
827 free(depNode->target);
828 depNode->target = NULL;
829 }
830 return APPSPAWN_SANDBOX_MOUNT_FAIL;
831 }
832 return 0;
833 }
834
CheckAndCreateDepPath(const SandboxContext * context,const SandboxNameGroupNode * groupNode)835 static bool CheckAndCreateDepPath(const SandboxContext *context, const SandboxNameGroupNode *groupNode)
836 {
837 PathMountNode *mountNode = (PathMountNode *)GetFirstSandboxMountNode(&groupNode->section);
838 if (mountNode == NULL) {
839 return false;
840 }
841
842 // 这里可能需要替换deps的数据
843 VarExtraData *extraData = GetVarExtraData(context, &groupNode->section);
844 const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, mountNode->source, NULL, extraData);
845 if (srcPath == NULL) {
846 return false;
847 }
848 if (access(srcPath, F_OK) == 0) {
849 APPSPAWN_LOGV("Src path %{public}s exist, do not mount", srcPath);
850 return true;
851 }
852 // 不存在,则创建并挂载
853 APPSPAWN_LOGV("Mount depended source: %{public}s", groupNode->depNode->source);
854 CreateSandboxDir(groupNode->depNode->source, FILE_MODE);
855 return false;
856 }
857
MountSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox,const SandboxSection * section,uint32_t op)858 static int MountSandboxConfig(const SandboxContext *context,
859 const AppSpawnSandboxCfg *sandbox, const SandboxSection *section, uint32_t op)
860 {
861 uint32_t operation = (op != MOUNT_PATH_OP_NONE) ? op : 0;
862 SetMountPathOperation(&operation, section->sandboxNode.type);
863 // if sandbox switch is off, don't do symlink work again
864 if (context->sandboxSwitch && sandbox->topSandboxSwitch) {
865 SetMountPathOperation(&operation, MOUNT_PATH_OP_SYMLINK);
866 }
867
868 int ret = DoSandboxNodeMount(context, section, operation);
869 APPSPAWN_CHECK(ret == 0, return ret,
870 "Mount sandbox config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
871
872 if (section->nameGroups == NULL) {
873 return 0;
874 }
875
876 for (uint32_t i = 0; i < section->number; i++) {
877 if (section->nameGroups[i] == NULL) {
878 continue;
879 }
880 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
881 if (groupNode->depMounted != 1) {
882 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX);
883 }
884 SetMountPathOperation(&operation, SANDBOX_TAG_NAME_GROUP);
885 ret = DoSandboxNodeMount(context, &groupNode->section, operation);
886 APPSPAWN_CHECK(ret == 0, return ret,
887 "Mount name group %{public}s fail result: %{public}d", groupNode->section.name, ret);
888 }
889 return 0;
890 }
891
SetExpandSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)892 static int SetExpandSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
893 {
894 int ret = ProcessExpandAppSandboxConfig(context, sandbox, "HspList");
895 APPSPAWN_CHECK(ret == 0, return ret,
896 "Set HspList config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
897 ret = ProcessExpandAppSandboxConfig(context, sandbox, "DataGroup");
898 APPSPAWN_CHECK(ret == 0, return ret,
899 "Set DataGroup config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
900
901 bool mountDestBundlePath = false;
902 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
903 if (msgDomainInfo != NULL) {
904 mountDestBundlePath = (strcmp(msgDomainInfo->apl, APL_SYSTEM_BASIC) == 0) ||
905 (strcmp(msgDomainInfo->apl, APL_SYSTEM_CORE) == 0);
906 }
907 if (mountDestBundlePath || (CheckSpawningMsgFlagSet(context, APP_FLAGS_ACCESS_BUNDLE_DIR) != 0)) {
908 // need permission check for system app here
909 const char *destBundlesPath = GetSandboxRealVar(context,
910 BUFFER_FOR_TARGET, "/data/bundles/", context->rootPath, NULL);
911 CreateSandboxDir(destBundlesPath, FILE_MODE);
912 MountArg mountArg = {PHYSICAL_APP_INSTALL_PATH, destBundlesPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE};
913 ret = SandboxMountPath(&mountArg);
914 APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
915 }
916 return 0;
917 }
918
SetSandboxPackageNameConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)919 static int SetSandboxPackageNameConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
920 {
921 SandboxPackageNameNode *sandboxNode =
922 (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName);
923 if (sandboxNode != NULL) {
924 int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE);
925 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
926 }
927 return 0;
928 }
929
SetSandboxSpawnFlagsConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)930 static int SetSandboxSpawnFlagsConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
931 {
932 ListNode *node = sandbox->spawnFlagsQueue.front.next;
933 while (node != &sandbox->spawnFlagsQueue.front) {
934 SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node);
935 // match flags point
936 if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) {
937 node = node->next;
938 continue;
939 }
940
941 int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE);
942 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
943 node = node->next;
944 }
945 return 0;
946 }
947
SetSandboxPermissionConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)948 static int SetSandboxPermissionConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
949 {
950 APPSPAWN_LOGV("Set permission config");
951 ListNode *node = sandbox->permissionQueue.front.next;
952 while (node != &sandbox->permissionQueue.front) {
953 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
954 if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) {
955 node = node->next;
956 continue;
957 }
958
959 APPSPAWN_LOGV("SetSandboxPermissionConfig permission %{public}d %{public}s",
960 permissionNode->permissionIndex, permissionNode->section.name);
961 int ret = MountSandboxConfig(context, sandbox, &permissionNode->section, MOUNT_PATH_OP_NONE);
962 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
963 node = node->next;
964 }
965 return 0;
966 }
967
SetOverlayAppSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)968 static int SetOverlayAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
969 {
970 if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_OVERLAY)) {
971 return 0;
972 }
973 int ret = ProcessExpandAppSandboxConfig(context, sandbox, "Overlay");
974 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
975 return 0;
976 }
977
SetBundleResourceSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)978 static int SetBundleResourceSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
979 {
980 if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_BUNDLE_RESOURCES)) {
981 return 0;
982 }
983 const char *destPath = GetSandboxRealVar(context,
984 BUFFER_FOR_TARGET, "/data/storage/bundle_resources/", context->rootPath, NULL);
985 CreateSandboxDir(destPath, FILE_MODE);
986 MountArg mountArg = {
987 "/data/service/el1/public/bms/bundle_resources/", destPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE
988 };
989 int ret = SandboxMountPath(&mountArg);
990 return ret;
991 }
992
ChangeCurrentDir(const SandboxContext * context)993 static int32_t ChangeCurrentDir(const SandboxContext *context)
994 {
995 int32_t ret = 0;
996 ret = chdir(context->rootPath);
997 APPSPAWN_CHECK(ret == 0, return ret,
998 "chdir failed, app: %{public}s, path: %{public}s errno: %{public}d",
999 context->bundleName, context->rootPath, errno);
1000
1001 if (context->sandboxShared) {
1002 ret = chroot(context->rootPath);
1003 APPSPAWN_CHECK(ret == 0, return ret,
1004 "chroot failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
1005 return ret;
1006 }
1007 ret = syscall(SYS_pivot_root, context->rootPath, context->rootPath);
1008 APPSPAWN_CHECK(ret == 0, return ret,
1009 "pivot root failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
1010 ret = umount2(".", MNT_DETACH);
1011 APPSPAWN_CHECK(ret == 0, return ret,
1012 "MNT_DETACH failed, path: %{public}s errno: %{public}d", context->rootPath, errno);
1013 APPSPAWN_LOGV("ChangeCurrentDir %{public}s ", context->rootPath);
1014 return ret;
1015 }
1016
SandboxRootFolderCreateNoShare(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox,bool remountProc)1017 static int SandboxRootFolderCreateNoShare(
1018 const SandboxContext *context, const AppSpawnSandboxCfg *sandbox, bool remountProc)
1019 {
1020 APPSPAWN_LOGV("SandboxRootFolderCreateNoShare %{public}s ", context->rootPath);
1021 int ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
1022 APPSPAWN_CHECK(ret == 0, return ret,
1023 "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
1024
1025 MountArg arg = {context->rootPath, context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL, MS_SLAVE};
1026 ret = SandboxMountPath(&arg);
1027 APPSPAWN_CHECK(ret == 0, return ret,
1028 "mount path failed, app: %{public}s errno: %{public}d", context->rootPath, ret);
1029 return ret;
1030 }
1031
SandboxRootFolderCreate(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)1032 static int SandboxRootFolderCreate(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
1033 {
1034 APPSPAWN_LOGV("topSandboxSwitch %{public}d sandboxSwitch: %{public}d sandboxShared: %{public}d \n",
1035 sandbox->topSandboxSwitch, context->sandboxSwitch, context->sandboxShared);
1036
1037 int ret = 0;
1038 if (sandbox->topSandboxSwitch == 0 || context->sandboxSwitch == 0) {
1039 ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
1040 APPSPAWN_CHECK(ret == 0, return ret,
1041 "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
1042 // bind mount "/" to /mnt/sandbox/<packageName> path
1043 // rootfs: to do more resources bind mount here to get more strict resources constraints
1044 ret = mount("/", context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL);
1045 APPSPAWN_CHECK(ret == 0, return ret,
1046 "mount bind / failed, app: %{public}s errno: %{public}d", context->rootPath, errno);
1047 } else if (!context->sandboxShared) {
1048 bool remountProc = !context->nwebspawn && ((sandbox->sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID);
1049 ret = SandboxRootFolderCreateNoShare(context, sandbox, remountProc);
1050 }
1051 return ret;
1052 }
1053
IsSandboxMounted(const AppSpawnSandboxCfg * sandbox,const char * name,const char * rootPath)1054 static bool IsSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, const char *rootPath)
1055 {
1056 char path[PATH_MAX] = {};
1057 int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX);
1058 APPSPAWN_CHECK(len > 0, return false, "Failed to format path");
1059
1060 FILE *f = fopen(path, "rb");
1061 if (f != NULL) {
1062 fclose(f);
1063 #ifndef APPSPAWN_TEST
1064 return true;
1065 #endif
1066 }
1067 return false;
1068 }
1069
SetSandboxMounted(const AppSpawnSandboxCfg * sandbox,const char * name,char * rootPath)1070 static int SetSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, char *rootPath)
1071 {
1072 APPSPAWN_LOGW("SetSystemConstMounted %{public}s ", rootPath);
1073 char path[PATH_MAX] = {};
1074 int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX);
1075 APPSPAWN_CHECK(len > 0, return 0, "Failed to format path");
1076
1077 FILE *f = fopen(path, "wb");
1078 if (f != NULL) {
1079 fclose(f);
1080 }
1081 return 0;
1082 }
1083
UnmountPath(char * rootPath,uint32_t len,const SandboxMountNode * sandboxNode)1084 static void UnmountPath(char *rootPath, uint32_t len, const SandboxMountNode *sandboxNode)
1085 {
1086 if (sandboxNode->type == SANDBOX_TAG_MOUNT_PATH) {
1087 PathMountNode *pathNode = (PathMountNode *)sandboxNode;
1088 int ret = strcat_s(rootPath, len, pathNode->target);
1089 APPSPAWN_CHECK(ret == 0, return, "Failed to format");
1090 APPSPAWN_LOGV("Unmount sandbox config sandbox path %{public}s ", rootPath);
1091 ret = umount2(rootPath, MNT_DETACH);
1092 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount2 %{public}s errno: %{public}d", rootPath, errno);
1093 }
1094 }
1095
UnmountDepPaths(const AppSpawnSandboxCfg * sandbox,uid_t uid)1096 int UnmountDepPaths(const AppSpawnSandboxCfg *sandbox, uid_t uid)
1097 {
1098 APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context");
1099 APPSPAWN_LOGI("Unmount sandbox mount-paths-deps %{public}u ", sandbox->depNodeCount);
1100 char path[PATH_MAX] = {};
1101 int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE);
1102 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1);
1103 uint32_t rootLen = strlen(path);
1104 for (uint32_t i = 0; i < sandbox->depNodeCount; i++) {
1105 SandboxNameGroupNode *groupNode = sandbox->depGroupNodes[i];
1106 if (groupNode == NULL || groupNode->depNode == NULL) {
1107 continue;
1108 }
1109 // unmount this deps
1110 UnmountPath(path, sizeof(path), &groupNode->depNode->sandboxNode);
1111 path[rootLen] = '\0';
1112 }
1113 return 0;
1114 }
1115
UnmountSandboxConfigs(const AppSpawnSandboxCfg * sandbox,uid_t uid,const char * name)1116 int UnmountSandboxConfigs(const AppSpawnSandboxCfg *sandbox, uid_t uid, const char *name)
1117 {
1118 APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context");
1119 APPSPAWN_CHECK(name != NULL, return -1, "Invalid name");
1120 char path[PATH_MAX] = {};
1121 int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE);
1122 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1);
1123 uint32_t rootLen = strlen(path);
1124 APPSPAWN_LOGI("Unmount sandbox %{public}s root: %{public}s", name, path);
1125
1126 if (!IsSandboxMounted(sandbox, name, path)) {
1127 return 0;
1128 }
1129
1130 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, name);
1131 if (section == NULL) {
1132 return 0;
1133 }
1134 ListNode *node = section->front.next;
1135 while (node != §ion->front) {
1136 SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
1137 UnmountPath(path, sizeof(path), sandboxNode);
1138 path[rootLen] = '\0';
1139 // get next
1140 node = node->next;
1141 }
1142
1143 // delete stamp file
1144 ret = strcat_s(path, sizeof(path), SANDBOX_STAMP_FILE_SUFFIX);
1145 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return 0);
1146 APPSPAWN_LOGI("Unmount sandbox %{public}s ", path);
1147 unlink(path);
1148 return 0;
1149 }
1150
1151 // Check whether the process incubation contains the ohos.permission.ACCESS_DLP_FILE permission
IsADFPermission(AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property)1152 static bool IsADFPermission(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property)
1153 {
1154 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, ACCESS_DLP_FILE_MODE);
1155 if (index > 0 && CheckAppPermissionFlagSet(property, index)) {
1156 return true;
1157 }
1158 if (GetBundleName(property) != NULL && strstr(GetBundleName(property), "com.ohos.dlpmanager") != NULL) {
1159 return true;
1160 }
1161 return false;
1162 }
1163
StagedMountSystemConst(AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property,int nwebspawn)1164 int StagedMountSystemConst(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
1165 {
1166 APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
1167 /**
1168 * system-const 处理逻辑
1169 * root-dir "/mnt/sandbox/app-root/<currentUserId>"
1170 * 遍历system-const, 处理mount path -- 可以清除配置
1171 * src = mount-path.src-path
1172 * dst = root-dir + mount-path.sandbox-path
1173 *
1174 * 遍历name-groups,处理mount path
1175 * 检查type,必须是 system-const
1176 * 如果存在 mount-paths-deps
1177 * src = mount-path.src-path
1178 * dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path>
1179 * 否则:
1180 * src = mount-path.src-path
1181 * dst = root-dir + mount-path.sandbox-path
1182 */
1183 SandboxContext *context = GetSandboxContext();
1184 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR);
1185 int ret = InitSandboxContext(context, sandbox, property, nwebspawn);
1186 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1187
1188 if (IsSandboxMounted(sandbox, "system-const", context->rootPath) && IsADFPermission(sandbox, property) != true) {
1189 APPSPAWN_LOGV("Sandbox system-const %{public}s has been mount", context->rootPath);
1190 DeleteSandboxContext(context);
1191 return 0;
1192 }
1193
1194 APPSPAWN_LOGV("Set sandbox system-const %{public}s", context->rootPath);
1195 uint32_t operation = 0;
1196 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX); // 首次挂载,使用sandbox替换
1197 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const");
1198 if (section != NULL) {
1199 ret = MountSandboxConfig(context, sandbox, section, operation);
1200 }
1201 SetSandboxMounted(sandbox, "system-const", context->rootPath);
1202 DeleteSandboxContext(context);
1203 return ret;
1204 }
1205
MountDepGroups(const SandboxContext * context,SandboxNameGroupNode * groupNode)1206 static int MountDepGroups(const SandboxContext *context, SandboxNameGroupNode *groupNode)
1207 {
1208 /**
1209 * 在unshare前处理mount-paths-deps 处理逻辑
1210 * 1.判断是否有mount-paths-deps节点,没有直接返回;
1211 * 2.填充json文件中路径的变量值;
1212 * 3.校验deps-mode的值是否是not-exists
1213 * 是not-exist则判断mount-paths.src-path是否存在,若不存在则创建并挂载mount-paths-deps中的目录
1214 * 若存在则不挂载mount-paths-deps中的目录
1215 * 是always则创建并挂载mount-paths-deps中的目录;
1216 * deps-mode默认值为always;
1217 *
1218 */
1219 int ret = 0;
1220 if (groupNode == NULL || groupNode->depNode == NULL) {
1221 return 0;
1222 }
1223
1224 ret = UpdateMountPathDepsPath(context, groupNode);
1225 APPSPAWN_CHECK(ret == 0, return ret, "Failed to update deps path name groups %{public}s", groupNode->section.name);
1226
1227 if (groupNode->depMode == MOUNT_MODE_NOT_EXIST && CheckAndCreateDepPath(context, groupNode)) {
1228 return 0;
1229 }
1230
1231 uint32_t operation = 0;
1232 SetMountPathOperation(&operation, MOUNT_PATH_OP_UNMOUNT);
1233 groupNode->depMounted = 1;
1234 ret = DoSandboxPathNodeMount(context, &groupNode->section, groupNode->depNode, operation);
1235 if (ret != 0) {
1236 APPSPAWN_LOGE("Mount deps root fail %{public}s", groupNode->section.name);
1237 }
1238 return ret;
1239 }
1240
SetSystemConstDepGroups(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1241 static int SetSystemConstDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1242 {
1243 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const");
1244 if (section == NULL || section->nameGroups == NULL) {
1245 return 0;
1246 }
1247
1248 int ret = 0;
1249 for (uint32_t i = 0; i < section->number; i++) {
1250 if (section->nameGroups[i] == NULL) {
1251 continue;
1252 }
1253 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
1254 ret = MountDepGroups(context, groupNode);
1255 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1256 }
1257 return ret;
1258 }
1259
SetAppVariableDepGroups(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1260 static int SetAppVariableDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1261 {
1262 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable");
1263 if (section == NULL || section->nameGroups == NULL) {
1264 return 0;
1265 }
1266
1267 int ret = 0;
1268 for (uint32_t i = 0; i < section->number; i++) {
1269 if (section->nameGroups[i] == NULL) {
1270 continue;
1271 }
1272 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i];
1273 ret = MountDepGroups(context, groupNode);
1274 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1275 }
1276 return ret;
1277 }
1278
SetSpawnFlagsDepGroups(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1279 static int SetSpawnFlagsDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1280 {
1281 ListNode *node = sandbox->spawnFlagsQueue.front.next;
1282 int ret = 0;
1283 while (node != &sandbox->spawnFlagsQueue.front) {
1284 SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node);
1285 // match flags point
1286 if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) {
1287 node = node->next;
1288 continue;
1289 }
1290
1291 if (sandboxNode->section.nameGroups == NULL) {
1292 node = node->next;
1293 continue;
1294 }
1295
1296 for (uint32_t i = 0; i < sandboxNode->section.number; i++) {
1297 if (sandboxNode->section.nameGroups[i] == NULL) {
1298 continue;
1299 }
1300 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)sandboxNode->section.nameGroups[i];
1301 ret = MountDepGroups(context, groupNode);
1302 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1303 }
1304 node = node->next;
1305 }
1306 return ret;
1307 }
1308
SetPackageNameDepGroups(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1309 static int SetPackageNameDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1310 {
1311 SandboxPackageNameNode *sandboxNode =
1312 (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName);
1313 if (sandboxNode == NULL || sandboxNode->section.nameGroups == NULL) {
1314 return 0;
1315 }
1316
1317 int ret = 0;
1318 for (uint32_t i = 0; i < sandboxNode->section.number; i++) {
1319 if (sandboxNode->section.nameGroups[i] == NULL) {
1320 continue;
1321 }
1322 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)sandboxNode->section.nameGroups[i];
1323 ret = MountDepGroups(context, groupNode);
1324 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1325 }
1326 return ret;
1327 }
1328
SetPermissionDepGroups(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1329 static int SetPermissionDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1330 {
1331 ListNode *node = sandbox->permissionQueue.front.next;
1332 int ret = 0;
1333 while (node != &sandbox->permissionQueue.front) {
1334 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
1335 // match flags point
1336 if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) {
1337 node = node->next;
1338 continue;
1339 }
1340
1341 if (permissionNode->section.nameGroups == NULL) {
1342 node = node->next;
1343 continue;
1344 }
1345
1346 for (uint32_t i = 0; i < permissionNode->section.number; i++) {
1347 if (permissionNode->section.nameGroups[i] == NULL) {
1348 continue;
1349 }
1350 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)permissionNode->section.nameGroups[i];
1351 ret = MountDepGroups(context, groupNode);
1352 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups");
1353 }
1354 node = node->next;
1355 }
1356 return ret;
1357 }
1358
1359 // The execution of the preunshare phase depends on the mounted mount point
StagedDepGroupMounts(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1360 static int StagedDepGroupMounts(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1361 {
1362 int ret = SetSystemConstDepGroups(context, sandbox);
1363 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set system const deps groups");
1364
1365 ret = SetAppVariableDepGroups(context, sandbox);
1366 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set app variable deps groups");
1367
1368 ret = SetSpawnFlagsDepGroups(context, sandbox);
1369 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set spawn flags deps groups");
1370
1371 ret = SetPackageNameDepGroups(context, sandbox);
1372 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set package name deps groups");
1373
1374 ret = SetPermissionDepGroups(context, sandbox);
1375 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set permission deps groups");
1376
1377 return ret;
1378 }
1379
StagedMountPreUnShare(const SandboxContext * context,AppSpawnSandboxCfg * sandbox)1380 int StagedMountPreUnShare(const SandboxContext *context, AppSpawnSandboxCfg *sandbox)
1381 {
1382 APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context");
1383 APPSPAWN_LOGV("Set sandbox config before unshare group count %{public}d", sandbox->depNodeCount);
1384
1385 MountDirToShared(context, sandbox);
1386 int ret = StagedDepGroupMounts(context, sandbox);
1387
1388 return ret;
1389 }
1390
SetAppVariableConfig(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)1391 static int SetAppVariableConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
1392 {
1393 /**
1394 * app-variable 处理逻辑
1395 * root-dir global.sandbox-root
1396 * app-variabl, 处理mount path
1397 * src = mount-path.src-path
1398 * dst = root-dir + mount-path.src-path
1399 * 遍历name-groups,处理mount path
1400 * 如果存在 mount-paths-deps
1401 * dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path>
1402 * 否则:
1403 * src = mount-path.src-path
1404 * dst = root-dir + mount-path.sandbox-path
1405 */
1406 int ret = 0;
1407 // 首次挂载,使用sandbox替换
1408 uint32_t operation = 0;
1409 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX);
1410 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable");
1411 if (section == NULL) {
1412 return 0;
1413 }
1414 ret = MountSandboxConfig(context, sandbox, section, operation);
1415 APPSPAWN_CHECK(ret == 0, return ret,
1416 "Set app-variable config fail result: %{public}d, app: %{public}s", ret, context->bundleName);
1417 return 0;
1418 }
1419
StagedMountPostUnshare(const SandboxContext * context,const AppSpawnSandboxCfg * sandbox)1420 int StagedMountPostUnshare(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox)
1421 {
1422 APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context");
1423 APPSPAWN_LOGV("Set sandbox config after unshare ");
1424
1425 int ret = SetAppVariableConfig(context, sandbox);
1426 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1427 if (!context->nwebspawn) {
1428 ret = SetExpandSandboxConfig(context, sandbox);
1429 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1430 }
1431
1432 ret = SetSandboxSpawnFlagsConfig(context, sandbox);
1433 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1434
1435 ret = SetSandboxPackageNameConfig(context, sandbox);
1436 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1437
1438 ret = SetSandboxPermissionConfig(context, sandbox);
1439 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1440 return ret;
1441 }
1442
1443 #ifdef APPSPAWN_MOUNT_TMPSHM
MountDevShmPath(SandboxContext * context)1444 static void MountDevShmPath(SandboxContext *context)
1445 {
1446 char sandboxDevShmPath[PATH_MAX] = {};
1447 int ret = strcpy_s(sandboxDevShmPath, sizeof(sandboxDevShmPath), context->rootPath);
1448 APPSPAWN_CHECK(ret == 0, return, "Failed to strcpy rootPath");
1449 ret = strcat_s(sandboxDevShmPath, sizeof(sandboxDevShmPath), DEV_SHM_DIR);
1450 APPSPAWN_CHECK(ret == 0, return, "Failed to format devShmPath");
1451 int result = mount("tmpfs", sandboxDevShmPath, "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, "size=32M");
1452 if (result != 0) {
1453 APPSPAWN_LOGW("Error mounting %{public}s to tmpfs, errno %{public}d", sandboxDevShmPath, errno);
1454 }
1455 }
1456 #endif
1457
MountSandboxConfigs(AppSpawnSandboxCfg * sandbox,const AppSpawningCtx * property,int nwebspawn)1458 int MountSandboxConfigs(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn)
1459 {
1460 APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
1461 APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property));
1462
1463 SandboxContext *context = GetSandboxContext();
1464 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR);
1465 int ret = InitSandboxContext(context, sandbox, property, nwebspawn);
1466 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
1467
1468 APPSPAWN_LOGV("Set sandbox config %{public}s sandboxNsFlags 0x%{public}x",
1469 context->rootPath, context->sandboxNsFlags);
1470 do {
1471 ret = StagedMountPreUnShare(context, sandbox);
1472 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1473
1474 CreateSandboxDir(context->rootPath, FILE_MODE);
1475 // add pid to a new mnt namespace
1476 ret = unshare(context->sandboxNsFlags);
1477 APPSPAWN_CHECK(ret == 0, break,
1478 "unshare failed, app: %{public}s errno: %{public}d", context->bundleName, errno);
1479 if ((context->sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) {
1480 ret = EnableNewNetNamespace();
1481 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1482 }
1483
1484 ret = SandboxRootFolderCreate(context, sandbox);
1485 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1486
1487 ret = StagedMountPostUnshare(context, sandbox);
1488 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1489
1490 ret = SetOverlayAppSandboxConfig(context, sandbox);
1491 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1492 ret = SetBundleResourceSandboxConfig(context, sandbox);
1493 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1494
1495 #ifdef APPSPAWN_MOUNT_TMPSHM
1496 MountDevShmPath(context);
1497 #endif
1498 ret = ChangeCurrentDir(context);
1499 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
1500 #if defined(APPSPAWN_MOUNT_TMPSHM) && defined(WITH_SELINUX)
1501 Restorecon(DEV_SHM_DIR);
1502 #endif
1503 APPSPAWN_LOGV("Change root dir success %{public}s ", context->rootPath);
1504 } while (0);
1505 DeleteSandboxContext(context);
1506 return ret;
1507 }
1508