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