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