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