• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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