• 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 "appspawn_msg.h"
22 #include "appspawn_sandbox.h"
23 #include "appspawn_utils.h"
24 #include "json_utils.h"
25 #include "securec.h"
26 
27 #define SANDBOX_GROUP_PATH "/data/storage/el2/group/"
28 #define SANDBOX_INSTALL_PATH "/data/storage/el1/bundle/"
29 #define SANDBOX_OVERLAY_PATH "/data/storage/overlay/"
30 
CheckPath(const char * name)31 static inline bool CheckPath(const char *name)
32 {
33     return name != NULL && strcmp(name, ".") != 0 && strcmp(name, "..") != 0 && strstr(name, "/") == NULL;
34 }
35 
MountAllHsp(const SandboxContext * context,const cJSON * hsps)36 APPSPAWN_STATIC int MountAllHsp(const SandboxContext *context, const cJSON *hsps)
37 {
38     APPSPAWN_CHECK(context != NULL && hsps != NULL, return -1, "Invalid context or hsps");
39 
40     int ret = 0;
41     cJSON *bundles = cJSON_GetObjectItemCaseSensitive(hsps, "bundles");
42     cJSON *modules = cJSON_GetObjectItemCaseSensitive(hsps, "modules");
43     cJSON *versions = cJSON_GetObjectItemCaseSensitive(hsps, "versions");
44     APPSPAWN_CHECK(bundles != NULL && cJSON_IsArray(bundles), return -1, "MountAllHsp: invalid bundles");
45     APPSPAWN_CHECK(modules != NULL && cJSON_IsArray(modules), return -1, "MountAllHsp: invalid modules");
46     APPSPAWN_CHECK(versions != NULL && cJSON_IsArray(versions), return -1, "MountAllHsp: invalid versions");
47     int count = cJSON_GetArraySize(bundles);
48     APPSPAWN_CHECK(count == cJSON_GetArraySize(modules), return -1, "MountAllHsp: sizes are not same");
49     APPSPAWN_CHECK(count == cJSON_GetArraySize(versions), return -1, "MountAllHsp: sizes are not same");
50 
51     APPSPAWN_LOGI("MountAllHsp app: %{public}s, count: %{public}d", context->bundleName, count);
52     for (int i = 0; i < count; i++) {
53         char *libBundleName = cJSON_GetStringValue(cJSON_GetArrayItem(bundles, i));
54         char *libModuleName = cJSON_GetStringValue(cJSON_GetArrayItem(modules, i));
55         char *libVersion = cJSON_GetStringValue(cJSON_GetArrayItem(versions, i));
56         APPSPAWN_CHECK(CheckPath(libBundleName) && CheckPath(libModuleName) && CheckPath(libVersion),
57             return -1, "MountAllHsp: path error");
58 
59         // src path
60         int len = sprintf_s(context->buffer[0].buffer, context->buffer[0].bufferLen, "%s%s/%s/%s",
61             PHYSICAL_APP_INSTALL_PATH, libBundleName, libVersion, libModuleName);
62         APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
63         // sandbox path
64         len = sprintf_s(context->buffer[1].buffer, context->buffer[1].bufferLen, "%s%s%s/%s",
65             context->rootPath, SANDBOX_INSTALL_PATH, libBundleName, libModuleName);
66         APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
67 
68         CreateSandboxDir(context->buffer[1].buffer, FILE_MODE);
69         MountArg mountArg = {
70             context->buffer[0].buffer, context->buffer[1].buffer, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE
71         };
72         ret = SandboxMountPath(&mountArg);
73         APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
74     }
75     return ret;
76 }
77 
GetLastPath(const char * libPhysicalPath)78 static inline char *GetLastPath(const char *libPhysicalPath)
79 {
80     char *tmp = GetLastStr(libPhysicalPath, "/");
81     return tmp + 1;
82 }
83 
MountAllGroup(const SandboxContext * context,const cJSON * groups)84 APPSPAWN_STATIC int MountAllGroup(const SandboxContext *context, const cJSON *groups)
85 {
86     APPSPAWN_CHECK(context != NULL && groups != NULL, return -1, "Invalid context or group");
87     mode_t mountFlags = MS_REC | MS_BIND;
88     mode_t mountSharedFlag = MS_SLAVE;
89     if (CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_ISOLATED_SANDBOX)) {
90         APPSPAWN_LOGV("MountAllGroup falsg is isolated");
91         mountSharedFlag |= MS_REMOUNT | MS_NODEV | MS_RDONLY | MS_BIND;
92     }
93     int ret = 0;
94     cJSON *dataGroupIds = cJSON_GetObjectItemCaseSensitive(groups, "dataGroupId");
95     cJSON *gids = cJSON_GetObjectItemCaseSensitive(groups, "gid");
96     cJSON *dirs = cJSON_GetObjectItemCaseSensitive(groups, "dir");
97     APPSPAWN_CHECK(dataGroupIds != NULL && cJSON_IsArray(dataGroupIds),
98         return -1, "MountAllGroup: invalid dataGroupIds");
99     APPSPAWN_CHECK(gids != NULL && cJSON_IsArray(gids), return -1, "MountAllGroup: invalid gids");
100     APPSPAWN_CHECK(dirs != NULL && cJSON_IsArray(dirs), return -1, "MountAllGroup: invalid dirs");
101     int count = cJSON_GetArraySize(dataGroupIds);
102     APPSPAWN_CHECK(count == cJSON_GetArraySize(gids), return -1, "MountAllGroup: sizes are not same");
103     APPSPAWN_CHECK(count == cJSON_GetArraySize(dirs), return -1, "MountAllGroup: sizes are not same");
104 
105     APPSPAWN_LOGI("MountAllGroup: app: %{public}s, count: %{public}d", context->bundleName, count);
106     for (int i = 0; i < count; i++) {
107         cJSON *dirJson = cJSON_GetArrayItem(dirs, i);
108         APPSPAWN_CHECK(dirJson != NULL && cJSON_IsString(dirJson), return -1, "MountAllGroup: invalid dirJson");
109         const char *libPhysicalPath = cJSON_GetStringValue(dirJson);
110         APPSPAWN_CHECK(!CheckPath(libPhysicalPath), return -1, "MountAllGroup: path error");
111 
112         char *dataGroupUuid = GetLastPath(libPhysicalPath);
113         int len = sprintf_s(context->buffer[0].buffer, context->buffer[0].bufferLen, "%s%s%s",
114             context->rootPath, SANDBOX_GROUP_PATH, dataGroupUuid);
115         APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
116         APPSPAWN_LOGV("MountAllGroup src: '%{public}s' =>'%{public}s'", libPhysicalPath, context->buffer[0].buffer);
117 
118         CreateSandboxDir(context->buffer[0].buffer, FILE_MODE);
119         MountArg mountArg = {libPhysicalPath, context->buffer[0].buffer, NULL, mountFlags, NULL, mountSharedFlag};
120         ret = SandboxMountPath(&mountArg);
121         APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
122     }
123     return ret;
124 }
125 
126 typedef struct {
127     const SandboxContext *sandboxContext;
128     uint32_t srcSetLen;
129     char *mountedSrcSet;
130 } OverlayContext;
131 
SetOverlayAppPath(const char * hapPath,void * context)132 static int SetOverlayAppPath(const char *hapPath, void *context)
133 {
134     APPSPAWN_LOGV("SetOverlayAppPath '%{public}s'", hapPath);
135     OverlayContext *overlayContext = (OverlayContext *)context;
136     const SandboxContext *sandboxContext = overlayContext->sandboxContext;
137 
138     // src path
139     char *tmp = GetLastStr(hapPath, "/");
140     if (tmp == NULL) {
141         return 0;
142     }
143     int ret = strncpy_s(sandboxContext->buffer[0].buffer,
144         sandboxContext->buffer[0].bufferLen, hapPath, tmp - (char *)hapPath);
145     APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
146 
147     if (strstr(overlayContext->mountedSrcSet, sandboxContext->buffer[0].buffer) != NULL) {
148         APPSPAWN_LOGV("%{public}s have mounted before, no need to mount twice.", sandboxContext->buffer[0].buffer);
149         return 0;
150     }
151     ret = strcat_s(overlayContext->mountedSrcSet, overlayContext->srcSetLen, "|");
152     APPSPAWN_CHECK(ret == 0, return ret, "Fail to add src path to set %{public}s", "|");
153     ret = strcat_s(overlayContext->mountedSrcSet, overlayContext->srcSetLen, sandboxContext->buffer[0].buffer);
154     APPSPAWN_CHECK(ret == 0, return ret, "Fail to add src path to set %{public}s", sandboxContext->buffer[0].buffer);
155 
156     // sandbox path
157     tmp = GetLastStr(sandboxContext->buffer[0].buffer, "/");
158     if (tmp == NULL) {
159         return 0;
160     }
161     int len = sprintf_s(sandboxContext->buffer[1].buffer, sandboxContext->buffer[1].bufferLen, "%s%s",
162         sandboxContext->rootPath, SANDBOX_OVERLAY_PATH);
163     APPSPAWN_CHECK(len > 0, return -1, "Failed to format install path");
164     ret = strcat_s(sandboxContext->buffer[1].buffer, sandboxContext->buffer[1].bufferLen - len, tmp + 1);
165     APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
166     APPSPAWN_LOGV("SetOverlayAppPath path: '%{public}s' => '%{public}s'",
167         sandboxContext->buffer[0].buffer, sandboxContext->buffer[1].buffer);
168 
169     ret = MakeDirRec(sandboxContext->buffer[1].buffer, FILE_MODE, 1);
170     APPSPAWN_CHECK(ret == 0, return ret, "Fail to mkdir dir %{public}s, ret: %{public}d",
171                    sandboxContext->buffer[1].buffer, ret);
172     MountArg mountArg = {
173         sandboxContext->buffer[0].buffer, sandboxContext->buffer[1].buffer, NULL, MS_REC | MS_BIND, NULL, MS_SHARED
174     };
175     int retMount = SandboxMountPath(&mountArg);
176     if (retMount != 0) {
177         APPSPAWN_LOGE("Fail to mount overlay path, src is %{public}s.", hapPath);
178         ret = retMount;
179     }
180     return ret;
181 }
182 
SetOverlayAppSandboxConfig(const SandboxContext * context,const char * overlayInfo)183 static int SetOverlayAppSandboxConfig(const SandboxContext *context, const char *overlayInfo)
184 {
185     APPSPAWN_CHECK(context != NULL && overlayInfo != NULL, return -1, "Invalid context or overlayInfo");
186     OverlayContext overlayContext;
187     overlayContext.sandboxContext = context;
188     overlayContext.srcSetLen = strlen(overlayInfo);
189     overlayContext.mountedSrcSet = (char *)calloc(1, overlayContext.srcSetLen + 1);
190     APPSPAWN_CHECK(overlayContext.mountedSrcSet != NULL, return -1, "Failed to create mountedSrcSet");
191     *(overlayContext.mountedSrcSet + overlayContext.srcSetLen) = '\0';
192     int ret = StringSplit(overlayInfo, "|", (void *)&overlayContext, SetOverlayAppPath);
193     APPSPAWN_LOGV("overlayContext->mountedSrcSet: '%{public}s'", overlayContext.mountedSrcSet);
194     free(overlayContext.mountedSrcSet);
195     return ret;
196 }
197 
GetJsonObjFromProperty(const SandboxContext * context,const char * name)198 static inline cJSON *GetJsonObjFromProperty(const SandboxContext *context, const char *name)
199 {
200     uint32_t size = 0;
201     char *extInfo = (char *)(GetAppSpawnMsgExtInfo(context->message, name, &size));
202     if (size == 0 || extInfo == NULL) {
203         return NULL;
204     }
205     APPSPAWN_LOGV("Get json name %{public}s value %{public}s", name, extInfo);
206     cJSON *root = cJSON_Parse(extInfo);
207     APPSPAWN_CHECK(root != NULL, return NULL, "Invalid ext info %{public}s for %{public}s", extInfo, name);
208     return root;
209 }
210 
ProcessHSPListConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandBox,const char * name)211 static int ProcessHSPListConfig(const SandboxContext *context, const AppSpawnSandboxCfg *appSandBox, const char *name)
212 {
213     cJSON *root = GetJsonObjFromProperty(context, name);
214     APPSPAWN_CHECK_ONLY_EXPER(root != NULL, return 0);
215     int ret = MountAllHsp(context, root);
216     cJSON_Delete(root);
217     return ret;
218 }
219 
ProcessDataGroupConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandBox,const char * name)220 static int ProcessDataGroupConfig(const SandboxContext *context, const AppSpawnSandboxCfg *appSandBox, const char *name)
221 {
222     cJSON *root = GetJsonObjFromProperty(context, name);
223     APPSPAWN_CHECK_ONLY_EXPER(root != NULL, return 0);
224     int ret = MountAllGroup(context, root);
225     cJSON_Delete(root);
226     return ret;
227 }
228 
ProcessOverlayAppConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandBox,const char * name)229 static int ProcessOverlayAppConfig(const SandboxContext *context,
230     const AppSpawnSandboxCfg *appSandBox, const char *name)
231 {
232     uint32_t size = 0;
233     char *extInfo = (char *)GetAppSpawnMsgExtInfo(context->message, name, &size);
234     if (size == 0 || extInfo == NULL) {
235         return 0;
236     }
237     APPSPAWN_LOGV("ProcessOverlayAppConfig name %{public}s value %{public}s", name, extInfo);
238     return SetOverlayAppSandboxConfig(context, extInfo);
239 }
240 
241 struct ListNode g_sandboxExpandCfgList = {&g_sandboxExpandCfgList, &g_sandboxExpandCfgList};
AppSandboxExpandAppCfgCompareName(ListNode * node,void * data)242 static int AppSandboxExpandAppCfgCompareName(ListNode *node, void *data)
243 {
244     AppSandboxExpandAppCfgNode *varNode = ListEntry(node, AppSandboxExpandAppCfgNode, node);
245     return strncmp((char *)data, varNode->name, strlen(varNode->name));
246 }
247 
AppSandboxExpandAppCfgComparePrio(ListNode * node1,ListNode * node2)248 static int AppSandboxExpandAppCfgComparePrio(ListNode *node1, ListNode *node2)
249 {
250     AppSandboxExpandAppCfgNode *varNode1 = ListEntry(node1, AppSandboxExpandAppCfgNode, node);
251     AppSandboxExpandAppCfgNode *varNode2 = ListEntry(node2, AppSandboxExpandAppCfgNode, node);
252     return varNode1->prio - varNode2->prio;
253 }
254 
GetAppSandboxExpandAppCfg(const char * name)255 static const AppSandboxExpandAppCfgNode *GetAppSandboxExpandAppCfg(const char *name)
256 {
257     ListNode *node = OH_ListFind(&g_sandboxExpandCfgList, (void *)name, AppSandboxExpandAppCfgCompareName);
258     if (node == NULL) {
259         return NULL;
260     }
261     return ListEntry(node, AppSandboxExpandAppCfgNode, node);
262 }
263 
RegisterExpandSandboxCfgHandler(const char * name,int prio,ProcessExpandSandboxCfg handleExpandCfg)264 int RegisterExpandSandboxCfgHandler(const char *name, int prio, ProcessExpandSandboxCfg handleExpandCfg)
265 {
266     APPSPAWN_CHECK_ONLY_EXPER(name != NULL && handleExpandCfg != NULL, return APPSPAWN_ARG_INVALID);
267     if (GetAppSandboxExpandAppCfg(name) != NULL) {
268         return APPSPAWN_NODE_EXIST;
269     }
270 
271     size_t len = APPSPAWN_ALIGN(strlen(name) + 1);
272     AppSandboxExpandAppCfgNode *node = (AppSandboxExpandAppCfgNode *)(malloc(sizeof(AppSandboxExpandAppCfgNode) + len));
273     APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create sandbox");
274     // ext data init
275     OH_ListInit(&node->node);
276     node->cfgHandle = handleExpandCfg;
277     node->prio = prio;
278     int ret = strcpy_s(node->name, len, name);
279     APPSPAWN_CHECK(ret == 0, free(node);
280         return -1, "Failed to copy name %{public}s", name);
281     OH_ListAddWithOrder(&g_sandboxExpandCfgList, &node->node, AppSandboxExpandAppCfgComparePrio);
282     return 0;
283 }
284 
ProcessExpandAppSandboxConfig(const SandboxContext * context,const AppSpawnSandboxCfg * appSandBox,const char * name)285 int ProcessExpandAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *appSandBox, const char *name)
286 {
287     APPSPAWN_CHECK_ONLY_EXPER(context != NULL && appSandBox != NULL, return APPSPAWN_ARG_INVALID);
288     APPSPAWN_CHECK_ONLY_EXPER(name != NULL, return APPSPAWN_ARG_INVALID);
289     APPSPAWN_LOGV("ProcessExpandAppSandboxConfig %{public}s.", name);
290     const AppSandboxExpandAppCfgNode *node = GetAppSandboxExpandAppCfg(name);
291     if (node != NULL && node->cfgHandle != NULL) {
292         return node->cfgHandle(context, appSandBox, name);
293     }
294     return 0;
295 }
296 
AddDefaultExpandAppSandboxConfigHandle(void)297 void AddDefaultExpandAppSandboxConfigHandle(void)
298 {
299     RegisterExpandSandboxCfgHandler("HspList", 0, ProcessHSPListConfig);
300     RegisterExpandSandboxCfgHandler("DataGroup", 1, ProcessDataGroupConfig);
301     RegisterExpandSandboxCfgHandler("Overlay", 2, ProcessOverlayAppConfig);  // 2 priority
302 }
303 
ClearExpandAppSandboxConfigHandle(void)304 void ClearExpandAppSandboxConfigHandle(void)
305 {
306     OH_ListRemoveAll(&g_sandboxExpandCfgList, NULL);
307 }
308