• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <sys/mount.h>
17 #include <sys/stat.h>
18 #include <sys/syscall.h>
19 #include <sys/types.h>
20 
21 #include "securec.h"
22 #include "appspawn_msg.h"
23 #include "appspawn_sandbox.h"
24 #include "appspawn_utils.h"
25 #include "json_utils.h"
26 #include "appspawn_permission.h"
27 #include "sandbox_shared.h"
28 
29 #define SANDBOX_INSTALL_PATH "/data/storage/el1/bundle/"
30 #define SANDBOX_OVERLAY_PATH "/data/storage/overlay/"
31 
MountAllHsp(const SandboxContext * context,const cJSON * hsps)32 APPSPAWN_STATIC int MountAllHsp(const SandboxContext *context, const cJSON *hsps)
33 {
34     APPSPAWN_CHECK(context != NULL && hsps != NULL, return -1, "Invalid context or hsps");
35 
36     int ret = 0;
37     cJSON *bundles = cJSON_GetObjectItemCaseSensitive(hsps, "bundles");
38     cJSON *modules = cJSON_GetObjectItemCaseSensitive(hsps, "modules");
39     cJSON *versions = cJSON_GetObjectItemCaseSensitive(hsps, "versions");
40     APPSPAWN_CHECK(bundles != NULL && cJSON_IsArray(bundles), return -1, "MountAllHsp: invalid bundles");
41     APPSPAWN_CHECK(modules != NULL && cJSON_IsArray(modules), return -1, "MountAllHsp: invalid modules");
42     APPSPAWN_CHECK(versions != NULL && cJSON_IsArray(versions), return -1, "MountAllHsp: invalid versions");
43     int count = cJSON_GetArraySize(bundles);
44     APPSPAWN_CHECK(count == cJSON_GetArraySize(modules), return -1, "MountAllHsp: sizes are not same");
45     APPSPAWN_CHECK(count == cJSON_GetArraySize(versions), return -1, "MountAllHsp: sizes are not same");
46 
47     APPSPAWN_LOGI("MountAllHsp app: %{public}s, count: %{public}d", context->bundleName, count);
48     for (int i = 0; i < count; i++) {
49         char *libBundleName = cJSON_GetStringValue(cJSON_GetArrayItem(bundles, i));
50         char *libModuleName = cJSON_GetStringValue(cJSON_GetArrayItem(modules, i));
51         char *libVersion = cJSON_GetStringValue(cJSON_GetArrayItem(versions, i));
52         APPSPAWN_CHECK(CheckPath(libBundleName) && CheckPath(libModuleName) && CheckPath(libVersion),
53             return -1, "MountAllHsp: path error");
54 
55         // src path
56         int len = sprintf_s(context->buffer[0].buffer, context->buffer[0].bufferLen, "%s%s/%s/%s",
57             PHYSICAL_APP_INSTALL_PATH, libBundleName, libVersion, libModuleName);
58         APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
59         // sandbox path
60         len = sprintf_s(context->buffer[1].buffer, context->buffer[1].bufferLen, "%s%s%s/%s",
61             context->rootPath, SANDBOX_INSTALL_PATH, libBundleName, libModuleName);
62         APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
63 
64         CreateSandboxDir(context->buffer[1].buffer, FILE_MODE);
65         MountArg mountArg = {
66             context->buffer[0].buffer, context->buffer[1].buffer, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE
67         };
68         ret = SandboxMountPath(&mountArg);
69         APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
70     }
71     return ret;
72 }
73 
MountAllGroup(const SandboxContext * context,const AppSpawnSandboxCfg * appSandbox,const cJSON * groups)74 APPSPAWN_STATIC int MountAllGroup(const SandboxContext *context, const AppSpawnSandboxCfg *appSandbox,
75                                   const cJSON *groups)
76 {
77     APPSPAWN_CHECK(context != NULL && groups != NULL && appSandbox != NULL, return APPSPAWN_SANDBOX_INVALID,
78                    "Invalid context or group");
79     mode_t mountFlags = MS_REC | MS_BIND;
80     mode_t mountSharedFlag = MS_SLAVE;
81     if (CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_ISOLATED_SANDBOX)) {
82         APPSPAWN_LOGV("Data group flags is isolated");
83         mountSharedFlag |= MS_REMOUNT | MS_NODEV | MS_RDONLY | MS_BIND;
84     }
85 
86     int ret = 0;
87     // Iterate through the array (assuming groups is an array)
88     cJSON *item = NULL;
89     cJSON_ArrayForEach(item, groups) {
90         // Check if the item is valid
91         APPSPAWN_CHECK(IsValidDataGroupItem(item), return APPSPAWN_ARG_INVALID,
92                        "Element is not a valid data group item");
93 
94         cJSON *dirItem = cJSON_GetObjectItemCaseSensitive(item, "dir");
95         cJSON *uuidItem = cJSON_GetObjectItemCaseSensitive(item, "uuid");
96         if (dirItem == NULL || !cJSON_IsString(dirItem) || uuidItem == NULL || !cJSON_IsString(uuidItem)) {
97             APPSPAWN_LOGE("Data group element is invalid");
98             return APPSPAWN_ARG_INVALID;
99         }
100 
101         const char *srcPath = dirItem->valuestring;
102         APPSPAWN_CHECK(!CheckPath(srcPath), return APPSPAWN_ARG_INVALID, "src path %{public}s is invalid", srcPath);
103 
104         int elxValue = GetElxInfoFromDir(srcPath);
105         APPSPAWN_CHECK((elxValue >= EL2 && elxValue < ELX_MAX), return APPSPAWN_ARG_INVALID, "Get elx value failed");
106 
107         const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(elxValue);
108         APPSPAWN_CHECK(templateItem != NULL, return APPSPAWN_ARG_INVALID, "Get data group arg template failed");
109 
110         // If permission isn't null, need check permission flag
111         if (templateItem->permission != NULL) {
112             int index = GetPermissionIndexInQueue(&appSandbox->permissionQueue, templateItem->permission);
113             APPSPAWN_LOGV("mount dir no lock mount permission flag %{public}d", index);
114             if (!CheckSandboxCtxPermissionFlagSet(context, (uint32_t)index)) {
115                 continue;
116             }
117         }
118         (void)memset_s(context->buffer[0].buffer, context->buffer[0].bufferLen, 0, context->buffer[0].bufferLen);
119         int len = snprintf_s(context->buffer[0].buffer, context->buffer[0].bufferLen, context->buffer[0].bufferLen - 1,
120                              "%s%s%s", context->rootPath, templateItem->sandboxPath, uuidItem->valuestring);
121         APPSPAWN_CHECK(len > 0, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "Get data group arg template failed");
122         ret = CreateSandboxDir(context->buffer[0].buffer, FILE_MODE);
123         APPSPAWN_CHECK(ret == 0, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "Mkdir sandbox dir failed");
124         MountArg mountArg = {srcPath, context->buffer[0].buffer, NULL, mountFlags, NULL, mountSharedFlag};
125         ret = SandboxMountPath(&mountArg);
126         APPSPAWN_CHECK_ONLY_LOG(ret == 0, "mount datagroup failed");
127     }
128     return 0;
129 }
130 
131 typedef struct {
132     const SandboxContext *sandboxContext;
133     uint32_t srcSetLen;
134     char *mountedSrcSet;
135 } OverlayContext;
136 
SetOverlayAppPath(const char * hapPath,void * context)137 static int SetOverlayAppPath(const char *hapPath, void *context)
138 {
139     APPSPAWN_LOGV("SetOverlayAppPath '%{public}s'", hapPath);
140     OverlayContext *overlayContext = (OverlayContext *)context;
141     const SandboxContext *sandboxContext = overlayContext->sandboxContext;
142 
143     // src path
144     char *tmp = GetLastStr(hapPath, "/");
145     if (tmp == NULL) {
146         return 0;
147     }
148     int ret = strncpy_s(sandboxContext->buffer[0].buffer,
149         sandboxContext->buffer[0].bufferLen, hapPath, tmp - (char *)hapPath);
150     APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
151 
152     if (strstr(overlayContext->mountedSrcSet, sandboxContext->buffer[0].buffer) != NULL) {
153         APPSPAWN_LOGV("%{public}s have mounted before, no need to mount twice.", sandboxContext->buffer[0].buffer);
154         return 0;
155     }
156     ret = strcat_s(overlayContext->mountedSrcSet, overlayContext->srcSetLen, "|");
157     APPSPAWN_CHECK(ret == 0, return ret, "Fail to add src path to set %{public}s", "|");
158     ret = strcat_s(overlayContext->mountedSrcSet, overlayContext->srcSetLen, sandboxContext->buffer[0].buffer);
159     APPSPAWN_CHECK(ret == 0, return ret, "Fail to add src path to set %{public}s", sandboxContext->buffer[0].buffer);
160 
161     // sandbox path
162     tmp = GetLastStr(sandboxContext->buffer[0].buffer, "/");
163     if (tmp == NULL) {
164         return 0;
165     }
166     int len = sprintf_s(sandboxContext->buffer[1].buffer, sandboxContext->buffer[1].bufferLen, "%s%s",
167         sandboxContext->rootPath, SANDBOX_OVERLAY_PATH);
168     APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
169     ret = strcat_s(sandboxContext->buffer[1].buffer, sandboxContext->buffer[1].bufferLen - len, tmp + 1);
170     APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
171     APPSPAWN_LOGV("SetOverlayAppPath path: '%{public}s' => '%{public}s'",
172         sandboxContext->buffer[0].buffer, sandboxContext->buffer[1].buffer);
173 
174     ret = MakeDirRec(sandboxContext->buffer[1].buffer, FILE_MODE, 1);
175     APPSPAWN_CHECK(ret == 0, return ret, "Fail to mkdir dir %{public}s, ret: %{public}d",
176                    sandboxContext->buffer[1].buffer, ret);
177     MountArg mountArg = {
178         sandboxContext->buffer[0].buffer, sandboxContext->buffer[1].buffer, NULL, MS_REC | MS_BIND, NULL, MS_SHARED
179     };
180     int retMount = SandboxMountPath(&mountArg);
181     if (retMount != 0) {
182         APPSPAWN_LOGE("Fail to mount overlay path, src is %{public}s.", hapPath);
183         ret = retMount;
184     }
185     return ret;
186 }
187 
SetOverlayAppSandboxConfig(const SandboxContext * context,const char * overlayInfo)188 static int SetOverlayAppSandboxConfig(const SandboxContext *context, const char *overlayInfo)
189 {
190     APPSPAWN_CHECK(context != NULL && overlayInfo != NULL, return -1, "Invalid context or overlayInfo");
191     OverlayContext overlayContext;
192     overlayContext.sandboxContext = context;
193     overlayContext.srcSetLen = strlen(overlayInfo);
194     overlayContext.mountedSrcSet = (char *)calloc(1, overlayContext.srcSetLen + 1);
195     APPSPAWN_CHECK(overlayContext.mountedSrcSet != NULL, return -1, "Failed to create mountedSrcSet");
196     *(overlayContext.mountedSrcSet + overlayContext.srcSetLen) = '\0';
197     int ret = StringSplit(overlayInfo, "|", (void *)&overlayContext, SetOverlayAppPath);
198     APPSPAWN_LOGV("overlayContext->mountedSrcSet: '%{public}s'", overlayContext.mountedSrcSet);
199     free(overlayContext.mountedSrcSet);
200     overlayContext.mountedSrcSet = NULL;
201     return ret;
202 }
203 
GetJsonObjFromProperty(const SandboxContext * context,const char * name)204 static inline cJSON *GetJsonObjFromProperty(const SandboxContext *context, const char *name)
205 {
206     uint32_t size = 0;
207     char *extInfo = (char *)(GetAppSpawnMsgExtInfo(context->message, name, &size));
208     if (size == 0 || extInfo == NULL) {
209         return NULL;
210     }
211     APPSPAWN_LOGV("Get json name %{public}s value %{public}s", name, extInfo);
212     cJSON *root = cJSON_Parse(extInfo);
213     APPSPAWN_CHECK(root != NULL, return NULL, "Invalid ext info %{public}s for %{public}s", extInfo, name);
214     return root;
215 }
216 
ProcessHSPListConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandbox,const char * name)217 static int ProcessHSPListConfig(const SandboxContext *context, const AppSpawnSandboxCfg *appSandbox, const char *name)
218 {
219     cJSON *root = GetJsonObjFromProperty(context, name);
220     APPSPAWN_CHECK_ONLY_EXPER(root != NULL, return 0);
221     int ret = MountAllHsp(context, root);
222     cJSON_Delete(root);
223     return ret;
224 }
225 
ProcessDataGroupConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandbox,const char * name)226 static int ProcessDataGroupConfig(const SandboxContext *context, const AppSpawnSandboxCfg *appSandbox, const char *name)
227 {
228     cJSON *root = GetJsonObjFromProperty(context, name);
229     APPSPAWN_CHECK_ONLY_EXPER(root != NULL, return 0);
230     int ret = MountAllGroup(context, appSandbox, root);
231     cJSON_Delete(root);
232     return ret;
233 }
234 
ProcessOverlayAppConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandbox,const char * name)235 static int ProcessOverlayAppConfig(const SandboxContext *context,
236     const AppSpawnSandboxCfg *appSandbox, const char *name)
237 {
238     uint32_t size = 0;
239     char *extInfo = (char *)GetAppSpawnMsgExtInfo(context->message, name, &size);
240     if (size == 0 || extInfo == NULL) {
241         return 0;
242     }
243     APPSPAWN_LOGV("ProcessOverlayAppConfig name %{public}s value %{public}s", name, extInfo);
244     return SetOverlayAppSandboxConfig(context, extInfo);
245 }
246 
247 struct ListNode g_sandboxExpandCfgList = {&g_sandboxExpandCfgList, &g_sandboxExpandCfgList};
AppSandboxExpandAppCfgCompareName(ListNode * node,void * data)248 static int AppSandboxExpandAppCfgCompareName(ListNode *node, void *data)
249 {
250     AppSandboxExpandAppCfgNode *varNode = ListEntry(node, AppSandboxExpandAppCfgNode, node);
251     return strncmp((char *)data, varNode->name, strlen(varNode->name));
252 }
253 
AppSandboxExpandAppCfgComparePrio(ListNode * node1,ListNode * node2)254 static int AppSandboxExpandAppCfgComparePrio(ListNode *node1, ListNode *node2)
255 {
256     AppSandboxExpandAppCfgNode *varNode1 = ListEntry(node1, AppSandboxExpandAppCfgNode, node);
257     AppSandboxExpandAppCfgNode *varNode2 = ListEntry(node2, AppSandboxExpandAppCfgNode, node);
258     return varNode1->prio - varNode2->prio;
259 }
260 
GetAppSandboxExpandAppCfg(const char * name)261 static const AppSandboxExpandAppCfgNode *GetAppSandboxExpandAppCfg(const char *name)
262 {
263     ListNode *node = OH_ListFind(&g_sandboxExpandCfgList, (void *)name, AppSandboxExpandAppCfgCompareName);
264     if (node == NULL) {
265         return NULL;
266     }
267     return ListEntry(node, AppSandboxExpandAppCfgNode, node);
268 }
269 
RegisterExpandSandboxCfgHandler(const char * name,int prio,ProcessExpandSandboxCfg handleExpandCfg)270 int RegisterExpandSandboxCfgHandler(const char *name, int prio, ProcessExpandSandboxCfg handleExpandCfg)
271 {
272     APPSPAWN_CHECK_ONLY_EXPER(name != NULL && handleExpandCfg != NULL, return APPSPAWN_ARG_INVALID);
273     if (GetAppSandboxExpandAppCfg(name) != NULL) {
274         return APPSPAWN_NODE_EXIST;
275     }
276 
277     size_t len = APPSPAWN_ALIGN(strlen(name) + 1);
278     AppSandboxExpandAppCfgNode *node = (AppSandboxExpandAppCfgNode *)(malloc(sizeof(AppSandboxExpandAppCfgNode) + len));
279     APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create sandbox");
280     // ext data init
281     OH_ListInit(&node->node);
282     node->cfgHandle = handleExpandCfg;
283     node->prio = prio;
284     int ret = strcpy_s(node->name, len, name);
285     APPSPAWN_CHECK(ret == 0, free(node);
286                              node = NULL;
287                              return -1, "Failed to copy name %{public}s", name);
288     OH_ListAddWithOrder(&g_sandboxExpandCfgList, &node->node, AppSandboxExpandAppCfgComparePrio);
289     return 0;
290 }
291 
ProcessExpandAppSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandbox,const char * name)292 int ProcessExpandAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *appSandbox, const char *name)
293 {
294     APPSPAWN_CHECK_ONLY_EXPER(context != NULL && appSandbox != NULL, return APPSPAWN_ARG_INVALID);
295     APPSPAWN_CHECK_ONLY_EXPER(name != NULL, return APPSPAWN_ARG_INVALID);
296     APPSPAWN_LOGV("ProcessExpandAppSandboxConfig %{public}s.", name);
297     const AppSandboxExpandAppCfgNode *node = GetAppSandboxExpandAppCfg(name);
298     if (node != NULL && node->cfgHandle != NULL) {
299         return node->cfgHandle(context, appSandbox, name);
300     }
301     return 0;
302 }
303 
AddDefaultExpandAppSandboxConfigHandle(void)304 void AddDefaultExpandAppSandboxConfigHandle(void)
305 {
306     RegisterExpandSandboxCfgHandler("HspList", 0, ProcessHSPListConfig);
307     RegisterExpandSandboxCfgHandler("DataGroup", 1, ProcessDataGroupConfig);
308     RegisterExpandSandboxCfgHandler("Overlay", 2, ProcessOverlayAppConfig);  // 2 priority
309 }
310 
ClearExpandAppSandboxConfigHandle(void)311 void ClearExpandAppSandboxConfigHandle(void)
312 {
313     OH_ListRemoveAll(&g_sandboxExpandCfgList, NULL);
314 }
315