1 /*
2 * Copyright (C) 2025 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 <cerrno>
17 #include <sys/mount.h>
18 #include <vector>
19 #include <cstring>
20 #include <fstream>
21 #include <sstream>
22 #include <algorithm>
23 #include <regex>
24 #include <map>
25 #include "securec.h"
26 #include "nlohmann/json.hpp"
27
28 #include "sandbox_shared_mount.h"
29 #include "appspawn_mount_permission.h"
30 #include "appspawn_utils.h"
31 #include "parameter.h"
32
33 #define USER_ID_SIZE 16
34 #define DIR_MODE 0711
35 #define LOCK_STATUS_SIZE 16
36
37 #define DATA_GROUP_SOCKET_TYPE "DataGroup"
38 #define GROUPLIST_KEY_DATAGROUPID "dataGroupId"
39 #define GROUPLIST_KEY_GID "gid"
40 #define GROUPLIST_KEY_DIR "dir"
41 #define GROUPLIST_KEY_UUID "uuid"
42
43 static const MountSharedTemplate MOUNT_SHARED_MAP[] = {
44 {"/data/storage/el2", nullptr},
45 {"/data/storage/el3", nullptr},
46 {"/data/storage/el4", nullptr},
47 {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"},
48 };
49
50 static const DataGroupSandboxPathTemplate DATA_GROUP_SANDBOX_PATH_MAP[] = {
51 {"el2", EL2, "/data/storage/el2/group/", nullptr},
52 {"el3", EL3, "/data/storage/el3/group/", nullptr},
53 {"el4", EL4, "/data/storage/el4/group/", nullptr},
54 {"el5", EL5, "/data/storage/el5/group/", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"},
55 };
56
57 static std::map<std::string, int> g_mountInfoMap;
58
GetElxInfoFromDir(const char * path)59 int GetElxInfoFromDir(const char *path)
60 {
61 int ret = ELX_MAX;
62 if (path == nullptr) {
63 return ret;
64 }
65 uint32_t count = ARRAY_LENGTH(DATA_GROUP_SANDBOX_PATH_MAP);
66 for (uint32_t i = 0; i < count; ++i) {
67 if (strstr(path, DATA_GROUP_SANDBOX_PATH_MAP[i].elxName) != nullptr) {
68 return DATA_GROUP_SANDBOX_PATH_MAP[i].category;
69 }
70 }
71 APPSPAWN_LOGE("Get elx info from dir failed, path %{public}s", path);
72 return ret;
73 }
74
GetDataGroupArgTemplate(uint32_t category)75 const DataGroupSandboxPathTemplate *GetDataGroupArgTemplate(uint32_t category)
76 {
77 uint32_t count = ARRAY_LENGTH(DATA_GROUP_SANDBOX_PATH_MAP);
78 if (category > count) {
79 APPSPAWN_LOGE("category %{public}d is out of range", category);
80 return nullptr;
81 }
82 for (uint32_t i = 0; i < count; ++i) {
83 if (DATA_GROUP_SANDBOX_PATH_MAP[i].category == category) {
84 return &DATA_GROUP_SANDBOX_PATH_MAP[i];
85 }
86 }
87 return nullptr;
88 }
89
IsValidDataGroupItem(nlohmann::json & item)90 bool IsValidDataGroupItem(nlohmann::json &item)
91 {
92 // Check if the item contains the specified key and if the value corresponding to the key is a string
93 if (item.contains(GROUPLIST_KEY_DATAGROUPID) && item[GROUPLIST_KEY_DATAGROUPID].is_string() &&
94 item.contains(GROUPLIST_KEY_GID) && item[GROUPLIST_KEY_GID].is_string() &&
95 item.contains(GROUPLIST_KEY_DIR) && item[GROUPLIST_KEY_DIR].is_string() &&
96 item.contains(GROUPLIST_KEY_UUID) && item[GROUPLIST_KEY_UUID].is_string()) {
97 return true;
98 }
99 return false;
100 }
101
GetEl1BundleMountCount(void)102 void *GetEl1BundleMountCount(void)
103 {
104 return static_cast<void*>(&g_mountInfoMap);
105 }
106
107 #ifndef APPSPAWN_SANDBOX_NEW
IsUnlockStatus(uint32_t uid)108 static bool IsUnlockStatus(uint32_t uid)
109 {
110 const int userIdBase = UID_BASE;
111 uid = uid / userIdBase;
112 if (uid == 0) {
113 return true;
114 }
115 std::string lockStatusParam = "startup.appspawn.lockstatus_" + std::to_string(uid);
116 char userLockStatus[LOCK_STATUS_SIZE] = {0};
117 int ret = GetParameter(lockStatusParam.c_str(), "1", userLockStatus, sizeof(userLockStatus));
118 APPSPAWN_LOGI("get param %{public}s %{public}s", lockStatusParam.c_str(), userLockStatus);
119 if (ret > 0 && (strcmp(userLockStatus, "0") == 0)) { // 0:unlock status 1:lock status
120 return true;
121 }
122 return false;
123 }
124
DoSharedMount(const SharedMountArgs * arg)125 static int DoSharedMount(const SharedMountArgs *arg)
126 {
127 if (arg == nullptr || arg->srcPath == nullptr || arg->destPath == nullptr) {
128 APPSPAWN_LOGE("Invalid arg");
129 return APPSPAWN_ARG_INVALID;
130 }
131
132 APPSPAWN_LOGV("Mount arg: '%{public}s' '%{public}s' %{public}lu '%{public}s' %{public}s => %{public}s",
133 arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE",
134 arg->mountFlags, arg->options, arg->srcPath, arg->destPath);
135
136 int ret = mount(arg->srcPath, arg->destPath, arg->fsType, arg->mountFlags, arg->options);
137 if (ret != 0) {
138 APPSPAWN_LOGE("mount %{public}s to %{public}s failed, errno %{public}d",
139 arg->srcPath, arg->destPath, errno);
140 return ret;
141 }
142 ret = mount(nullptr, arg->destPath, nullptr, arg->mountSharedFlag, nullptr);
143 if (ret != 0) {
144 APPSPAWN_LOGE("mount path %{public}s to shared failed, errno %{public}d", arg->destPath, errno);
145 return ret;
146 }
147 APPSPAWN_LOGI("mount path %{public}s to shared success", arg->destPath);
148 return 0;
149 }
150
SetSandboxPathShared(const std::string & sandboxPath)151 static bool SetSandboxPathShared(const std::string &sandboxPath)
152 {
153 int ret = mount(nullptr, sandboxPath.c_str(), nullptr, MS_SHARED, nullptr);
154 if (ret != 0) {
155 APPSPAWN_LOGW("Need to mount %{public}s to shared, errno %{public}d", sandboxPath.c_str(), errno);
156 return false;
157 }
158 return true;
159 }
160
MountEl1Bundle(const AppSpawningCtx * property,const AppDacInfo * info,const char * bundleName)161 static int MountEl1Bundle(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName)
162 {
163 /* /data/app/el1/bundle/public/<bundleName> */
164 char sourcePath[PATH_MAX_LEN] = {0};
165 int ret = snprintf_s(sourcePath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/data/app/el1/bundle/public/%s", bundleName);
166 if (ret <= 0) {
167 APPSPAWN_LOGE("snprintf data/app/el1/bundle/public/%{public}s failed, errno %{public}d", bundleName, errno);
168 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
169 }
170
171 /* /mnt/sandbox/<currentUserId>/<bundleName>/data/storage/el1/bundle */
172 char targetPath[PATH_MAX_LEN] = {0};
173 ret = snprintf_s(targetPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s/data/storage/el1/bundle",
174 info->uid/ UID_BASE, bundleName);
175 if (ret <= 0) {
176 APPSPAWN_LOGE("snprintf el1 bundle sandbox path failed, errno %{public}d", errno);
177 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
178 }
179
180 ret = MakeDirRec(targetPath, DIR_MODE, 1);
181 if (ret != 0) {
182 APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", targetPath, errno);
183 return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL;
184 }
185
186 ret = umount2(targetPath, MNT_DETACH);
187 if (ret != 0) {
188 APPSPAWN_LOGE("umount2 %{public}s failed, errno %{public}d", targetPath, errno);
189 }
190
191 SharedMountArgs arg = {
192 .srcPath = sourcePath,
193 .destPath = targetPath,
194 .fsType = nullptr,
195 .mountFlags = MS_BIND | MS_REC,
196 .options = nullptr,
197 .mountSharedFlag = MS_SHARED
198 };
199 ret = DoSharedMount(&arg);
200 if (ret != 0) {
201 APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", targetPath, ret);
202 }
203 std::string key = std::to_string(info->uid / UID_BASE) + "-" + std::string(bundleName);
204 g_mountInfoMap[key]++;
205 return ret;
206 }
207
MountWithFileMgr(const AppSpawningCtx * property,const AppDacInfo * info,const char * bundleName)208 static int MountWithFileMgr(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName)
209 {
210 /* /mnt/user/<currentUserId>/nosharefs/docs */
211 char nosharefsDocsDir[PATH_MAX_LEN] = {0};
212 int ret = snprintf_s(nosharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/user/%u/nosharefs/docs",
213 info->uid / UID_BASE);
214 if (ret <= 0) {
215 APPSPAWN_LOGE("snprintf nosharefsDocsDir failed, errno %{public}d", errno);
216 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
217 }
218
219 /* /mnt/sandbox/<currentUser/<bundleName>/storage/Users */
220 char storageUserPath[PATH_MAX_LEN] = {0};
221 ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s/storage/Users",
222 info->uid / UID_BASE, bundleName);
223 if (ret <= 0) {
224 APPSPAWN_LOGE("snprintf storageUserPath failed, errno %{public}d", errno);
225 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
226 }
227
228 // Check whether the directory is a shared mount point
229 if (SetSandboxPathShared(storageUserPath)) {
230 APPSPAWN_LOGI("shared mountpoint is exist");
231 return 0;
232 }
233
234 ret = MakeDirRec(storageUserPath, DIR_MODE, 1);
235 if (ret != 0) {
236 APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", storageUserPath, errno);
237 return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL;
238 }
239
240 SharedMountArgs arg = {
241 .srcPath = nosharefsDocsDir,
242 .destPath = storageUserPath,
243 .fsType = nullptr,
244 .mountFlags = MS_BIND | MS_REC,
245 .options = nullptr,
246 .mountSharedFlag = MS_SHARED
247 };
248 ret = DoSharedMount(&arg);
249 if (ret != 0) {
250 APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", storageUserPath, ret);
251 }
252 return ret;
253 }
254
MountWithOther(const AppSpawningCtx * property,const AppDacInfo * info,const char * bundleName)255 static int MountWithOther(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName)
256 {
257 /* /mnt/user/<currentUserId>/sharefs/docs */
258 char sharefsDocsDir[PATH_MAX_LEN] = {0};
259 int ret = snprintf_s(sharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/user/%u/sharefs/docs",
260 info->uid / UID_BASE);
261 if (ret <= 0) {
262 APPSPAWN_LOGE("snprintf sharefsDocsDir failed, errno %{public}d", errno);
263 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
264 }
265
266 /* /mnt/sandbox/<currentUser/<bundleName>/storage/Users */
267 char storageUserPath[PATH_MAX_LEN] = {0};
268 ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s/storage/Users",
269 info->uid / UID_BASE, bundleName);
270 if (ret <= 0) {
271 APPSPAWN_LOGE("snprintf storageUserPath failed, errno %{public}d", errno);
272 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
273 }
274
275 // Check whether the directory is a shared mount point
276 if (SetSandboxPathShared(storageUserPath)) {
277 APPSPAWN_LOGI("shared mountpoint is exist");
278 return 0;
279 }
280
281 ret = MakeDirRec(storageUserPath, DIR_MODE, 1);
282 if (ret != 0) {
283 APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", storageUserPath, errno);
284 return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL;
285 }
286
287 char options[PATH_MAX_LEN] = {0};
288 ret = snprintf_s(options, PATH_MAX_LEN, PATH_MAX_LEN - 1, "override_support_delete,user_id=%u",
289 info->uid / UID_BASE);
290 if (ret <= 0) {
291 APPSPAWN_LOGE("snprintf options failed, errno %{public}d", errno);
292 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
293 }
294
295 SharedMountArgs arg = {
296 .srcPath = sharefsDocsDir,
297 .destPath = storageUserPath,
298 .fsType = "sharefs",
299 .mountFlags = MS_NODEV,
300 .options = options,
301 .mountSharedFlag = MS_SHARED
302 };
303 ret = DoSharedMount(&arg);
304 if (ret != 0) {
305 APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", storageUserPath, ret);
306 }
307 return ret;
308 }
309
MountStorageUsers(const AppSpawningCtx * property,const AppDacInfo * info,const char * bundleName)310 static void MountStorageUsers(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName)
311 {
312 int ret = 0;
313 int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
314 int checkRes = CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index));
315 if (checkRes == 0) {
316 /* mount /mnt/user/<currentUserId>/sharefs/docs to /mnt/sandbox/<currentUserId>/<bundleName>/storage/Users */
317 ret = MountWithOther(property, info, bundleName);
318 } else {
319 /* mount /mnt/user/<currentUserId>/nosharefs/docs to /mnt/sandbox/<currentUserId>/<bundleName>/storage/Users */
320 ret = MountWithFileMgr(property, info, bundleName);
321 }
322 if (ret != 0) {
323 APPSPAWN_LOGE("Update %{public}s storage dir failed, ret %{public}d",
324 checkRes == 0 ? "sharefs dir" : "no sharefs dir", ret);
325 } else {
326 APPSPAWN_LOGI("Update %{public}s storage dir success", checkRes == 0 ? "sharefs dir" : "no sharefs dir");
327 }
328 }
329
MountSharedMapItem(const AppSpawningCtx * property,const AppDacInfo * info,const char * bundleName,const char * sandboxPathItem)330 static int MountSharedMapItem(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName,
331 const char *sandboxPathItem)
332 {
333 /* /mnt/sandbox/<currentUserId>/<bundleName>/data/storage/el<x> */
334 char sandboxPath[PATH_MAX_LEN] = {0};
335 int ret = snprintf_s(sandboxPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s%s",
336 info->uid / UID_BASE, bundleName, sandboxPathItem);
337 if (ret <= 0) {
338 APPSPAWN_LOGE("snprintf sandboxPath failed, errno %{public}d", errno);
339 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
340 }
341
342 // Check whether the directory is a shared mount point
343 if (SetSandboxPathShared(sandboxPath)) {
344 APPSPAWN_LOGI("shared mountpoint is exist");
345 return 0;
346 }
347
348 ret = MakeDirRec(sandboxPath, DIR_MODE, 1);
349 if (ret != 0) {
350 APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", sandboxPath, errno);
351 return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL;
352 }
353
354 SharedMountArgs arg = {
355 .srcPath = sandboxPath,
356 .destPath = sandboxPath,
357 .fsType = nullptr,
358 .mountFlags = MS_BIND | MS_REC,
359 .options = nullptr,
360 .mountSharedFlag = MS_SHARED
361 };
362 ret = DoSharedMount(&arg);
363 if (ret != 0) {
364 APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", sandboxPath, ret);
365 }
366 return ret;
367 }
368
MountSharedMap(const AppSpawningCtx * property,const AppDacInfo * info,const char * bundleName)369 static void MountSharedMap(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName)
370 {
371 int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]);
372 for (int i = 0; i < length; i++) {
373 if (MOUNT_SHARED_MAP[i].permission == nullptr) {
374 MountSharedMapItem(property, info, bundleName, MOUNT_SHARED_MAP[i].sandboxPath);
375 } else {
376 int index = GetPermissionIndex(nullptr, MOUNT_SHARED_MAP[i].permission);
377 APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index);
378 if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index))) {
379 MountSharedMapItem(property, info, bundleName, MOUNT_SHARED_MAP[i].sandboxPath);
380 }
381 }
382 }
383 APPSPAWN_LOGI("mount shared map success");
384 }
385
CheckPath(const std::string & name)386 static inline bool CheckPath(const std::string& name)
387 {
388 return !name.empty() && name != "." && name != ".." && name.find("/") == std::string::npos;
389 }
390
DataGroupCtxNodeCompare(ListNode * node,void * data)391 static int DataGroupCtxNodeCompare(ListNode *node, void *data)
392 {
393 DataGroupCtx *existingNode = (DataGroupCtx *)ListEntry(node, DataGroupCtx, node);
394 DataGroupCtx *newNode = (DataGroupCtx *)data;
395 if (existingNode == nullptr || newNode == nullptr) {
396 APPSPAWN_LOGE("Invalid param");
397 return APPSPAWN_ARG_INVALID;
398 }
399
400 // compare src path and sandbox path
401 bool isSrcPathEqual = (strcmp(existingNode->srcPath.path, newNode->srcPath.path) == 0);
402 bool isDestPathEqual = (strcmp(existingNode->destPath.path, newNode->destPath.path) == 0);
403
404 return (isSrcPathEqual && isDestPathEqual) ? 0 : 1;
405 }
406
AddDataGroupItemToQueue(AppSpawnMgr * content,const std::string & srcPath,const std::string & destPath,const std::string & dataGroupUuid)407 static int AddDataGroupItemToQueue(AppSpawnMgr *content, const std::string &srcPath, const std::string &destPath,
408 const std::string &dataGroupUuid)
409 {
410 DataGroupCtx *dataGroupNode = (DataGroupCtx *)calloc(1, sizeof(DataGroupCtx));
411 APPSPAWN_CHECK(dataGroupNode != nullptr, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "Calloc dataGroupNode failed");
412 if (strcpy_s(dataGroupNode->srcPath.path, PATH_MAX_LEN - 1, srcPath.c_str()) != EOK ||
413 strcpy_s(dataGroupNode->destPath.path, PATH_MAX_LEN - 1, destPath.c_str()) != EOK ||
414 strcpy_s(dataGroupNode->dataGroupUuid, UUID_MAX_LEN, dataGroupUuid.c_str()) != EOK) {
415 APPSPAWN_LOGE("strcpy dataGroupNode->srcPath failed");
416 free(dataGroupNode);
417 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
418 }
419 dataGroupNode->srcPath.pathLen = strlen(dataGroupNode->srcPath.path);
420 dataGroupNode->destPath.pathLen = strlen(dataGroupNode->destPath.path);
421 ListNode *node = OH_ListFind(&content->dataGroupCtxQueue, (void *)dataGroupNode, DataGroupCtxNodeCompare);
422 if (node != nullptr) {
423 APPSPAWN_LOGI("DataGroupCtxNode %{public}s is exist", dataGroupNode->srcPath.path);
424 free(dataGroupNode);
425 dataGroupNode = nullptr;
426 return 0;
427 }
428 OH_ListInit(&dataGroupNode->node);
429 OH_ListAddTail(&content->dataGroupCtxQueue, &dataGroupNode->node);
430 return 0;
431 }
432
GetExtraInfoByType(const AppSpawningCtx * appPropery,const std::string & type)433 static std::string GetExtraInfoByType(const AppSpawningCtx *appPropery, const std::string &type)
434 {
435 uint32_t len = 0;
436 char *info = reinterpret_cast<char *>(GetAppPropertyExt(appPropery, type.c_str(), &len));
437 if (info == nullptr) {
438 return "";
439 }
440 return std::string(info, len);
441 }
442
DumpDataGroupCtxQueue(const ListNode * front)443 static void DumpDataGroupCtxQueue(const ListNode *front)
444 {
445 if (front == nullptr) {
446 return;
447 }
448
449 uint32_t count = 0;
450 ListNode *node = front->next;
451 while (node != front) {
452 DataGroupCtx *dataGroupNode = (DataGroupCtx *)ListEntry(node, DataGroupCtx, node);
453 count++;
454 APPSPAWN_LOGV(" ************************************** %{public}d", count);
455 APPSPAWN_LOGV(" srcPath: %{public}s", dataGroupNode->srcPath.path);
456 APPSPAWN_LOGV(" destPath: %{public}s", dataGroupNode->destPath.path);
457 APPSPAWN_LOGV(" uuid: %{public}s", dataGroupNode->dataGroupUuid);
458 node = node->next;
459 }
460 }
461
ParseDataGroupList(AppSpawnMgr * content,const AppSpawningCtx * property,AppDacInfo * info,AppSpawnMsgBundleInfo * bundleInfo)462 static int ParseDataGroupList(AppSpawnMgr *content, const AppSpawningCtx *property, AppDacInfo *info,
463 AppSpawnMsgBundleInfo *bundleInfo)
464 {
465 int ret = 0;
466 std::string dataGroupList = GetExtraInfoByType(property, DATA_GROUP_SOCKET_TYPE);
467 if (dataGroupList.length() == 0) {
468 APPSPAWN_LOGE("dataGroupList is empty");
469 return APPSPAWN_ARG_INVALID;
470 }
471
472 nlohmann::json dataGroupJson = nlohmann::json::parse(dataGroupList.c_str(), nullptr, false);
473 APPSPAWN_CHECK(!dataGroupJson.is_discarded() && dataGroupJson.contains(GROUPLIST_KEY_DATAGROUPID) &&
474 dataGroupJson.contains(GROUPLIST_KEY_GID) && dataGroupJson.contains(GROUPLIST_KEY_DIR), return -1,
475 "MountAllGroup: json parse failed");
476
477 nlohmann::json& dataGroupIds = dataGroupJson[GROUPLIST_KEY_DATAGROUPID];
478 nlohmann::json& gids = dataGroupJson[GROUPLIST_KEY_GID];
479 nlohmann::json& dirs = dataGroupJson[GROUPLIST_KEY_DIR];
480 APPSPAWN_CHECK(dataGroupIds.is_array() && gids.is_array() && dirs.is_array() && dataGroupIds.size() == gids.size()
481 && dataGroupIds.size() == dirs.size(), return -1, "MountAllGroup: value is not arrary or sizes are not same");
482 for (uint32_t i = 0; i < dataGroupIds.size(); i++) {
483 // elements in json arrary can be different type
484 APPSPAWN_CHECK(dataGroupIds[i].is_string() && gids[i].is_string() && dirs[i].is_string(),
485 return -1, "MountAllGroup: element type error");
486
487 std::string srcPath = dirs[i];
488 APPSPAWN_CHECK(!CheckPath(srcPath), return -1, "MountAllGroup: path error");
489
490 size_t lastPathSplitPos = srcPath.find_last_of("/");
491 APPSPAWN_CHECK(lastPathSplitPos != std::string::npos, return -1, "MountAllGroup: path error");
492 std::string dataGroupUuid = srcPath.substr(lastPathSplitPos + 1);
493
494 uint32_t elxValue = GetElxInfoFromDir(srcPath.c_str());
495 APPSPAWN_CHECK((elxValue >= EL2 && elxValue < ELX_MAX), return -1, "Get elx value failed");
496
497 const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(elxValue);
498 APPSPAWN_CHECK(templateItem != nullptr, return -1, "Get data group arg template failed");
499
500 // If permission isn't null, need check permission flag
501 if (templateItem->permission != nullptr) {
502 int index = GetPermissionIndex(nullptr, templateItem->permission);
503 APPSPAWN_LOGV("mount dir no lock mount permission flag %{public}d", index);
504 if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index)) == 0) {
505 continue;
506 }
507 }
508
509 // sandboxPath: /mnt/sandbox/<currentUserId>/<bundleName>/data/storage/el<x>/group
510 std::string sandboxPath = "/mnt/sandbox/" + std::to_string(info->uid / UID_BASE) + "/" + bundleInfo->bundleName
511 + templateItem->sandboxPath;
512
513 ret = AddDataGroupItemToQueue(content, srcPath, sandboxPath, dataGroupUuid);
514 if (ret != 0) {
515 APPSPAWN_LOGE("Add datagroup item to dataGroupCtxQueue failed, el%{public}d", elxValue);
516 OH_ListRemoveAll(&content->dataGroupCtxQueue, nullptr);
517 return -1;
518 }
519 }
520
521 DumpDataGroupCtxQueue(&content->dataGroupCtxQueue);
522 return ret;
523 }
524
UpdateDataGroupDirs(AppSpawnMgr * content)525 int UpdateDataGroupDirs(AppSpawnMgr *content)
526 {
527 if (content == nullptr) {
528 return APPSPAWN_ARG_INVALID;
529 }
530
531 ListNode *node = content->dataGroupCtxQueue.next;
532 while (node != &content->dataGroupCtxQueue) {
533 DataGroupCtx *dataGroupNode = (DataGroupCtx *)ListEntry(node, DataGroupCtx, node);
534 char sandboxPath[PATH_MAX_LEN] = {0};
535 int ret = snprintf_s(sandboxPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s%s", dataGroupNode->destPath.path,
536 dataGroupNode->dataGroupUuid);
537 if (ret <= 0) {
538 APPSPAWN_LOGE("snprintf_s sandboxPath: %{public}s failed, errno %{public}d",
539 dataGroupNode->destPath.path, errno);
540 return APPSPAWN_ERROR_UTILS_MEM_FAIL;
541 }
542
543 SharedMountArgs args = {
544 .srcPath = dataGroupNode->srcPath.path,
545 .destPath = sandboxPath,
546 .fsType = nullptr,
547 .mountFlags = MS_BIND | MS_REC,
548 .options = nullptr,
549 .mountSharedFlag = MS_SHARED
550 };
551 ret = DoSharedMount(&args);
552 if (ret != 0) {
553 APPSPAWN_LOGE("Shared mount %{public}s to %{public}s failed, errno %{public}d", args.srcPath,
554 sandboxPath, ret);
555 }
556 node = node->next;
557 }
558 OH_ListRemoveAll(&content->dataGroupCtxQueue, NULL);
559 return 0;
560 }
561
MountDirToShared(AppSpawnMgr * content,const AppSpawningCtx * property)562 static void MountDirToShared(AppSpawnMgr *content, const AppSpawningCtx *property)
563 {
564 if (property == nullptr) {
565 return;
566 }
567
568 AppDacInfo *info = reinterpret_cast<AppDacInfo *>(GetAppProperty(property, TLV_DAC_INFO));
569 AppSpawnMsgBundleInfo *bundleInfo =
570 reinterpret_cast<AppSpawnMsgBundleInfo *>(GetAppProperty(property, TLV_BUNDLE_INFO));
571 if (info == NULL || bundleInfo == NULL) {
572 return;
573 }
574
575 MountEl1Bundle(property, info, bundleInfo->bundleName);
576
577 if (IsUnlockStatus(info->uid)) {
578 return;
579 }
580
581 MountSharedMap(property, info, bundleInfo->bundleName);
582 MountStorageUsers(property, info, bundleInfo->bundleName);
583 ParseDataGroupList(content, property, info, bundleInfo);
584
585 std::string lockSbxPathStamp = "/mnt/sandbox/" + std::to_string(info->uid / UID_BASE) + "/";
586 lockSbxPathStamp += CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : "";
587 lockSbxPathStamp += bundleInfo->bundleName;
588 lockSbxPathStamp += "_locked";
589 int ret = MakeDirRec(lockSbxPathStamp.c_str(), DIR_MODE, 1);
590 if (ret != 0) {
591 APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", lockSbxPathStamp.c_str(), errno);
592 }
593 }
594 #endif
595
MountToShared(AppSpawnMgr * content,const AppSpawningCtx * property)596 int MountToShared(AppSpawnMgr *content, const AppSpawningCtx *property)
597 {
598 #ifndef APPSPAWN_SANDBOX_NEW
599 // mount dynamic directory to shared
600 MountDirToShared(content, property);
601 #endif
602 return 0;
603 }
604
MODULE_CONSTRUCTOR(void)605 MODULE_CONSTRUCTOR(void)
606 {
607 #ifndef APPSPAWN_SANDBOX_NEW
608 (void)AddServerStageHook(STAGE_SERVER_LOCK, HOOK_PRIO_COMMON, UpdateDataGroupDirs);
609 #endif
610 }
611