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_client.h"
17#include "appspawn_mount_permission.h"
18#include "appspawn_hook.h"
19#include "appspawn_utils.h"
20#include "parameter.h"
21#include "securec.h"
22
23static inline int CalcFlagsUnits(uint32_t maxIndex)
24{
25    return ((maxIndex / 32) + ((maxIndex % 32 == 0) ? 0 : 1));  // 32 max bit in uint32_t
26}
27
28static inline int SetAppSpawnMsgFlags(AppSpawnMsgFlags *msgFlags, uint32_t index)
29{
30    uint32_t blockIndex = index / 32;  // 32 max bit in int
31    uint32_t bitIndex = index % 32;    // 32 max bit in int
32    if (blockIndex < msgFlags->count) {
33        msgFlags->flags[blockIndex] |= (1 << bitIndex);
34    }
35    return 0;
36}
37
38static inline int CheckMsg(const AppSpawnReqMsgNode *reqNode, const AppSpawnTlv *tlv, const char *name)
39{
40    if ((reqNode->msg->msgLen + tlv->tlvLen) > MAX_MSG_TOTAL_LENGTH) {
41        APPSPAWN_LOGE("The message is too long %{public}s", name);
42        return APPSPAWN_MSG_INVALID;
43    }
44    if (reqNode->msg->msgType == MSG_GET_RENDER_TERMINATION_STATUS) {
45        if (tlv->tlvType != TLV_RENDER_TERMINATION_INFO) {
46            APPSPAWN_LOGE("Not support tlv %{public}s for message MSG_GET_RENDER_TERMINATION_STATUS", name);
47            return APPSPAWN_TLV_NOT_SUPPORT;
48        }
49    }
50    return 0;
51}
52
53static inline int CheckInputString(const char *info, const char *value, uint32_t maxLen)
54{
55    APPSPAWN_CHECK(value != NULL, return APPSPAWN_ARG_INVALID, "Invalid input info for %{public}s ", info);
56    uint32_t valueLen = (uint32_t)strlen(value);
57    APPSPAWN_CHECK(valueLen > 0 && valueLen < maxLen, return APPSPAWN_ARG_INVALID,
58        "Invalid input string length '%{public}s' for '%{public}s'", value, info);
59    return 0;
60}
61
62static AppSpawnMsgBlock *CreateAppSpawnMsgBlock(AppSpawnReqMsgNode *reqNode)
63{
64    AppSpawnMsgBlock *block = (AppSpawnMsgBlock *)calloc(1, MAX_MSG_BLOCK_LEN);
65    APPSPAWN_CHECK(block != NULL, return NULL, "Failed to create block");
66    OH_ListInit(&block->node);
67    block->blockSize = MAX_MSG_BLOCK_LEN - sizeof(AppSpawnMsgBlock);
68    block->currentIndex = 0;
69    OH_ListAddTail(&reqNode->msgBlocks, &block->node);
70    return block;
71}
72
73static AppSpawnMsgBlock *GetValidMsgBlock(const AppSpawnReqMsgNode *reqNode, uint32_t realLen)
74{
75    AppSpawnMsgBlock *block = NULL;
76    struct ListNode *node = reqNode->msgBlocks.next;
77    while (node != &reqNode->msgBlocks) {
78        block = ListEntry(node, AppSpawnMsgBlock, node);
79        if ((block->blockSize - block->currentIndex) >= realLen) {
80            return block;
81        }
82        node = node->next;
83    }
84    return NULL;
85}
86
87static AppSpawnMsgBlock *GetTailMsgBlock(const AppSpawnReqMsgNode *reqNode)
88{
89    AppSpawnMsgBlock *block = NULL;
90    struct ListNode *node = reqNode->msgBlocks.prev;
91    if (node != &reqNode->msgBlocks) {
92        block = ListEntry(node, AppSpawnMsgBlock, node);
93    }
94    return block;
95}
96
97static void FreeMsgBlock(ListNode *node)
98{
99    AppSpawnMsgBlock *block = ListEntry(node, AppSpawnMsgBlock, node);
100    OH_ListRemove(node);
101    OH_ListInit(node);
102    free(block);
103}
104
105static int AddAppDataToBlock(AppSpawnMsgBlock *block, const uint8_t *data, uint32_t dataLen, int32_t dataType)
106{
107    APPSPAWN_CHECK(block->blockSize > block->currentIndex,
108        return APPSPAWN_BUFFER_NOT_ENOUGH, "Not enough buffer for data");
109    uint32_t reminderLen = block->blockSize - block->currentIndex;
110    uint32_t realDataLen = (dataType == DATA_TYPE_STRING) ? APPSPAWN_ALIGN(dataLen + 1) : APPSPAWN_ALIGN(dataLen);
111    APPSPAWN_CHECK(reminderLen >= realDataLen, return APPSPAWN_BUFFER_NOT_ENOUGH, "Not enough buffer for data");
112    int ret = memcpy_s(block->buffer + block->currentIndex, reminderLen, data, dataLen);
113    APPSPAWN_CHECK(ret == EOK, return APPSPAWN_SYSTEM_ERROR, "Failed to copy data");
114    if (dataType == DATA_TYPE_STRING) {
115        *((char *)block->buffer + block->currentIndex + dataLen) = '\0';
116    }
117    block->currentIndex += realDataLen;
118    return 0;
119}
120
121static int AddAppDataToTail(AppSpawnReqMsgNode *reqNode, const uint8_t *data, uint32_t dataLen, int32_t dataType)
122{
123    uint32_t currLen = 0;
124    AppSpawnMsgBlock *block = GetTailMsgBlock(reqNode);
125    APPSPAWN_CHECK(block != NULL, return APPSPAWN_BUFFER_NOT_ENOUGH, "Not block info reqNode");
126    uint32_t realDataLen = (dataType == DATA_TYPE_STRING) ? dataLen + 1 : dataLen;
127    do {
128        uint32_t reminderBufferLen = block->blockSize - block->currentIndex;
129        uint32_t reminderDataLen = realDataLen - currLen;
130        uint32_t realLen = APPSPAWN_ALIGN(reminderDataLen);
131        uint32_t realCopy = 0;
132        if (reminderBufferLen >= realLen) {  // 足够存储,直接保存
133            int ret = memcpy_s(block->buffer + block->currentIndex, reminderBufferLen, data + currLen, reminderDataLen);
134            APPSPAWN_CHECK(ret == EOK, return APPSPAWN_SYSTEM_ERROR, "Failed to copy data");
135            block->currentIndex += realLen;
136            break;
137        } else if (reminderBufferLen > 0) {
138            realCopy = reminderDataLen > reminderBufferLen ? reminderBufferLen : reminderDataLen;
139            int ret = memcpy_s(block->buffer + block->currentIndex, reminderBufferLen, data + currLen, realCopy);
140            APPSPAWN_CHECK(ret == EOK, return APPSPAWN_SYSTEM_ERROR, "Failed to copy data");
141            block->currentIndex += realCopy;
142            currLen += realCopy;
143        }
144        block = CreateAppSpawnMsgBlock(reqNode);
145        APPSPAWN_CHECK(block != NULL, return APPSPAWN_SYSTEM_ERROR, "Not enough buffer for data");
146    } while (currLen < realDataLen);
147    return 0;
148}
149
150static int AddAppDataEx(AppSpawnReqMsgNode *reqNode, const char *name, const AppSpawnAppData *data)
151{
152    AppSpawnTlvExt tlv = {};
153    if (data->dataType == DATA_TYPE_STRING) {
154        tlv.tlvLen = APPSPAWN_ALIGN(data->dataLen + 1) + sizeof(AppSpawnTlvExt);
155    } else {
156        tlv.tlvLen = APPSPAWN_ALIGN(data->dataLen) + sizeof(AppSpawnTlvExt);
157    }
158    tlv.tlvType = TLV_MAX;
159    tlv.dataLen = data->dataLen;
160    tlv.dataType = data->dataType;
161    int ret = strcpy_s(tlv.tlvName, sizeof(tlv.tlvName), name);
162    APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to add data for %{public}s", name);
163    ret = CheckMsg(reqNode, (AppSpawnTlv *)&tlv, name);
164    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
165
166    APPSPAWN_LOGV("AddAppDataEx tlv [%{public}s %{public}u ] dataLen: %{public}u start: %{public}u",
167        name, tlv.tlvLen, data->dataLen, reqNode->msg->msgLen);
168    // 获取一个能保存改完整tlv的block
169    AppSpawnMsgBlock *block = GetValidMsgBlock(reqNode, tlv.tlvLen);
170    if (block != NULL) {
171        ret = AddAppDataToBlock(block, (uint8_t *)&tlv, sizeof(tlv), 0);
172        APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv for %{public}s", name);
173        ret = AddAppDataToBlock(block, data->data, data->dataLen, data->dataType);
174        APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data for %{public}s", name);
175    } else {
176        // 没有一个可用的block,最队列最后添加数据
177        ret = AddAppDataToTail(reqNode, (uint8_t *)&tlv, sizeof(tlv), 0);
178        APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv to tail for %{public}s", name);
179        ret = AddAppDataToTail(reqNode, data->data, data->dataLen, data->dataType);
180        APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data to tail for %{public}s", name);
181    }
182    reqNode->msg->tlvCount++;
183    reqNode->msg->msgLen += tlv.tlvLen;
184    APPSPAWN_LOGV("AddAppDataEx success name '%{public}s' end: %{public}u", name, reqNode->msg->msgLen);
185    return 0;
186}
187
188static int AddAppData(AppSpawnReqMsgNode *reqNode,
189    uint32_t tlvType, const AppSpawnAppData *data, uint32_t count, const char *name)
190{
191    // 计算实际数据的长度
192    uint32_t realLen = sizeof(AppSpawnTlv);
193    uint32_t dataLen = 0;
194    for (uint32_t index = 0; index < count; index++) {
195        dataLen += data[index].dataLen;
196        realLen += (data[index].dataType == DATA_TYPE_STRING) ?
197            APPSPAWN_ALIGN(data[index].dataLen + 1) : APPSPAWN_ALIGN(data[index].dataLen);
198    }
199    AppSpawnTlv tlv;
200    tlv.tlvLen = realLen;
201    tlv.tlvType = tlvType;
202    int ret = CheckMsg(reqNode, &tlv, name);
203    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
204
205    APPSPAWN_LOGV("AddAppData tlv [%{public}s %{public}u] dataLen: %{public}u start: %{public}u",
206        name, tlv.tlvLen, dataLen, reqNode->msg->msgLen);
207    // 获取一个能保存改完整tlv的block
208    AppSpawnMsgBlock *block = GetValidMsgBlock(reqNode, tlv.tlvLen);
209    if (block != NULL) {
210        ret = AddAppDataToBlock(block, (uint8_t *)&tlv, sizeof(tlv), 0);
211        APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv for %{public}d", tlvType);
212
213        for (uint32_t index = 0; index < count; index++) {
214            ret = AddAppDataToBlock(block, (uint8_t *)data[index].data, data[index].dataLen, data[index].dataType);
215            APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data for %{public}d", tlvType);
216        }
217    } else {
218        // 没有一个可用的block,最队列最后添加数据
219        ret = AddAppDataToTail(reqNode, (uint8_t *)&tlv, sizeof(tlv), 0);
220        APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv to tail for %{public}d", tlvType);
221        // 添加tlv信息
222        for (uint32_t index = 0; index < count; index++) {
223            ret = AddAppDataToTail(reqNode, (uint8_t *)data[index].data, data[index].dataLen, data[index].dataType);
224            APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data for %{public}d", tlvType);
225        }
226    }
227    reqNode->msg->msgLen += tlv.tlvLen;
228    APPSPAWN_LOGV("AddAppData success tlvType %{public}s end: %{public}u", name, reqNode->msg->msgLen);
229    return 0;
230}
231
232static int SetFlagsTlv(AppSpawnReqMsgNode *reqNode,
233    AppSpawnMsgBlock *block, AppSpawnMsgFlags **msgFlags, int type, int maxCount)
234{
235    uint32_t units = (uint32_t)CalcFlagsUnits(maxCount);
236    APPSPAWN_LOGV("SetFlagsTlv maxCount %{public}d type %{public}d units %{public}d", maxCount, type, units);
237    uint32_t flagsLen = sizeof(AppSpawnTlv) + sizeof(AppSpawnMsgFlags) + sizeof(uint32_t) * units;
238    APPSPAWN_CHECK((block->blockSize - block->currentIndex) > flagsLen,
239        return APPSPAWN_BUFFER_NOT_ENOUGH, "Invalid block to set flags tlv type %{public}d", type);
240
241    AppSpawnTlv *tlv = (AppSpawnTlv *)(block->buffer + block->currentIndex);
242    tlv->tlvLen = flagsLen;
243    tlv->tlvType = type;
244    *msgFlags = (AppSpawnMsgFlags *)(block->buffer + block->currentIndex + sizeof(AppSpawnTlv));
245    (*msgFlags)->count = units;
246    block->currentIndex += flagsLen;
247    reqNode->msg->msgLen += flagsLen;
248    reqNode->msg->tlvCount++;
249    return 0;
250}
251
252static int CreateBaseMsg(AppSpawnReqMsgNode *reqNode, uint32_t msgType, const char *processName)
253{
254    AppSpawnMsgBlock *block = CreateAppSpawnMsgBlock(reqNode);
255    APPSPAWN_CHECK(block != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create block for %{public}s", processName);
256
257    // 保留消息头的大小
258    reqNode->msg = (AppSpawnMsg *)(block->buffer + block->currentIndex);
259    reqNode->msg->magic = APPSPAWN_MSG_MAGIC;
260    reqNode->msg->msgId = 0;
261    reqNode->msg->msgType = msgType;
262    reqNode->msg->msgLen = sizeof(AppSpawnMsg);
263    reqNode->msg->tlvCount = 0;
264    int ret = strcpy_s(reqNode->msg->processName, sizeof(reqNode->msg->processName), processName);
265    APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to create block for %{public}s", processName);
266    block->currentIndex = sizeof(AppSpawnMsg);
267    ret = SetFlagsTlv(reqNode, block, &reqNode->msgFlags, TLV_MSG_FLAGS, MAX_FLAGS_INDEX);
268    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
269    APPSPAWN_CHECK_ONLY_EXPER(msgType == MSG_APP_SPAWN || msgType == MSG_SPAWN_NATIVE_PROCESS, return 0);
270    int maxCount = GetPermissionMaxCount();
271    APPSPAWN_CHECK(maxCount > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid max for permission %{public}s", processName);
272    ret = SetFlagsTlv(reqNode, block, &reqNode->permissionFlags, TLV_PERMISSION, maxCount);
273    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
274    APPSPAWN_LOGV("CreateBaseMsg msgLen: %{public}u %{public}u", reqNode->msg->msgLen, block->currentIndex);
275    return 0;
276}
277
278static void DeleteAppSpawnReqMsg(AppSpawnReqMsgNode *reqNode)
279{
280    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return);
281    APPSPAWN_LOGV("DeleteAppSpawnReqMsg reqId: %{public}u", reqNode->reqId);
282    reqNode->msgFlags = NULL;
283    reqNode->permissionFlags = NULL;
284    reqNode->msg = NULL;
285    // 释放block
286    OH_ListRemoveAll(&reqNode->msgBlocks, FreeMsgBlock);
287    free(reqNode);
288}
289
290static AppSpawnReqMsgNode *CreateAppSpawnReqMsg(uint32_t msgType, const char *processName)
291{
292    static uint32_t reqId = 0;
293    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)malloc(sizeof(AppSpawnReqMsgNode));
294    APPSPAWN_CHECK(reqNode != NULL, return NULL, "Failed to create msg node for %{public}s", processName);
295
296    OH_ListInit(&reqNode->node);
297    OH_ListInit(&reqNode->msgBlocks);
298    reqNode->reqId = ++reqId;
299    reqNode->msg = NULL;
300    reqNode->msgFlags = NULL;
301    reqNode->permissionFlags = NULL;
302    reqNode->fdCount = 0;
303    reqNode->isAsan = 0;
304    int ret = CreateBaseMsg(reqNode, msgType, processName);
305    APPSPAWN_CHECK(ret == 0, DeleteAppSpawnReqMsg(reqNode);
306         return NULL, "Failed to create base msg for %{public}s", processName);
307    APPSPAWN_LOGV("CreateAppSpawnReqMsg reqId: %{public}d msg type: %{public}u processName: %{public}s",
308        reqNode->reqId, msgType, processName);
309    return reqNode;
310}
311
312int AppSpawnReqMsgAddFd(AppSpawnReqMsgHandle reqHandle, const char* fdName, int fd)
313{
314    APPSPAWN_CHECK(reqHandle != NULL, return APPSPAWN_ARG_INVALID, "Invalid reqHandle");
315    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
316    APPSPAWN_CHECK(reqNode != NULL, return APPSPAWN_ARG_INVALID, "Invalid reqNode");
317    APPSPAWN_CHECK(fd >= 0 && fdName != NULL && strlen(fdName) <= APP_FDNAME_MAXLEN
318        &&  reqNode->fdCount < APP_MAX_FD_COUNT, return APPSPAWN_ARG_INVALID,
319        "Invalid fdinfo %{public}d %{public}d %{public}d", fd, fdName != NULL, reqNode->fdCount);
320    reqNode->fds[reqNode->fdCount++] = fd;
321    return AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_APP_FD, (void *)fdName);
322}
323
324static void GetSpecialGid(const char *bundleName, gid_t gidTable[], uint32_t *gidCount)
325{
326    // special handle bundle name medialibrary and scanner
327    const char *specialBundleNames[] = {
328        "com.ohos.medialibrary.medialibrarydata", "com.ohos.medialibrary.medialibrarydata:backup"
329    };
330
331    for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) {
332        if (strcmp(bundleName, specialBundleNames[i]) == 0) {
333            if (*gidCount < APP_MAX_GIDS) {
334                gidTable[(*gidCount)++] = GID_USER_DATA_RW;
335                gidTable[(*gidCount)++] = GID_FILE_ACCESS;
336            }
337            break;
338        }
339    }
340}
341
342int AppSpawnReqMsgCreate(AppSpawnMsgType msgType, const char *processName, AppSpawnReqMsgHandle *reqHandle)
343{
344    APPSPAWN_CHECK(reqHandle != NULL, return APPSPAWN_ARG_INVALID, "Invalid request handle");
345    APPSPAWN_CHECK(msgType < MAX_TYPE_INVALID,
346        return APPSPAWN_MSG_INVALID, "Invalid message type %{public}u %{public}s", msgType, processName);
347    int ret = CheckInputString("processName", processName, APP_LEN_PROC_NAME);
348    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
349    AppSpawnReqMsgNode *reqNode = CreateAppSpawnReqMsg(msgType, processName);
350    APPSPAWN_CHECK(reqNode != NULL, return APPSPAWN_SYSTEM_ERROR,
351        "Failed to create msg node for %{public}s", processName);
352    *reqHandle = (AppSpawnReqMsgHandle)(reqNode);
353    return 0;
354}
355
356void AppSpawnReqMsgFree(AppSpawnReqMsgHandle reqHandle)
357{
358    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
359    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return);
360    DeleteAppSpawnReqMsg(reqNode);
361}
362
363int AppSpawnReqMsgSetAppDacInfo(AppSpawnReqMsgHandle reqHandle, const AppDacInfo *dacInfo)
364{
365    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
366    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
367    APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_ARG_INVALID, "Invalid dacInfo ");
368
369    AppDacInfo tmpDacInfo = {0};
370    (void)memcpy_s(&tmpDacInfo, sizeof(tmpDacInfo), dacInfo, sizeof(tmpDacInfo));
371    GetSpecialGid(reqNode->msg->processName, tmpDacInfo.gidTable, &tmpDacInfo.gidCount);
372
373    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
374    data[0].data = (uint8_t *)&tmpDacInfo;
375    data[0].dataLen = sizeof(AppSpawnMsgDacInfo);
376    return AddAppData(reqNode, TLV_DAC_INFO, data, 1, "TLV_DAC_INFO");
377}
378
379int AppSpawnReqMsgSetBundleInfo(AppSpawnReqMsgHandle reqHandle, uint32_t bundleIndex, const char *bundleName)
380{
381    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
382    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
383    int ret = CheckInputString("TLV_BUNDLE_INFO", bundleName, APP_LEN_BUNDLE_NAME);
384    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
385
386    AppSpawnMsgBundleInfo info = {};
387    info.bundleIndex = bundleIndex;
388    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
389    data[0].data = (uint8_t *)&info;
390    data[0].dataLen = sizeof(AppSpawnMsgBundleInfo);
391    data[1].data = (uint8_t *)bundleName;
392    data[1].dataLen = strlen(bundleName);
393    data[1].dataType = DATA_TYPE_STRING;
394    return AddAppData(reqNode, TLV_BUNDLE_INFO, data, MAX_DATA_IN_TLV, "TLV_BUNDLE_INFO");
395}
396
397static int CheckEnabled(const char *param, const char *value)
398{
399    char tmp[32] = {0}; // 32 max
400    int ret = GetParameter(param, "", tmp, sizeof(tmp));
401    APPSPAWN_LOGV("CheckEnabled key %{public}s ret %{public}d result: %{public}s", param, ret, tmp);
402    int enabled = (ret > 0 && strcmp(tmp, value) == 0);
403    return enabled;
404}
405
406int AppSpawnReqMsgSetAppFlag(AppSpawnReqMsgHandle reqHandle, AppFlagsIndex flagIndex)
407{
408    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
409    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
410    APPSPAWN_CHECK(reqNode->msgFlags != NULL, return APPSPAWN_ARG_INVALID, "No msg flags tlv ");
411    APPSPAWN_CHECK(flagIndex < MAX_FLAGS_INDEX, return APPSPAWN_ARG_INVALID,
412        "Invalid msg app flags %{public}d", flagIndex);
413    if (!reqNode->isAsan &&
414        (flagIndex == APP_FLAGS_UBSAN_ENABLED || flagIndex == APP_FLAGS_ASANENABLED ||
415        flagIndex == APP_FLAGS_TSAN_ENABLED || flagIndex == APP_FLAGS_HWASAN_ENABLED ||
416        (flagIndex == APP_FLAGS_COLD_BOOT && CheckEnabled("startup.appspawn.cold.boot", "true")))) {
417        reqNode->isAsan = 1;
418    }
419
420    return SetAppSpawnMsgFlags(reqNode->msgFlags, flagIndex);
421}
422
423int AppSpawnReqMsgAddExtInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const uint8_t *value, uint32_t valueLen)
424{
425    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
426    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
427    int ret = CheckInputString("check name", name, APPSPAWN_TLV_NAME_LEN);
428    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
429    APPSPAWN_CHECK(value != NULL && valueLen <= EXTRAINFO_TOTAL_LENGTH_MAX && valueLen > 0,
430        return APPSPAWN_ARG_INVALID, "Invalid ext value ");
431
432    APPSPAWN_LOGV("AppSpawnReqMsgAddExtInfo name %{public}s", name);
433    AppSpawnAppData data[1] = {};  // 1 max data count
434    data[0].data = (uint8_t *)value;
435    data[0].dataLen = valueLen;
436    return AddAppDataEx(reqNode, name, data);  // 2 max count
437}
438
439int AppSpawnReqMsgAddStringInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const char *value)
440{
441    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
442    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
443    int ret = CheckInputString("check name", name, APPSPAWN_TLV_NAME_LEN);
444    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
445    ret = CheckInputString(name, value, EXTRAINFO_TOTAL_LENGTH_MAX);
446    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
447
448    APPSPAWN_LOGV("AppSpawnReqMsgAddStringInfo name %{public}s", name);
449    AppSpawnAppData data[1] = {};  // 1 max data count
450    data[0].data = (uint8_t *)value;
451    data[0].dataLen = strlen(value);
452    data[0].dataType = DATA_TYPE_STRING;
453    return AddAppDataEx(reqNode, name, data);  // 2 max count
454}
455
456int AppSpawnReqMsgAddPermission(AppSpawnReqMsgHandle reqHandle, const char *permission)
457{
458    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
459    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
460    APPSPAWN_CHECK(permission != NULL, return APPSPAWN_ARG_INVALID, "Invalid permission ");
461    APPSPAWN_CHECK(reqNode->permissionFlags != NULL, return APPSPAWN_ARG_INVALID, "No permission tlv ");
462
463    int32_t maxIndex = GetMaxPermissionIndex(NULL);
464    int index = GetPermissionIndex(NULL, permission);
465    APPSPAWN_CHECK(index >= 0 && index < maxIndex,
466        return APPSPAWN_PERMISSION_NOT_SUPPORT, "Invalid permission %{public}s", permission);
467    APPSPAWN_LOGV("AddPermission index %{public}d name %{public}s", index, permission);
468    int ret = SetAppSpawnMsgFlags(reqNode->permissionFlags, index);
469    APPSPAWN_CHECK(ret == 0, return ret, "Invalid permission %{public}s", permission);
470    return 0;
471}
472
473int AppSpawnReqMsgSetAppDomainInfo(AppSpawnReqMsgHandle reqHandle, uint32_t hapFlags, const char *apl)
474{
475    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
476    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
477    int ret = CheckInputString("TLV_DOMAIN_INFO", apl, APP_APL_MAX_LEN);
478    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
479
480    AppSpawnMsgDomainInfo msgDomainInfo;
481    msgDomainInfo.hapFlags = hapFlags;
482    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
483    data[0].data = (uint8_t *)&msgDomainInfo;
484    data[0].dataLen = sizeof(AppSpawnMsgDomainInfo);
485    data[1].data = (uint8_t *)apl;
486    data[1].dataLen = strlen(apl);
487    data[1].dataType = DATA_TYPE_STRING;
488    return AddAppData(reqNode, TLV_DOMAIN_INFO, data, MAX_DATA_IN_TLV, "TLV_DOMAIN_INFO");
489}
490
491int AppSpawnReqMsgSetAppInternetPermissionInfo(AppSpawnReqMsgHandle reqHandle, uint8_t allow, uint8_t setAllow)
492{
493    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
494    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
495
496    AppSpawnMsgInternetInfo info = {};
497    info.allowInternet = allow;
498    info.setAllowInternet = setAllow;
499    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
500    data[0].data = (uint8_t *)&info;
501    data[0].dataLen = sizeof(AppSpawnMsgInternetInfo);
502    return AddAppData(reqNode, TLV_INTERNET_INFO, data, 1, "TLV_INTERNET_INFO");
503}
504
505int AppSpawnReqMsgSetAppOwnerId(AppSpawnReqMsgHandle reqHandle, const char *ownerId)
506{
507    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
508    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
509    int ret = CheckInputString("TLV_OWNER_INFO", ownerId, APP_OWNER_ID_LEN);
510    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
511
512    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
513    data[0].data = (uint8_t *)ownerId;
514    data[0].dataLen = strlen(ownerId);
515    data[0].dataType = DATA_TYPE_STRING;
516    return AddAppData(reqNode, TLV_OWNER_INFO, data, 1, "TLV_OWNER_INFO");
517}
518
519int AppSpawnReqMsgSetAppAccessToken(AppSpawnReqMsgHandle reqHandle, uint64_t accessTokenIdEx)
520{
521    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
522    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
523
524    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
525    data[0].data = (uint8_t *)&accessTokenIdEx;
526    data[0].dataLen = sizeof(accessTokenIdEx);
527    return AddAppData(reqNode, TLV_ACCESS_TOKEN_INFO, data, 1, "TLV_ACCESS_TOKEN_INFO");
528}
529
530int AppSpawnTerminateMsgCreate(pid_t pid, AppSpawnReqMsgHandle *reqHandle)
531{
532    APPSPAWN_CHECK(reqHandle != NULL, return APPSPAWN_ARG_INVALID, "Invalid request handle");
533    AppSpawnReqMsgNode *reqNode = CreateAppSpawnReqMsg(MSG_GET_RENDER_TERMINATION_STATUS, "terminate-process");
534    APPSPAWN_CHECK(reqNode != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create msg node");
535
536    AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
537    data[0].data = (uint8_t *)&pid;
538    data[0].dataLen = sizeof(pid);
539    int ret = AddAppData(reqNode, TLV_RENDER_TERMINATION_INFO, data, 1, "TLV_RENDER_TERMINATION_INFO");
540    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, DeleteAppSpawnReqMsg(reqNode);
541        return ret);
542    *reqHandle = (AppSpawnReqMsgHandle)(reqNode);
543    return 0;
544}
545
546int AppSpawnClientAddPermission(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle, const char *permission)
547{
548    AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle;
549    APPSPAWN_CHECK(reqMgr != NULL, return APPSPAWN_ARG_INVALID, "Invalid reqMgr");
550    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
551    APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
552    APPSPAWN_CHECK(permission != NULL, return APPSPAWN_ARG_INVALID, "Invalid permission ");
553    APPSPAWN_CHECK(reqNode->permissionFlags != NULL, return APPSPAWN_ARG_INVALID, "No permission tlv ");
554
555    int32_t maxIndex = GetMaxPermissionIndex(handle);
556    int index = GetPermissionIndex(handle, permission);
557    APPSPAWN_CHECK(index >= 0 && index < maxIndex,
558        return APPSPAWN_PERMISSION_NOT_SUPPORT, "Invalid permission %{public}s", permission);
559    APPSPAWN_LOGV("add permission index %{public}d name %{public}s", index, permission);
560    int ret = SetAppSpawnMsgFlags(reqNode->permissionFlags, index);
561    APPSPAWN_CHECK(ret == 0, return ret, "Invalid permission %{public}s", permission);
562    return 0;
563}
564