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_manager.h"
17 #include "appspawn_sandbox.h"
18 #include "appspawn_utils.h"
19 #include "modulemgr.h"
20 #include "parameter.h"
21 #include "securec.h"
22
23 struct ListNode g_sandboxVarList = {&g_sandboxVarList, &g_sandboxVarList};
24
VarPackageNameIndexReplace(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)25 static int VarPackageNameIndexReplace(const SandboxContext *context,
26 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
27 {
28 AppSpawnMsgBundleInfo *bundleInfo = (
29 AppSpawnMsgBundleInfo *)GetSpawningMsgInfo(context, TLV_BUNDLE_INFO);
30 APPSPAWN_CHECK(bundleInfo != NULL, return APPSPAWN_TLV_NONE,
31 "No bundle info in msg %{public}s", context->bundleName);
32 int len = 0;
33 if (bundleInfo->bundleIndex > 0) {
34 len = sprintf_s((char *)buffer, bufferLen, "%s_%d", bundleInfo->bundleName, bundleInfo->bundleIndex);
35 } else {
36 len = sprintf_s((char *)buffer, bufferLen, "%s", bundleInfo->bundleName);
37 }
38 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen),
39 return -1, "Failed to format path app: %{public}s", context->bundleName);
40 *realLen = (uint32_t)len;
41 return 0;
42 }
43
VarPackageNameReplace(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)44 static int VarPackageNameReplace(const SandboxContext *context,
45 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
46 {
47 int len = sprintf_s((char *)buffer, bufferLen, "%s", context->bundleName);
48 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen),
49 return -1, "Failed to format path app: %{public}s", context->bundleName);
50 *realLen = (uint32_t)len;
51 return 0;
52 }
53
VarCurrentUseIdReplace(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)54 static int VarCurrentUseIdReplace(const SandboxContext *context,
55 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
56 {
57 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
58 APPSPAWN_CHECK(info != NULL, return APPSPAWN_TLV_NONE,
59 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName);
60 int len = 0;
61 if (extraData == NULL || !CHECK_FLAGS_BY_INDEX(extraData->operation, SANDBOX_TAG_PERMISSION)) {
62 len = sprintf_s((char *)buffer, bufferLen, "%u", info->uid / UID_BASE);
63 } else if (context->appFullMountEnable && strlen(info->userName) > 0) {
64 len = sprintf_s((char *)buffer, bufferLen, "%s", "currentUser");
65 } else {
66 len = sprintf_s((char *)buffer, bufferLen, "%s", "currentUser");
67 }
68 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen),
69 return -1, "Failed to format path app: %{public}s", context->bundleName);
70 *realLen = (uint32_t)len;
71 return 0;
72 }
73
VarArkWebPackageNameReplace(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)74 static int VarArkWebPackageNameReplace(const SandboxContext *context,
75 const char *buffer, uint32_t bufferLen, uint32_t *realLen,
76 const VarExtraData *extraData)
77 {
78 static char arkWebPackageName[PARAM_BUFFER_SIZE] = {0};
79 if (strlen(arkWebPackageName) == 0) {
80 int len = GetParameter(ARK_WEB_PERSIST_PACKAGE_NAME, "",
81 arkWebPackageName, sizeof(arkWebPackageName));
82 APPSPAWN_CHECK(len > 0, return -1,
83 "Failed to get param for var %{public}s",
84 ARK_WEB_PERSIST_PACKAGE_NAME);
85 }
86 APPSPAWN_LOGV("ArkWebPackageNameReplace '%{public}s'", arkWebPackageName);
87
88 int len = sprintf_s((char*) buffer, bufferLen, "%s", arkWebPackageName);
89 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen), return -1,
90 "Failed to format path app: %{public}s", arkWebPackageName);
91 *realLen = (uint32_t) len;
92 return 0;
93 }
94
VariableNodeCompareName(ListNode * node,void * data)95 static int VariableNodeCompareName(ListNode *node, void *data)
96 {
97 AppSandboxVarNode *varNode = (AppSandboxVarNode *)ListEntry(node, AppSandboxVarNode, node);
98 return strcmp((char *)data, varNode->name);
99 }
100
GetAppSandboxVarNode(const char * name)101 static AppSandboxVarNode *GetAppSandboxVarNode(const char *name)
102 {
103 ListNode *node = OH_ListFind(&g_sandboxVarList, (void *)name, VariableNodeCompareName);
104 if (node == NULL) {
105 return NULL;
106 }
107 return (AppSandboxVarNode *)ListEntry(node, AppSandboxVarNode, node);
108 }
109
ReplaceVariableByParameter(const char * varData,SandboxBuffer * sandboxBuffer)110 static int ReplaceVariableByParameter(const char *varData, SandboxBuffer *sandboxBuffer)
111 {
112 // "<param:persist.nweb.sandbox.src_path>"
113 int len = GetParameter(varData + sizeof("<param:") - 1,
114 DEFAULT_NWEB_SANDBOX_SEC_PATH, sandboxBuffer->buffer + sandboxBuffer->current,
115 sandboxBuffer->bufferLen - sandboxBuffer->current - 1);
116 APPSPAWN_CHECK(len > 0, return -1, "Failed to get param for var %{public}s", varData);
117 sandboxBuffer->current += len;
118 return 0;
119 }
120
ReplaceVariableForDepSandboxPath(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)121 static int ReplaceVariableForDepSandboxPath(const SandboxContext *context,
122 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
123 {
124 APPSPAWN_CHECK(extraData != NULL && extraData->data.depNode != NULL, return -1, "Invalid extra data ");
125 uint32_t len = strlen(extraData->data.depNode->target);
126 int ret = memcpy_s((char *)buffer, bufferLen, extraData->data.depNode->target, len);
127 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data");
128 *realLen = len;
129 return 0;
130 }
131
ReplaceVariableForDepSrcPath(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)132 static int ReplaceVariableForDepSrcPath(const SandboxContext *context,
133 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
134 {
135 APPSPAWN_CHECK(extraData != NULL && extraData->data.depNode != NULL, return -1, "Invalid extra data ");
136 uint32_t len = strlen(extraData->data.depNode->source);
137 int ret = memcpy_s((char *)buffer, bufferLen, extraData->data.depNode->source, len);
138 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data");
139 *realLen = len;
140 return 0;
141 }
142
ReplaceVariableForDepPath(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)143 static int ReplaceVariableForDepPath(const SandboxContext *context,
144 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
145 {
146 APPSPAWN_CHECK(extraData != NULL && extraData->data.depNode != NULL, return -1, "Invalid extra data ");
147 char *path = extraData->data.depNode->source;
148 if (CHECK_FLAGS_BY_INDEX(extraData->operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX)) {
149 path = extraData->data.depNode->target;
150 } else if (CHECK_FLAGS_BY_INDEX(extraData->operation, MOUNT_PATH_OP_REPLACE_BY_SRC) && IsPathEmpty(path)) {
151 path = extraData->data.depNode->target;
152 }
153 APPSPAWN_CHECK(path != NULL, return -1, "Invalid path %{public}x ", extraData->operation);
154 uint32_t len = strlen(path);
155 int ret = memcpy_s((char *)buffer, bufferLen, path, len);
156 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data");
157 *realLen = len;
158 return 0;
159 }
160
ReplaceVariableForpackageName(const SandboxContext * context,const char * buffer,uint32_t bufferLen,uint32_t * realLen,const VarExtraData * extraData)161 static int ReplaceVariableForpackageName(const SandboxContext *context,
162 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData)
163 {
164 APPSPAWN_CHECK(context != NULL, return -1, "Invalid extra data ");
165 if (extraData != NULL && extraData->variablePackageName != NULL) {
166 int len = sprintf_s((char *)buffer, bufferLen, "%s", extraData->variablePackageName);
167 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen),
168 return -1, "Failed to format path app: %{public}s", context->bundleName);
169 *realLen = (uint32_t)len;
170 return 0;
171 }
172
173 AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetSpawningMsgInfo(context, TLV_BUNDLE_INFO);
174 APPSPAWN_CHECK(bundleInfo != NULL, return APPSPAWN_TLV_NONE,
175 "No bundle info in msg %{public}s", context->bundleName);
176 uint32_t flags = CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_CLONE_ENABLE) ? 1 : 0;
177 flags |= CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_EXTENSION_SANDBOX) ? 0x2 : 0;
178 char *extension = GetAppSpawnMsgExtInfo(context->message, MSG_EXT_NAME_APP_EXTENSION, NULL);
179 int32_t len = 0;
180 switch (flags) {
181 case 0: // default,
182 len = sprintf_s((char *)buffer, bufferLen, "%s", bundleInfo->bundleName);
183 break;
184 case 1: // 1 +clone-bundleIndex+packageName
185 len = sprintf_s((char *)buffer, bufferLen, "+clone-%u+%s", bundleInfo->bundleIndex, bundleInfo->bundleName);
186 break;
187 case 2: { // 2 +extension-<extensionType>+packageName
188 APPSPAWN_CHECK(extension != NULL, return -1, "Invalid extension data ");
189 len = sprintf_s((char *)buffer, bufferLen, "+extension-%s+%s", extension, bundleInfo->bundleName);
190 break;
191 }
192 case 3: { // 3 +clone-bundleIndex+extension-<extensionType>+packageName
193 APPSPAWN_CHECK(extension != NULL, return -1, "Invalid extension data ");
194 len = sprintf_s((char *)buffer, bufferLen, "+clone-%u+extension-%s+%s",
195 bundleInfo->bundleIndex, extension, bundleInfo->bundleName);
196 break;
197 }
198 default:
199 break;
200 }
201 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen),
202 return -1, "Failed to format path app: %{public}s flags %{public}u", context->bundleName, flags);
203 *realLen = (uint32_t)len;
204 return 0;
205 }
206
GetVariableName(char * varData,uint32_t len,const char * varStart,uint32_t * varLen)207 static int GetVariableName(char *varData, uint32_t len, const char *varStart, uint32_t *varLen)
208 {
209 uint32_t i = 0;
210 uint32_t sourceLen = strlen(varStart);
211 for (; i < sourceLen; i++) {
212 if (i > len) {
213 return -1;
214 }
215 varData[i] = *(varStart + i);
216 if (varData[i] == '>') {
217 break;
218 }
219 }
220 varData[i + 1] = '\0';
221 *varLen = i + 1;
222 return 0;
223 }
224
ReplaceVariable(const SandboxContext * context,const char * varStart,SandboxBuffer * sandboxBuffer,uint32_t * varLen,const VarExtraData * extraData)225 static int ReplaceVariable(const SandboxContext *context,
226 const char *varStart, SandboxBuffer *sandboxBuffer, uint32_t *varLen, const VarExtraData *extraData)
227 {
228 char varName[128] = {0}; // 128 max len for var
229 int ret = GetVariableName(varName, sizeof(varName), varStart, varLen);
230 APPSPAWN_CHECK(ret == 0, return -1, "Failed to get variable name");
231
232 uint32_t valueLen = 0;
233 AppSandboxVarNode *node = GetAppSandboxVarNode(varName);
234 if (node != NULL) {
235 ret = node->replaceVar(context, sandboxBuffer->buffer + sandboxBuffer->current,
236 sandboxBuffer->bufferLen - sandboxBuffer->current - 1, &valueLen, extraData);
237 APPSPAWN_CHECK(ret == 0 && valueLen < (sandboxBuffer->bufferLen - sandboxBuffer->current),
238 return -1, "Failed to fill real data");
239 sandboxBuffer->current += valueLen;
240 return 0;
241 }
242 // "<param:persist.nweb.sandbox.src_path>"
243 if (strncmp(varName, "<param:", sizeof("<param:") - 1) == 0) { // retry param:
244 varName[*varLen - 1] = '\0'; // erase last >
245 return ReplaceVariableByParameter(varName, sandboxBuffer);
246 }
247 if (strncmp(varName, "<lib>", sizeof("<lib>") - 1) == 0) { // retry lib
248 ret = memcpy_s(sandboxBuffer->buffer + sandboxBuffer->current,
249 sandboxBuffer->bufferLen - sandboxBuffer->current, APPSPAWN_LIB_NAME, strlen(APPSPAWN_LIB_NAME));
250 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data");
251 sandboxBuffer->current += strlen(APPSPAWN_LIB_NAME);
252 return 0;
253 }
254 // no match revered origin data
255 APPSPAWN_LOGE("ReplaceVariable var '%{public}s' no match variable", varName);
256 ret = memcpy_s(sandboxBuffer->buffer + sandboxBuffer->current,
257 sandboxBuffer->bufferLen - sandboxBuffer->current, varName, *varLen);
258 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data");
259 sandboxBuffer->current += *varLen;
260 return 0;
261 }
262
HandleVariableReplace(const SandboxContext * context,SandboxBuffer * sandboxBuffer,const char * source,const VarExtraData * extraData)263 static int HandleVariableReplace(const SandboxContext *context,
264 SandboxBuffer *sandboxBuffer, const char *source, const VarExtraData *extraData)
265 {
266 size_t sourceLen = strlen(source);
267 for (size_t i = 0; i < sourceLen; i++) {
268 if ((sandboxBuffer->current + 1) >= sandboxBuffer->bufferLen) {
269 return -1;
270 }
271 if (*(source + i) != '<') { // copy source
272 *(sandboxBuffer->buffer + sandboxBuffer->current) = *(source + i);
273 sandboxBuffer->current++;
274 continue;
275 }
276 uint32_t varLen = 0;
277 int ret = ReplaceVariable(context, source + i, sandboxBuffer, &varLen, extraData);
278 APPSPAWN_CHECK(ret == 0, return ret, "Failed to fill real data");
279 i += (varLen - 1);
280 }
281 return 0;
282 }
283
GetSandboxRealVar(const SandboxContext * context,uint32_t bufferType,const char * source,const char * prefix,const VarExtraData * extraData)284 const char *GetSandboxRealVar(const SandboxContext *context,
285 uint32_t bufferType, const char *source, const char *prefix, const VarExtraData *extraData)
286 {
287 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return NULL);
288 APPSPAWN_CHECK(bufferType < ARRAY_LENGTH(context->buffer), return NULL, "Invalid index for buffer");
289 SandboxBuffer *sandboxBuffer = &((SandboxContext *)context)->buffer[bufferType];
290 APPSPAWN_CHECK_ONLY_EXPER(sandboxBuffer != NULL && sandboxBuffer->buffer != NULL, return NULL);
291 const char *tmp = source;
292 int ret = 0;
293 if (!IsPathEmpty(prefix)) { // copy prefix data
294 ret = HandleVariableReplace(context, sandboxBuffer, prefix, extraData);
295 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to replace source %{public}s ", prefix);
296
297 if (tmp != NULL && sandboxBuffer->buffer[sandboxBuffer->current - 1] == '/' && *tmp == '/') {
298 tmp = source + 1;
299 }
300 }
301 if (!IsPathEmpty(tmp)) { // copy source data
302 ret = HandleVariableReplace(context, sandboxBuffer, tmp, extraData);
303 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to replace source %{public}s ", source);
304 }
305 sandboxBuffer->buffer[sandboxBuffer->current] = '\0';
306 // restore buffer
307 sandboxBuffer->current = 0;
308
309 // For the depNode scenario, if there are variables in the deps path, a secondary replacement is required
310 if (extraData != NULL && extraData->sandboxTag == SANDBOX_TAG_NAME_GROUP && extraData->data.depNode != NULL) {
311 if (strstr(sandboxBuffer->buffer, "<") != NULL) {
312 SandboxBuffer *tmpBuffer = &((SandboxContext *)context)->buffer[BUFFER_FOR_TMP];
313 ret = HandleVariableReplace(context, tmpBuffer, sandboxBuffer->buffer, extraData);
314 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to replace source %{public}s ", sandboxBuffer->buffer);
315 tmpBuffer->buffer[tmpBuffer->current] = '\0';
316 ret = strcpy_s(sandboxBuffer->buffer, sandboxBuffer->bufferLen, tmpBuffer->buffer);
317 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to copy source %{public}s ", sandboxBuffer->buffer);
318 }
319 }
320 return sandboxBuffer->buffer;
321 }
322
AddVariableReplaceHandler(const char * name,ReplaceVarHandler handler)323 int AddVariableReplaceHandler(const char *name, ReplaceVarHandler handler)
324 {
325 APPSPAWN_CHECK(name != NULL && handler != NULL, return APPSPAWN_ARG_INVALID, "Invalid arg ");
326 if (GetAppSandboxVarNode(name) != NULL) {
327 return APPSPAWN_NODE_EXIST;
328 }
329
330 size_t len = APPSPAWN_ALIGN(strlen(name) + 1);
331 AppSandboxVarNode *node = (AppSandboxVarNode *)malloc(sizeof(AppSandboxVarNode) + len);
332 APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create sandbox");
333 OH_ListInit(&node->node);
334 node->replaceVar = handler;
335 int ret = strcpy_s(node->name, len, name);
336 APPSPAWN_CHECK(ret == 0, free(node);
337 return -1, "Failed to copy name %{public}s", name);
338 OH_ListAddTail(&g_sandboxVarList, &node->node);
339 return 0;
340 }
341
AddDefaultVariable(void)342 void AddDefaultVariable(void)
343 {
344 AddVariableReplaceHandler(PARAMETER_PACKAGE_NAME, VarPackageNameReplace);
345 AddVariableReplaceHandler(PARAMETER_USER_ID, VarCurrentUseIdReplace);
346 AddVariableReplaceHandler(PARAMETER_PACKAGE_INDEX, VarPackageNameIndexReplace);
347 AddVariableReplaceHandler(PARAMETER_ARK_WEB_PACKAGE_INDEX, VarArkWebPackageNameReplace);
348 /*
349 deps-path路径变量的含义:
350 1)首次挂载时,表示mount-paths-deps->sandbox-path 【STAGE_GLOBAL或者应用孵化时的挂载】
351 使用 MOUNT_PATH_OP_REPLACE_BY_SANDBOX 标记
352 2)二次挂载时,表示mount-paths-deps->src-path;
353 如果mount-paths-deps->src-path为空,则使用mount-paths-deps->sandbox-path
354 使用 MOUNT_PATH_OP_ONLY_SANDBOX + MOUNT_PATH_OP_REPLACE_BY_SRC,只使用源目录,不添加root-dir
355 【RemountByName时,如el2解锁或nweb更新时】
356 */
357 AddVariableReplaceHandler("<deps-sandbox-path>", ReplaceVariableForDepSandboxPath);
358 AddVariableReplaceHandler("<deps-src-path>", ReplaceVariableForDepSrcPath);
359 AddVariableReplaceHandler("<deps-path>", ReplaceVariableForDepPath);
360 AddVariableReplaceHandler("<variablePackageName>", ReplaceVariableForpackageName);
361 }
362
ClearVariable(void)363 void ClearVariable(void)
364 {
365 OH_ListRemoveAll(&g_sandboxVarList, NULL);
366 }
367