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