* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "appspawn_client.h"
#include "appspawn_mount_permission.h"
#include "appspawn_hook.h"
#include "appspawn_utils.h"
#include "parameter.h"
#include "securec.h"
#define OHOS_PERMISSION_FOWNER "ohos.permission.FOWNER"
static inline int CalcFlagsUnits(uint32_t maxIndex)
{
return ((maxIndex / 32) + ((maxIndex % 32 == 0) ? 0 : 1));
}
static inline int SetAppSpawnMsgFlags(AppSpawnMsgFlags *msgFlags, uint32_t index)
{
uint32_t blockIndex = index / 32;
uint32_t bitIndex = index % 32;
if (blockIndex < msgFlags->count) {
msgFlags->flags[blockIndex] |= (1 << bitIndex);
}
return 0;
}
static inline int CheckMsg(const AppSpawnReqMsgNode *reqNode, const AppSpawnTlv *tlv, const char *name)
{
if ((reqNode->msg->msgLen + tlv->tlvLen) > MAX_MSG_TOTAL_LENGTH) {
APPSPAWN_LOGE("The message is too long %{public}s", name);
return APPSPAWN_MSG_INVALID;
}
if (reqNode->msg->msgType == MSG_GET_RENDER_TERMINATION_STATUS) {
if (tlv->tlvType != TLV_RENDER_TERMINATION_INFO) {
APPSPAWN_LOGE("Not support tlv %{public}s for message MSG_GET_RENDER_TERMINATION_STATUS", name);
return APPSPAWN_TLV_NOT_SUPPORT;
}
}
return 0;
}
static inline int CheckInputString(const char *info, const char *value, uint32_t maxLen)
{
APPSPAWN_CHECK(value != NULL, return APPSPAWN_ARG_INVALID, "Invalid input info for %{public}s ", info);
uint32_t valueLen = (uint32_t)strlen(value);
APPSPAWN_CHECK(valueLen > 0 && valueLen < maxLen, return APPSPAWN_ARG_INVALID,
"Invalid input string length '%{public}s' for '%{public}s'", value, info);
return 0;
}
static AppSpawnMsgBlock *CreateAppSpawnMsgBlock(AppSpawnReqMsgNode *reqNode)
{
AppSpawnMsgBlock *block = (AppSpawnMsgBlock *)calloc(1, MAX_MSG_BLOCK_LEN);
APPSPAWN_CHECK(block != NULL, return NULL, "Failed to create block");
OH_ListInit(&block->node);
block->blockSize = MAX_MSG_BLOCK_LEN - sizeof(AppSpawnMsgBlock);
block->currentIndex = 0;
OH_ListAddTail(&reqNode->msgBlocks, &block->node);
return block;
}
static AppSpawnMsgBlock *GetValidMsgBlock(const AppSpawnReqMsgNode *reqNode, uint32_t realLen)
{
AppSpawnMsgBlock *block = NULL;
struct ListNode *node = reqNode->msgBlocks.next;
while (node != &reqNode->msgBlocks) {
block = ListEntry(node, AppSpawnMsgBlock, node);
if ((block->blockSize - block->currentIndex) >= realLen) {
return block;
}
node = node->next;
}
return NULL;
}
static AppSpawnMsgBlock *GetTailMsgBlock(const AppSpawnReqMsgNode *reqNode)
{
AppSpawnMsgBlock *block = NULL;
struct ListNode *node = reqNode->msgBlocks.prev;
if (node != &reqNode->msgBlocks) {
block = ListEntry(node, AppSpawnMsgBlock, node);
}
return block;
}
static void FreeMsgBlock(ListNode *node)
{
AppSpawnMsgBlock *block = ListEntry(node, AppSpawnMsgBlock, node);
OH_ListRemove(node);
OH_ListInit(node);
free(block);
}
static int AddAppDataToBlock(AppSpawnMsgBlock *block, const uint8_t *data, uint32_t dataLen, int32_t dataType)
{
APPSPAWN_CHECK(block->blockSize > block->currentIndex,
return APPSPAWN_BUFFER_NOT_ENOUGH, "Not enough buffer for data");
uint32_t reminderLen = block->blockSize - block->currentIndex;
uint32_t realDataLen = (dataType == DATA_TYPE_STRING) ? APPSPAWN_ALIGN(dataLen + 1) : APPSPAWN_ALIGN(dataLen);
APPSPAWN_CHECK(reminderLen >= realDataLen, return APPSPAWN_BUFFER_NOT_ENOUGH, "Not enough buffer for data");
int ret = memcpy_s(block->buffer + block->currentIndex, reminderLen, data, dataLen);
APPSPAWN_CHECK(ret == EOK, return APPSPAWN_SYSTEM_ERROR, "Failed to copy data");
if (dataType == DATA_TYPE_STRING) {
*((char *)block->buffer + block->currentIndex + dataLen) = '\0';
}
block->currentIndex += realDataLen;
return 0;
}
static int AddAppDataToTail(AppSpawnReqMsgNode *reqNode, const uint8_t *data, uint32_t dataLen, int32_t dataType)
{
uint32_t currLen = 0;
AppSpawnMsgBlock *block = GetTailMsgBlock(reqNode);
APPSPAWN_CHECK(block != NULL, return APPSPAWN_BUFFER_NOT_ENOUGH, "Not block info reqNode");
uint32_t realDataLen = (dataType == DATA_TYPE_STRING) ? dataLen + 1 : dataLen;
do {
uint32_t reminderBufferLen = block->blockSize - block->currentIndex;
uint32_t reminderDataLen = realDataLen - currLen;
uint32_t realLen = APPSPAWN_ALIGN(reminderDataLen);
uint32_t realCopy = 0;
if (reminderBufferLen >= realLen) {
int ret = memcpy_s(block->buffer + block->currentIndex, reminderBufferLen, data + currLen, reminderDataLen);
APPSPAWN_CHECK(ret == EOK, return APPSPAWN_SYSTEM_ERROR, "Failed to copy data");
block->currentIndex += realLen;
break;
} else if (reminderBufferLen > 0) {
realCopy = reminderDataLen > reminderBufferLen ? reminderBufferLen : reminderDataLen;
int ret = memcpy_s(block->buffer + block->currentIndex, reminderBufferLen, data + currLen, realCopy);
APPSPAWN_CHECK(ret == EOK, return APPSPAWN_SYSTEM_ERROR, "Failed to copy data");
block->currentIndex += realCopy;
currLen += realCopy;
}
block = CreateAppSpawnMsgBlock(reqNode);
APPSPAWN_CHECK(block != NULL, return APPSPAWN_SYSTEM_ERROR, "Not enough buffer for data");
} while (currLen < realDataLen);
return 0;
}
static int AddAppDataEx(AppSpawnReqMsgNode *reqNode, const char *name, const AppSpawnAppData *data)
{
AppSpawnTlvExt tlv = {};
if (data->dataType == DATA_TYPE_STRING) {
tlv.tlvLen = APPSPAWN_ALIGN(data->dataLen + 1) + sizeof(AppSpawnTlvExt);
} else {
tlv.tlvLen = APPSPAWN_ALIGN(data->dataLen) + sizeof(AppSpawnTlvExt);
}
tlv.tlvType = TLV_MAX;
tlv.dataLen = data->dataLen;
tlv.dataType = data->dataType;
int ret = strcpy_s(tlv.tlvName, sizeof(tlv.tlvName), name);
APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to add data for %{public}s", name);
ret = CheckMsg(reqNode, (AppSpawnTlv *)&tlv, name);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
APPSPAWN_LOGV("AddAppDataEx tlv [%{public}s %{public}u ] dataLen: %{public}u start: %{public}u",
name, tlv.tlvLen, data->dataLen, reqNode->msg->msgLen);
AppSpawnMsgBlock *block = GetValidMsgBlock(reqNode, tlv.tlvLen);
if (block != NULL) {
ret = AddAppDataToBlock(block, (uint8_t *)&tlv, sizeof(tlv), 0);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv for %{public}s", name);
ret = AddAppDataToBlock(block, data->data, data->dataLen, data->dataType);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data for %{public}s", name);
} else {
ret = AddAppDataToTail(reqNode, (uint8_t *)&tlv, sizeof(tlv), 0);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv to tail for %{public}s", name);
ret = AddAppDataToTail(reqNode, data->data, data->dataLen, data->dataType);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data to tail for %{public}s", name);
}
reqNode->msg->tlvCount++;
reqNode->msg->msgLen += tlv.tlvLen;
APPSPAWN_LOGV("AddAppDataEx success name '%{public}s' end: %{public}u", name, reqNode->msg->msgLen);
return 0;
}
static int AddAppData(AppSpawnReqMsgNode *reqNode,
uint32_t tlvType, const AppSpawnAppData *data, uint32_t count, const char *name)
{
uint32_t realLen = sizeof(AppSpawnTlv);
uint32_t dataLen = 0;
for (uint32_t index = 0; index < count; index++) {
dataLen += data[index].dataLen;
realLen += (data[index].dataType == DATA_TYPE_STRING) ?
APPSPAWN_ALIGN(data[index].dataLen + 1) : APPSPAWN_ALIGN(data[index].dataLen);
}
AppSpawnTlv tlv;
tlv.tlvLen = realLen;
tlv.tlvType = tlvType;
int ret = CheckMsg(reqNode, &tlv, name);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
APPSPAWN_LOGV("AddAppData tlv [%{public}s %{public}u] dataLen: %{public}u start: %{public}u",
name, tlv.tlvLen, dataLen, reqNode->msg->msgLen);
AppSpawnMsgBlock *block = GetValidMsgBlock(reqNode, tlv.tlvLen);
if (block != NULL) {
ret = AddAppDataToBlock(block, (uint8_t *)&tlv, sizeof(tlv), 0);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv for %{public}d", tlvType);
for (uint32_t index = 0; index < count; index++) {
ret = AddAppDataToBlock(block, (uint8_t *)data[index].data, data[index].dataLen, data[index].dataType);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data for %{public}d", tlvType);
}
} else {
ret = AddAppDataToTail(reqNode, (uint8_t *)&tlv, sizeof(tlv), 0);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add tlv to tail for %{public}d", tlvType);
for (uint32_t index = 0; index < count; index++) {
ret = AddAppDataToTail(reqNode, (uint8_t *)data[index].data, data[index].dataLen, data[index].dataType);
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add data for %{public}d", tlvType);
}
}
reqNode->msg->msgLen += tlv.tlvLen;
APPSPAWN_LOGV("AddAppData success tlvType %{public}s end: %{public}u", name, reqNode->msg->msgLen);
return 0;
}
static int SetFlagsTlv(AppSpawnReqMsgNode *reqNode,
AppSpawnMsgBlock *block, AppSpawnMsgFlags **msgFlags, int type, int maxCount)
{
uint32_t units = (uint32_t)CalcFlagsUnits(maxCount);
APPSPAWN_LOGV("SetFlagsTlv maxCount %{public}d type %{public}d units %{public}d", maxCount, type, units);
uint32_t flagsLen = sizeof(AppSpawnTlv) + sizeof(AppSpawnMsgFlags) + sizeof(uint32_t) * units;
APPSPAWN_CHECK((block->blockSize - block->currentIndex) > flagsLen,
return APPSPAWN_BUFFER_NOT_ENOUGH, "Invalid block to set flags tlv type %{public}d", type);
AppSpawnTlv *tlv = (AppSpawnTlv *)(block->buffer + block->currentIndex);
tlv->tlvLen = flagsLen;
tlv->tlvType = type;
*msgFlags = (AppSpawnMsgFlags *)(block->buffer + block->currentIndex + sizeof(AppSpawnTlv));
(*msgFlags)->count = units;
block->currentIndex += flagsLen;
reqNode->msg->msgLen += flagsLen;
reqNode->msg->tlvCount++;
return 0;
}
static int CreateBaseMsg(AppSpawnReqMsgNode *reqNode, uint32_t msgType, const char *processName)
{
AppSpawnMsgBlock *block = CreateAppSpawnMsgBlock(reqNode);
APPSPAWN_CHECK(block != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create block for %{public}s", processName);
reqNode->msg = (AppSpawnMsg *)(block->buffer + block->currentIndex);
reqNode->msg->magic = APPSPAWN_MSG_MAGIC;
reqNode->msg->msgId = 0;
reqNode->msg->msgType = msgType;
reqNode->msg->msgLen = sizeof(AppSpawnMsg);
reqNode->msg->tlvCount = 0;
int ret = strcpy_s(reqNode->msg->processName, sizeof(reqNode->msg->processName), processName);
APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to create block for %{public}s", processName);
block->currentIndex = sizeof(AppSpawnMsg);
ret = SetFlagsTlv(reqNode, block, &reqNode->msgFlags, TLV_MSG_FLAGS, MAX_FLAGS_INDEX);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
APPSPAWN_CHECK_ONLY_EXPER(msgType == MSG_APP_SPAWN || msgType == MSG_SPAWN_NATIVE_PROCESS ||
msgType == MSG_SPAWN_IMAGE_PROCESS || msgType == MSG_SPAWN_WORKER_PROCESS, return 0);
int maxCount = GetPermissionMaxCount();
APPSPAWN_CHECK(maxCount > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid max for permission %{public}s", processName);
ret = SetFlagsTlv(reqNode, block, &reqNode->permissionFlags, TLV_PERMISSION, maxCount);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
APPSPAWN_LOGV("CreateBaseMsg msgLen: %{public}u %{public}u", reqNode->msg->msgLen, block->currentIndex);
return 0;
}
static void DeleteAppSpawnReqMsg(AppSpawnReqMsgNode *reqNode)
{
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return);
APPSPAWN_LOGV("DeleteAppSpawnReqMsg reqId: %{public}u", reqNode->reqId);
reqNode->msgFlags = NULL;
reqNode->permissionFlags = NULL;
reqNode->msg = NULL;
OH_ListRemoveAll(&reqNode->msgBlocks, FreeMsgBlock);
free(reqNode);
}
static AppSpawnReqMsgNode *CreateAppSpawnReqMsg(uint32_t msgType, const char *processName)
{
static uint32_t reqId = 0;
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)malloc(sizeof(AppSpawnReqMsgNode));
APPSPAWN_CHECK(reqNode != NULL, return NULL, "Failed to create msg node for %{public}s", processName);
OH_ListInit(&reqNode->node);
OH_ListInit(&reqNode->msgBlocks);
reqNode->reqId = ++reqId;
reqNode->msg = NULL;
reqNode->msgFlags = NULL;
reqNode->permissionFlags = NULL;
reqNode->fdCount = 0;
reqNode->isColdRun = 0;
int ret = CreateBaseMsg(reqNode, msgType, processName);
APPSPAWN_CHECK(ret == 0, DeleteAppSpawnReqMsg(reqNode);
return NULL, "Failed to create base msg for %{public}s", processName);
APPSPAWN_LOGV("CreateAppSpawnReqMsg reqId: %{public}d msg type: %{public}u processName: %{public}s",
reqNode->reqId, msgType, processName);
return reqNode;
}
int AppSpawnReqMsgAddFd(AppSpawnReqMsgHandle reqHandle, const char* fdName, int fd)
{
APPSPAWN_CHECK(reqHandle != NULL, return APPSPAWN_ARG_INVALID, "Invalid reqHandle");
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK(reqNode != NULL, return APPSPAWN_ARG_INVALID, "Invalid reqNode");
APPSPAWN_CHECK(fd >= 0 && fdName != NULL && strlen(fdName) <= APP_FDNAME_MAXLEN
&& reqNode->fdCount < APP_MAX_FD_COUNT, return APPSPAWN_ARG_INVALID,
"Invalid fdinfo %{public}d %{public}d %{public}d", fd, fdName != NULL, reqNode->fdCount);
reqNode->fds[reqNode->fdCount++] = fd;
return AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_APP_FD, (void *)fdName);
}
APPSPAWN_STATIC void GetSpecialGid(const char *bundleName, gid_t gidTable[], uint32_t *gidCount)
{
const char *specialBundleNames[] = {
"com.ohos.medialibrary.medialibrarydata", "com.ohos.medialibrary.medialibrarydata:backup"
};
for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) {
if (strcmp(bundleName, specialBundleNames[i]) == 0) {
if (*gidCount + 1 < APP_MAX_GIDS) {
gidTable[(*gidCount)++] = GID_USER_DATA_RW;
gidTable[(*gidCount)++] = GID_FILE_ACCESS;
}
break;
}
}
}
int AppSpawnReqMsgCreate(AppSpawnMsgType msgType, const char *processName, AppSpawnReqMsgHandle *reqHandle)
{
APPSPAWN_CHECK(reqHandle != NULL, return APPSPAWN_ARG_INVALID, "Invalid request handle");
APPSPAWN_CHECK(msgType < MAX_TYPE_INVALID,
return APPSPAWN_MSG_INVALID, "Invalid message type %{public}u %{public}s", msgType, processName);
int ret = CheckInputString("processName", processName, APP_LEN_PROC_NAME);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
AppSpawnReqMsgNode *reqNode = CreateAppSpawnReqMsg(msgType, processName);
APPSPAWN_CHECK(reqNode != NULL, return APPSPAWN_SYSTEM_ERROR,
"Failed to create msg node for %{public}s", processName);
*reqHandle = (AppSpawnReqMsgHandle)(reqNode);
return 0;
}
void AppSpawnReqMsgFree(AppSpawnReqMsgHandle reqHandle)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return);
DeleteAppSpawnReqMsg(reqNode);
}
int AppSpawnReqMsgSetAppDacInfo(AppSpawnReqMsgHandle reqHandle, const AppDacInfo *dacInfo)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_ARG_INVALID, "Invalid dacInfo ");
AppDacInfo tmpDacInfo = {0};
(void)memcpy_s(&tmpDacInfo, sizeof(tmpDacInfo), dacInfo, sizeof(tmpDacInfo));
GetSpecialGid(reqNode->msg->processName, tmpDacInfo.gidTable, &tmpDacInfo.gidCount);
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&tmpDacInfo;
data[0].dataLen = sizeof(AppSpawnMsgDacInfo);
return AddAppData(reqNode, TLV_DAC_INFO, data, 1, "TLV_DAC_INFO");
}
int AppSpawnReqMsgSetBundleInfo(AppSpawnReqMsgHandle reqHandle, uint32_t bundleIndex, const char *bundleName)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
int ret = CheckInputString("TLV_BUNDLE_INFO", bundleName, APP_LEN_BUNDLE_NAME);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
AppSpawnMsgBundleInfo info = {};
info.bundleIndex = bundleIndex;
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&info;
data[0].dataLen = sizeof(AppSpawnMsgBundleInfo);
data[1].data = (uint8_t *)bundleName;
data[1].dataLen = strlen(bundleName);
data[1].dataType = DATA_TYPE_STRING;
return AddAppData(reqNode, TLV_BUNDLE_INFO, data, MAX_DATA_IN_TLV, "TLV_BUNDLE_INFO");
}
static bool ShouldEnableColdRun(AppFlagsIndex flagIndex)
{
if (flagIndex == APP_FLAGS_UBSAN_ENABLED ||
flagIndex == APP_FLAGS_ASANENABLED ||
flagIndex == APP_FLAGS_TSAN_ENABLED ||
flagIndex == APP_FLAGS_HWASAN_ENABLED) {
return true;
}
if (flagIndex == APP_FLAGS_COLD_BOOT &&
CheckEnabled("startup.appspawn.cold.boot", "true")) {
return true;
}
if (flagIndex == APP_FLAGS_DEBUG_SIGN &&
CheckEnabled("const.security.developermode.state", "true") &&
CheckEnabled("hiviewdfx.hiprofiler.preload", "1")) {
return true;
}
return false;
}
int AppSpawnReqMsgSetAppFlag(AppSpawnReqMsgHandle reqHandle, AppFlagsIndex flagIndex)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
APPSPAWN_CHECK(reqNode->msgFlags != NULL, return APPSPAWN_ARG_INVALID, "No msg flags tlv");
APPSPAWN_CHECK(flagIndex < MAX_FLAGS_INDEX, return APPSPAWN_ARG_INVALID,
"Invalid msg app flags %{public}d", flagIndex);
if (!reqNode->isColdRun && ShouldEnableColdRun(flagIndex)) {
reqNode->isColdRun = 1;
}
return SetAppSpawnMsgFlags(reqNode->msgFlags, flagIndex);
}
int AppSpawnReqMsgAddExtInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const uint8_t *value, uint32_t valueLen)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
int ret = CheckInputString("check name", name, APPSPAWN_TLV_NAME_LEN);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
APPSPAWN_CHECK(value != NULL && valueLen <= EXTRAINFO_TOTAL_LENGTH_MAX && valueLen > 0,
return APPSPAWN_ARG_INVALID, "Invalid ext value ");
APPSPAWN_LOGV("AppSpawnReqMsgAddExtInfo name %{public}s", name);
AppSpawnAppData data[1] = {};
data[0].data = (uint8_t *)value;
data[0].dataLen = valueLen;
return AddAppDataEx(reqNode, name, data);
}
int AppSpawnReqMsgAddStringInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const char *value)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
int ret = CheckInputString("check name", name, APPSPAWN_TLV_NAME_LEN);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
ret = CheckInputString(name, value, EXTRAINFO_TOTAL_LENGTH_MAX);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
APPSPAWN_LOGV("AppSpawnReqMsgAddStringInfo name %{public}s", name);
AppSpawnAppData data[1] = {};
data[0].data = (uint8_t *)value;
data[0].dataLen = strlen(value);
data[0].dataType = DATA_TYPE_STRING;
return AddAppDataEx(reqNode, name, data);
}
int AppSpawnReqMsgAddPermission(AppSpawnReqMsgHandle reqHandle, const char *permission)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
APPSPAWN_CHECK(permission != NULL, return APPSPAWN_ARG_INVALID, "Invalid permission ");
APPSPAWN_CHECK(reqNode->permissionFlags != NULL, return APPSPAWN_ARG_INVALID, "No permission tlv ");
int32_t maxIndex = GetMaxPermissionIndex(NULL);
int index = GetPermissionIndex(NULL, permission);
APPSPAWN_CHECK(index >= 0 && index < maxIndex,
return APPSPAWN_PERMISSION_NOT_SUPPORT, "Invalid permission %{public}s", permission);
APPSPAWN_LOGV("AddPermission index %{public}d name %{public}s", index, permission);
int ret = SetAppSpawnMsgFlags(reqNode->permissionFlags, index);
APPSPAWN_CHECK(ret == 0, return ret, "Invalid permission %{public}s", permission);
return 0;
}
int AppSpawnReqMsgSetAppDomainInfo(AppSpawnReqMsgHandle reqHandle, uint32_t hapFlags, const char *apl)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
int ret = CheckInputString("TLV_DOMAIN_INFO", apl, APP_APL_MAX_LEN);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
AppSpawnMsgDomainInfo msgDomainInfo;
msgDomainInfo.hapFlags = hapFlags;
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&msgDomainInfo;
data[0].dataLen = sizeof(AppSpawnMsgDomainInfo);
data[1].data = (uint8_t *)apl;
data[1].dataLen = strlen(apl);
data[1].dataType = DATA_TYPE_STRING;
return AddAppData(reqNode, TLV_DOMAIN_INFO, data, MAX_DATA_IN_TLV, "TLV_DOMAIN_INFO");
}
int AppSpawnReqMsgSetAppInternetPermissionInfo(AppSpawnReqMsgHandle reqHandle, uint8_t allow, uint8_t setAllow)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
AppSpawnMsgInternetInfo info = {};
info.allowInternet = allow;
info.setAllowInternet = setAllow;
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&info;
data[0].dataLen = sizeof(AppSpawnMsgInternetInfo);
return AddAppData(reqNode, TLV_INTERNET_INFO, data, 1, "TLV_INTERNET_INFO");
}
int AppSpawnReqMsgSetAppOwnerId(AppSpawnReqMsgHandle reqHandle, const char *ownerId)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
int ret = CheckInputString("TLV_OWNER_INFO", ownerId, APP_OWNER_ID_LEN);
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)ownerId;
data[0].dataLen = strlen(ownerId);
data[0].dataType = DATA_TYPE_STRING;
return AddAppData(reqNode, TLV_OWNER_INFO, data, 1, "TLV_OWNER_INFO");
}
int AppSpawnReqMsgSetAppAccessToken(AppSpawnReqMsgHandle reqHandle, uint64_t accessTokenIdEx)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&accessTokenIdEx;
data[0].dataLen = sizeof(accessTokenIdEx);
return AddAppData(reqNode, TLV_ACCESS_TOKEN_INFO, data, 1, "TLV_ACCESS_TOKEN_INFO");
}
int AppSpawnTerminateMsgCreate(pid_t pid, AppSpawnReqMsgHandle *reqHandle)
{
APPSPAWN_CHECK(reqHandle != NULL, return APPSPAWN_ARG_INVALID, "Invalid request handle");
AppSpawnReqMsgNode *reqNode = CreateAppSpawnReqMsg(MSG_GET_RENDER_TERMINATION_STATUS, "terminate-process");
APPSPAWN_CHECK(reqNode != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create msg node");
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&pid;
data[0].dataLen = sizeof(pid);
int ret = AddAppData(reqNode, TLV_RENDER_TERMINATION_INFO, data, 1, "TLV_RENDER_TERMINATION_INFO");
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, DeleteAppSpawnReqMsg(reqNode);
return ret);
*reqHandle = (AppSpawnReqMsgHandle)(reqNode);
return 0;
}
int AppSpawnClientAddPermission(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle, const char *permission)
{
AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle;
APPSPAWN_CHECK(reqMgr != NULL, return APPSPAWN_ARG_INVALID, "Invalid reqMgr");
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL, return APPSPAWN_ARG_INVALID);
APPSPAWN_CHECK(permission != NULL, return APPSPAWN_ARG_INVALID, "Invalid permission ");
APPSPAWN_CHECK(reqNode->permissionFlags != NULL, return APPSPAWN_ARG_INVALID, "No permission tlv ");
if (strcmp(permission, OHOS_PERMISSION_FOWNER) == 0) {
APPSPAWN_LOGI("AppSpawnClientAddPermission %{public}s", permission);
return AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_SET_CAPS_FOWNER);
}
#ifdef APPSPAWN_SANDBOX_NEW
if (reqMgr->type == CLIENT_FOR_NWEBSPAWN) {
return 0;
}
#endif
int32_t maxIndex = GetMaxPermissionIndex(handle);
int index = GetPermissionIndex(handle, permission);
APPSPAWN_CHECK(index >= 0 && index < maxIndex,
return APPSPAWN_PERMISSION_NOT_SUPPORT, "Invalid permission %{public}s", permission);
APPSPAWN_LOGV("add permission index %{public}d name %{public}s", index, permission);
int ret = SetAppSpawnMsgFlags(reqNode->permissionFlags, index);
APPSPAWN_CHECK(ret == 0, return ret, "Invalid permission %{public}s", permission);
return 0;
}
int AppSpawnReqMsgSetCheckpointInfo(AppSpawnReqMsgHandle reqHandle, pid_t imgPid,
uint64_t checkPointId, const char *imgName)
{
AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
APPSPAWN_CHECK_ONLY_EXPER(reqNode != NULL && imgPid > 0, return APPSPAWN_ARG_INVALID);
AppSpawnCheckpointInfo checkpointInfo = {};
checkpointInfo.imgPid = imgPid;
checkpointInfo.checkPointId = checkPointId;
if (imgName != NULL) {
int ret = strcpy_s(checkpointInfo.imgName, APP_CHECKPOINT_NAME_LEN, imgName);
APPSPAWN_CHECK(ret == 0, return APPSPAWN_ARG_INVALID,
"Failed to copy imgName: %{public}s", imgName);
}
AppSpawnAppData data[MAX_DATA_IN_TLV] = {};
data[0].data = (uint8_t *)&checkpointInfo;
data[0].dataLen = sizeof(AppSpawnCheckpointInfo);
return AddAppData(reqNode, TLV_CHECK_POINT_INFO, data, 1, "TLV_CHECKPOINT_INFO");
}