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