Files
ability_dmsfwk_lite/source/dmslite_parser.c
T
wangyang2022 3b86853e08 安全排查,修改文件权限为644
Signed-off-by: wangyang2022 <wangyang412@huawei.com>
Change-Id: I0a8546086cc167899c2eb3771e31a41f36ce1063
2022-09-15 17:24:22 +08:00

295 lines
8.8 KiB
C

/*
* Copyright (c) 2020 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 "dmslite_parser.h"
#include <stdlib.h>
#include <unistd.h>
#include "dmsfwk_interface.h"
#include "dmslite_log.h"
#include "dmslite_msg_handler.h"
#include "dmslite_tlv_common.h"
#include "securec.h"
#define MIN_VALID_NODES 2
#define HIGH_BIT_MASK 0xFF
#define LOW_BIT_MASK 0x7F
#define TLV_LENGTH_SHIFT_BITS 7
#define BREAK_IF_FAILURE(errCode); \
if ((errCode) != DMS_TLV_SUCCESS) { \
break; \
} \
static inline bool IsNextTlvLength(uint8_t num)
{
/* 128-16383 : 0b1xxxxxxx 0b0xxxxxxx */
return (((num) & HIGH_BIT_MASK) >> TLV_LENGTH_SHIFT_BITS) == 0x00;
}
static inline void TlvByteToLength(uint8_t byte, uint16_t *len)
{
*len = ((*len) << TLV_LENGTH_SHIFT_BITS) | (byte & LOW_BIT_MASK);
}
static TlvErrorCode TlvBytesToLength(const uint8_t *bytesBuffer, uint16_t bufLength,
uint16_t *length, uint8_t *bytesNumber)
{
uint8_t bytesNum = 0;
uint16_t len = 0;
/* compute TLV's L, when value > 127, the L should be two bytes, else L is one byte long
0-127 : 0b0xxxxxxx
128-16383 : 0b1xxxxxxx 0b0xxxxxxx */
for (uint8_t i = 0; i < bufLength; i++) {
TlvByteToLength(bytesBuffer[i], &len);
bytesNum++;
if (IsNextTlvLength(bytesBuffer[i])) {
HILOGD("[bytesNum = %hhu, byte = %x]", bytesNum, bytesBuffer[i]);
break;
}
if (bytesNum >= TLV_MAX_LENGTH_BYTES) {
return DMS_TLV_ERR_LEN;
}
}
/* it is meaningless to have a node with length being zero */
if (len == 0) {
HILOGE("[Invalid zero-size length]");
return DMS_TLV_ERR_LEN;
}
*length = len;
*bytesNumber = bytesNum;
return DMS_TLV_SUCCESS;
}
static TlvErrorCode TlvFillNode(const uint8_t *byteBuffer, uint16_t bufLength,
TlvNode *node, uint16_t *actualHandledLen)
{
if (bufLength <= TLV_TYPE_LEN) {
HILOGE("[Bad bufLength %hu]", bufLength);
return DMS_TLV_ERR_LEN;
}
/* fill TLV's T(type) */
node->type = *byteBuffer;
uint16_t curTlvNodeLen = TLV_TYPE_LEN;
/* fill TLV's L(length) */
uint16_t length = 0;
uint8_t bytesNum = 0;
const uint8_t *lengthPartAddr = byteBuffer + curTlvNodeLen;
TlvErrorCode errCode = TlvBytesToLength(lengthPartAddr, bufLength - curTlvNodeLen,
&length, &bytesNum);
if (errCode != DMS_TLV_SUCCESS) {
return DMS_TLV_ERR_LEN;
}
node->length = length;
curTlvNodeLen += bytesNum;
/* fill TLV's V(value) */
node->value = byteBuffer + curTlvNodeLen;
curTlvNodeLen += length;
if (curTlvNodeLen > bufLength) {
return DMS_TLV_ERR_LEN;
} else {
*actualHandledLen = curTlvNodeLen;
}
return DMS_TLV_SUCCESS;
}
static void TlvFreeNodeList(TlvNode *node)
{
TlvNode *next = NULL;
while (node != NULL) {
next = node->next;
free(node);
node = next;
}
}
static inline TlvNode* MallocTlvNode()
{
TlvNode *node = (TlvNode *)malloc(sizeof(TlvNode));
if (node == NULL) {
HILOGE("[Out of memory]");
return NULL;
}
/* won't fail */
(void) memset_s(node, sizeof(TlvNode), 0x00, sizeof(TlvNode));
return node;
}
static inline TlvErrorCode CheckNodeSequence(const TlvNode *lastNode, const TlvNode *curNode)
{
if (lastNode == curNode) {
return DMS_TLV_SUCCESS;
}
if (lastNode->type >= curNode->type) {
HILOGE("[Bad node type sequence '%hhu' is expected but '%hhu' appears]",
lastNode->type, curNode->type);
return DMS_TLV_ERR_OUT_OF_ORDER;
}
return DMS_TLV_SUCCESS;
}
static inline TlvErrorCode MoveToNextTlvNode(TlvNode **curNode)
{
TlvNode *next = MallocTlvNode();
if (next == NULL) {
return DMS_TLV_ERR_NO_MEM;
}
(*curNode)->next = next;
*curNode = next;
return DMS_TLV_SUCCESS;
}
TlvErrorCode TlvBytesToNode(const uint8_t *byteBuffer, uint16_t bufLength, TlvNode **tlv)
{
if ((tlv == NULL) || (byteBuffer == NULL)) {
HILOGE("[Bad parameter]");
return DMS_TLV_ERR_PARAM;
}
/* bufLength is longer than TLV_TYPE_LEN + 1(means length should be at least 1 byte) */
if (bufLength <= (TLV_TYPE_LEN + 1)) {
HILOGE("[Bad Length %hu]", bufLength);
return DMS_TLV_ERR_LEN;
}
TlvNode *head = MallocTlvNode();
if (head == NULL) {
return DMS_TLV_ERR_NO_MEM;
}
TlvNode *curNode = head;
TlvNode *lastNode = curNode;
/* translate bytes to tlv node until the end of buffer */
uint16_t remainingLen = bufLength;
uint8_t handledNodeNum = 0;
const uint8_t *nodeStartAddr = byteBuffer;
TlvErrorCode errCode = DMS_TLV_SUCCESS;
while (true) {
uint16_t curTlvNodeLen = 0;
errCode = TlvFillNode(nodeStartAddr, remainingLen, curNode, &curTlvNodeLen);
BREAK_IF_FAILURE(errCode);
/* check whether there is need to continue processing the remaining nodes */
handledNodeNum++;
/* check node type sequence: the type of node must appear in strictly increasing order */
errCode = CheckNodeSequence(lastNode, curNode);
BREAK_IF_FAILURE(errCode);
remainingLen -= curTlvNodeLen;
if (remainingLen == 0) {
break;
}
HILOGD("[curNode length:%hu type:%hhu handledNodeNum:%hhu]", curNode->length,
curNode->type, handledNodeNum);
/* if all is ok, then move to the T part of the next tlv node */
nodeStartAddr += curTlvNodeLen;
lastNode = curNode;
errCode = MoveToNextTlvNode(&curNode);
BREAK_IF_FAILURE(errCode);
}
if (errCode == DMS_TLV_SUCCESS && handledNodeNum < MIN_VALID_NODES) {
HILOGE("[Parse done, but node num is invalid]");
errCode = DMS_TLV_ERR_BAD_NODE_NUM;
}
if (errCode != DMS_TLV_SUCCESS) {
TlvFreeNodeList(head);
head = NULL;
}
*tlv = head;
return errCode;
}
static int32_t Parse(const uint8_t *payload, uint16_t length, TlvNode **head)
{
if (length > MAX_DMS_MSG_LENGTH) {
HILOGE("[Bad parameters][length = %hu]", length);
return DMS_TLV_ERR_PARAM;
}
TlvNode *tlvHead = NULL;
TlvErrorCode errCode = TlvBytesToNode(payload, length, &tlvHead);
*head = tlvHead;
HILOGI("[errCode = %d]", errCode);
return errCode;
}
static bool CanCall()
{
#ifndef WEARABLE_PRODUCT
uid_t callerUid = getuid();
/* only foundation and xts (shell-enabled mode only) is reasonable to call ProcessCommuMsg directly */
if (callerUid != FOUNDATION_UID && callerUid != SHELL_UID) {
HILOGD("[Caller uid is not allowed, uid = %u]", callerUid);
return false;
}
#endif
return true;
}
int32_t ProcessCommuMsg(const CommuMessage *commuMessage, const IDmsFeatureCallback *dmsFeatureCallback)
{
if (!CanCall()) {
return DMS_EC_FAILURE;
}
if (commuMessage == NULL || commuMessage->payload == NULL || dmsFeatureCallback == NULL) {
return DMS_EC_FAILURE;
}
TlvNode *tlvHead = NULL;
int32_t errCode = Parse(commuMessage->payload, commuMessage->payloadLength, &tlvHead);
/* mainly for xts testsuit convenient, in non-test mode the onTlvParseDone should be set NULL */
if (dmsFeatureCallback->onTlvParseDone != NULL) {
dmsFeatureCallback->onTlvParseDone(errCode, tlvHead);
}
if (errCode != DMS_TLV_SUCCESS) {
return DMS_EC_PARSE_TLV_FAILURE;
}
uint16_t commandId = UnMarshallUint16(tlvHead, COMMAND_ID);
HILOGI("[ProcessCommuMsg commandId %hu]", commandId);
switch (commandId) {
case DMS_MSG_CMD_START_FA: {
errCode = StartAbilityFromRemoteHandler(tlvHead, dmsFeatureCallback->onStartAbilityDone);
break;
}
case DMS_MSG_CMD_REPLY: {
errCode = ReplyMsgHandler(tlvHead);
break;
}
default: {
HILOGW("[Unknown command id %hu]", commandId);
errCode = DMS_EC_UNKNOWN_COMMAND_ID;
break;
}
}
TlvFreeNodeList(tlvHead);
return errCode;
}