feat: L0~L1 支持Lms

1.【需求描述】:
   支持内核态和用户态堆内存非法访问检测,包括:越界访问、double free、释放后使用;支持libc常用高频函数内存检测;支持安全函数内存检测;读写检测可配可裁剪。
2.【方案描述】:
   L0 ~ L1:
   (1).影子内存映射与标记
   (2).编译器使能-fsanitize=kernel-address 自动插桩检测点
   (3).实时校验影子内存的合法性;
   (4).错误访问打印回溯栈

BREAKING CHANGE: 新增支持API:

LOS_LmsCheckPoolAdd使能检测指定内存池
LOS_LmsCheckPoolDel不检测指定内存池
LOS_LmsAddrProtect为指定内存段上锁,不允许访问
LOS_LmsAddrDisableProtect去能指定内存段的访问保护

Close #I4HYAV

Signed-off-by: LiteOS2021 <dinglu@huawei.com>
Change-Id: Id8e5c890656da9edc4a22227e6a3c32205c024ce
This commit is contained in:
LiteOS2021
2021-11-27 09:56:51 +08:00
parent 48f645db84
commit e748fdbe57
26 changed files with 2695 additions and 21 deletions
+43
View File
@@ -0,0 +1,43 @@
# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
module_switch = defined(LOSCFG_KERNEL_LMS)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"lms_libc.c",
"los_lms.c",
]
}
config("public") {
include_dirs = [ "." ]
}
+41
View File
@@ -0,0 +1,41 @@
config KERNEL_LMS
bool "Enable Lite Memory Sanitizer"
default n
depends on KERNEL_EXTKERNEL && DEBUG_VERSION && LIB_LIBC
help
Select y to build LiteOS with memory sanitizer.
config LMS_MAX_RECORD_POOL_NUM
int "Lms check pool max num"
default 50
depends on KERNEL_LMS
help
The Max num of lms check pool
config LMS_LOAD_CHECK
bool "Enable lms read check"
default y
depends on KERNEL_LMS
help
Select y to enable read check.
config LMS_STORE_CHECK
bool "Enable lms write check"
default y
depends on KERNEL_LMS
help
Select y to enable write check.
config LMS_CHECK_STRICT
bool "Enable lms strict check, byte-by-byte"
default n
depends on KERNEL_LMS
help
Select y to enable byte-by-byte check in lms
config LMS_LIBC_FULL_CHECK
bool "Enable libc all function do lms check"
default n
depends on KERNEL_LMS
help
Select y to enable libc full check
+10
View File
@@ -0,0 +1,10 @@
include $(LITEOSTOPDIR)/config.mk
MODULE_NAME := $(notdir $(shell pwd))
LOCAL_SRCS := $(wildcard *.c)
LOCAL_FLAGS := $(LOCAL_INCLUDE)
include $(MODULE)
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "string.h"
#include "los_lms_pri.h"
#undef memset
void *memset(void *addr, int c, size_t len)
{
__asan_storeN_noabort((UINTPTR)addr, len);
return __memset(addr, c, len);
}
#undef memmove
void *memmove(void *dest, const void *src, size_t len)
{
__asan_loadN_noabort((UINTPTR)src, len);
__asan_storeN_noabort((UINTPTR)dest, len);
return __memmove(dest, src, len);
}
#undef memcpy
void *memcpy(void *dest, const void *src, size_t len)
{
__asan_loadN_noabort((UINTPTR)src, len);
__asan_storeN_noabort((UINTPTR)dest, len);
return __memcpy(dest, src, len);
}
#undef strcat
char *strcat (char *s, const char *append)
{
if ((s == NULL) || (append == NULL)) {
return NULL;
}
CHAR *end = s;
size_t len = strlen(append);
for (; *end != '\0'; ++end) {
}
__asan_storeN_noabort((UINTPTR)end, len + 1);
__asan_loadN_noabort((UINTPTR)append, len + 1);
return __strcat(s, append);
}
#undef strcpy
char *strcpy(char *dest, const char *src)
{
if ((dest == NULL) || (src == NULL)) {
return NULL;
}
size_t len = strlen(src);
__asan_storeN_noabort((UINTPTR)dest, len + 1);
__asan_loadN_noabort((UINTPTR)src, len + 1);
return __strcpy(dest, src);
}
#undef strncat
char *strncat(char *dest, const char *src, size_t n)
{
if ((dest == NULL) || (src == NULL)) {
return NULL;
}
CHAR *end = dest;
size_t len = strlen(src);
size_t size = len > n ? n : len;
for (; *end != '\0'; ++end) {
}
__asan_storeN_noabort((UINTPTR)end, size + 1);
__asan_loadN_noabort((UINTPTR)src, size + 1);
return __strncat(dest, src, n);
}
#undef strncpy
char *strncpy(char *dest, const char *src, size_t n)
{
if ((dest == NULL) || (src == NULL)) {
return NULL;
}
size_t len = strlen(src);
size_t size = len > n ? n : len;
__asan_storeN_noabort((UINTPTR)dest, n);
__asan_loadN_noabort((UINTPTR)src, size + 1);
return __strncpy(dest, src, n);
}
+769
View File
@@ -0,0 +1,769 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_lms_pri.h"
#include "los_spinlock.h"
#include "los_exc.h"
#include "los_sched_pri.h"
#include "los_atomic.h"
#include "los_init.h"
LITE_OS_SEC_BSS STATIC LmsMemListNode g_lmsCheckPoolArray[LOSCFG_LMS_MAX_RECORD_POOL_NUM];
LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_lmsCheckPoolList;
STATIC Atomic g_checkDepth = 0;
LmsHook *g_lms = NULL;
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_lmsSpin);
#define LMS_LOCK(state) LOS_SpinLockSave(&g_lmsSpin, &(state))
#define LMS_UNLOCK(state) LOS_SpinUnlockRestore(&g_lmsSpin, (state))
#define OS_MEM_ALIGN_BACK(value, align) (((UINT32)(value)) & ~((UINT32)((align) - 1)))
#define OS_MEM_ALIGN_SIZE sizeof(UINTPTR)
#define POOL_ADDR_ALIGNSIZE 64
#define LMS_POOL_UNUSED 0
#define LMS_POOL_USED 1
#define INVALID_SHADOW_VALUE 0xFFFFFFFF
STATIC UINT32 OsLmsPoolResize(UINT32 size)
{
return OS_MEM_ALIGN_BACK(LMS_POOL_RESIZE(size), POOL_ADDR_ALIGNSIZE);
}
STATIC LmsMemListNode *OsLmsGetPoolNode(const VOID *pool)
{
UINTPTR poolAddr = (UINTPTR)pool;
LmsMemListNode *current = NULL;
LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
if (LOS_ListEmpty(&g_lmsCheckPoolList)) {
goto EXIT;
}
LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
if (current->poolAddr == poolAddr) {
return current;
}
}
EXIT:
return NULL;
}
STATIC LmsMemListNode *OsLmsGetPoolNodeFromAddr(UINTPTR addr)
{
LmsMemListNode *current = NULL;
LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
if (LOS_ListEmpty(&g_lmsCheckPoolList)) {
goto EXIT;
}
LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
if ((addr >= current->poolAddr) && (addr < current->poolAddr + current->poolSize)) {
return current;
}
}
EXIT:
return NULL;
}
STATIC LmsMemListNode *OsLmsCheckPoolCreate(VOID)
{
UINT32 i;
LmsMemListNode *current = NULL;
for (i = 0; i < LOSCFG_LMS_MAX_RECORD_POOL_NUM; i++) {
current = &g_lmsCheckPoolArray[i];
if (current->used == LMS_POOL_UNUSED) {
current->used = LMS_POOL_USED;
return current;
}
}
return NULL;
}
UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size)
{
UINT32 intSave;
UINTPTR poolAddr = (UINTPTR)pool;
UINT32 realSize;
LmsMemListNode *lmsPoolNode = NULL;
if (pool == NULL) {
return 0;
}
LMS_LOCK(intSave);
lmsPoolNode = OsLmsGetPoolNodeFromAddr((UINTPTR)pool);
if (lmsPoolNode != NULL) { /* if pool range already on checklist */
if (lmsPoolNode->poolAddr != (UINTPTR)pool) { /* pool is a subset of lmsPoolNode->poolAddr */
/* do not add it again, just return */
PRINT_DEBUG("[LMS]pool %p already on lms checklist !\n", pool);
LMS_UNLOCK(intSave);
return size; /* return size indicate the shadow memory init successful */
} else { /* Re-initialize the same pool, maybe with different size */
/* delete the old node, then add a new one */
lmsPoolNode->used = LMS_POOL_UNUSED;
LOS_ListDelete(&(lmsPoolNode->node));
}
}
lmsPoolNode = OsLmsCheckPoolCreate();
if (lmsPoolNode == NULL) {
PRINT_DEBUG("[LMS]the num of lms check pool is max already !\n");
LMS_UNLOCK(intSave);
return 0;
}
realSize = OsLmsPoolResize(size);
lmsPoolNode->poolAddr = poolAddr;
lmsPoolNode->poolSize = realSize;
lmsPoolNode->shadowStart = (UINTPTR)poolAddr + realSize;
lmsPoolNode->shadowSize = poolAddr + size - lmsPoolNode->shadowStart;
/* init shadow value */
(VOID)memset((VOID *)lmsPoolNode->shadowStart, LMS_SHADOW_AFTERFREE_U8, lmsPoolNode->shadowSize);
LOS_ListAdd(&g_lmsCheckPoolList, &(lmsPoolNode->node));
LMS_UNLOCK(intSave);
return realSize;
}
VOID LOS_LmsCheckPoolDel(const VOID *pool)
{
UINT32 intSave;
if (pool == NULL) {
return;
}
LMS_LOCK(intSave);
LmsMemListNode *delNode = OsLmsGetPoolNode(pool);
if (delNode == NULL) {
PRINT_ERR("[LMS]pool %p is not on lms checklist !\n", pool);
goto Release;
}
delNode->used = LMS_POOL_UNUSED;
LOS_ListDelete(&(delNode->node));
Release:
LMS_UNLOCK(intSave);
}
STATIC UINT32 OsLmsInit(VOID)
{
(VOID)memset(g_lmsCheckPoolArray, 0, sizeof(g_lmsCheckPoolArray));
LOS_ListInit(&g_lmsCheckPoolList);
static LmsHook hook = {
.init = LOS_LmsCheckPoolAdd,
.mallocMark = OsLmsLosMallocMark,
.freeMark = OsLmsLosFreeMark,
.simpleMark = OsLmsSimpleMark,
.check = OsLmsCheckValid,
};
g_lms = &hook;
return LOS_OK;
}
STATIC INLINE UINT32 OsLmsMem2Shadow(LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset)
{
if ((memAddr < node->poolAddr) || (memAddr >= node->poolAddr + node->poolSize)) { /* check ptr valid */
PRINT_ERR("[LMS]memAddr %p is not in pool region [%p, %p)\n", memAddr, node->poolAddr,
node->poolAddr + node->poolSize);
return LOS_NOK;
}
UINT32 memOffset = memAddr - node->poolAddr;
*shadowAddr = node->shadowStart + memOffset / LMS_SHADOW_U8_REFER_BYTES;
*shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) *
LMS_SHADOW_BITS_PER_CELL; /* (memOffset % 16) / 4 */
return LOS_OK;
}
STATIC INLINE VOID OsLmsGetShadowInfo(LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info)
{
UINTPTR shadowAddr;
UINT32 shadowOffset;
UINT32 shadowValue;
if (OsLmsMem2Shadow(node, memAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
return;
}
shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
info->memAddr = memAddr;
info->shadowAddr = shadowAddr;
info->shadowOffset = shadowOffset;
info->shadowValue = shadowValue;
}
VOID OsLmsSetShadowValue(LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value)
{
UINTPTR shadowStart;
UINTPTR shadowEnd;
UINT32 startOffset;
UINT32 endOffset;
UINT8 shadowValueMask;
UINT8 shadowValue;
/* endAddr -1, then we mark [startAddr, endAddr) to value */
if (OsLmsMem2Shadow(node, startAddr, &shadowStart, &startOffset) ||
OsLmsMem2Shadow(node, endAddr - 1, &shadowEnd, &endOffset)) {
return;
}
if (shadowStart == shadowEnd) { /* in the same u8 */
/* because endAddr - 1, the endOffset falls into the previous cell,
so endOffset + 2 is required for calculation */
shadowValueMask = LMS_SHADOW_MASK_U8;
shadowValueMask =
(shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)));
shadowValue = value & shadowValueMask;
*(UINT8 *)shadowStart &= ~shadowValueMask;
*(UINT8 *)shadowStart |= shadowValue;
} else {
/* Adjust startAddr to left util it reach the beginning of a u8 */
if (startOffset > 0) {
shadowValueMask = LMS_SHADOW_MASK_U8;
shadowValueMask = shadowValueMask << startOffset;
shadowValue = value & shadowValueMask;
*(UINT8 *)shadowStart &= ~shadowValueMask;
*(UINT8 *)shadowStart |= shadowValue;
shadowStart += 1;
}
/* Adjust endAddr to right util it reach the end of a u8 */
if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) {
shadowValueMask = LMS_SHADOW_MASK_U8;
shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL));
shadowValue = value & shadowValueMask;
*(UINT8 *)shadowEnd &= ~shadowValueMask;
*(UINT8 *)shadowEnd |= shadowValue;
shadowEnd -= 1;
}
if (shadowEnd + 1 > shadowStart) {
(VOID)memset((VOID *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart);
}
}
}
VOID OsLmsGetShadowValue(LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue)
{
UINTPTR shadowAddr;
UINT32 shadowOffset;
if (OsLmsMem2Shadow(node, addr, &shadowAddr, &shadowOffset) != LOS_OK) {
return;
}
*shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
}
VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
{
UINT32 intSave;
if (endAddr <= startAddr) {
PRINT_DEBUG("[LMS]mark 0x%x, 0x%x, 0x%x\n", startAddr, endAddr, (UINTPTR)__builtin_return_address(0));
return;
}
if (!IS_ALIGNED(startAddr, OS_MEM_ALIGN_SIZE) || !IS_ALIGNED(endAddr, OS_MEM_ALIGN_SIZE)) {
PRINT_ERR("[LMS]mark addr is not aligned! 0x%x, 0x%x\n", startAddr, endAddr);
return;
}
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(startAddr);
if (node == NULL) {
LMS_UNLOCK(intSave);
return;
}
OsLmsSetShadowValue(node, startAddr, endAddr, value);
LMS_UNLOCK(intSave);
}
VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
{
UINT32 intSave;
UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
if (node == NULL) {
LMS_UNLOCK(intSave);
return;
}
OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_ACCESSABLE_U8);
OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
LMS_UNLOCK(intSave);
}
VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck)
{
UINT32 intSave;
UINT32 shadowValue = INVALID_SHADOW_VALUE;
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(checkAddr);
if (node == NULL) {
LMS_UNLOCK(intSave);
return;
}
OsLmsGetShadowValue(node, checkAddr, &shadowValue);
LMS_UNLOCK(intSave);
if ((shadowValue == LMS_SHADOW_ACCESSABLE) || ((isFreeCheck) && (shadowValue == LMS_SHADOW_PAINT))) {
return;
}
OsLmsReportError(checkAddr, MEM_REGION_SIZE_1, isFreeCheck ? FREE_ERRORMODE : COMMON_ERRMODE);
}
VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
{
UINT32 intSave;
UINT32 shadowValue = INVALID_SHADOW_VALUE;
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
if (node == NULL) {
LMS_UNLOCK(intSave);
return;
}
UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
OsLmsGetShadowValue(node, curNodeStartAddr + nodeHeadSize, &shadowValue);
if ((shadowValue != LMS_SHADOW_ACCESSABLE) && (shadowValue != LMS_SHADOW_PAINT)) {
LMS_UNLOCK(intSave);
OsLmsReportError(curNodeStartAddr + nodeHeadSize, MEM_REGION_SIZE_1, FREE_ERRORMODE);
return;
}
if (*((UINT8 *)curNodeStart) == 0) { /* if merge the node has memset with 0 */
OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
}
OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_AFTERFREE_U8);
if (*((UINT8 *)nextNodeStart) == 0) { /* if merge the node has memset with 0 */
OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
}
LMS_UNLOCK(intSave);
}
VOID LOS_LmsAddrProtect(UINTPTR addrStart, UINTPTR addrEnd)
{
UINT32 intSave;
if (addrEnd <= addrStart) {
return;
}
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
if (node != NULL) {
OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_REDZONE_U8);
}
LMS_UNLOCK(intSave);
}
VOID LOS_LmsAddrDisableProtect(UINTPTR addrStart, UINTPTR addrEnd)
{
UINT32 intSave;
if (addrEnd <= addrStart) {
return;
}
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
if (node != NULL) {
OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_ACCESSABLE_U8);
}
LMS_UNLOCK(intSave);
}
STATIC UINT32 OsLmsCheckAddr(UINTPTR addr)
{
UINT32 intSave;
UINT32 shadowValue = INVALID_SHADOW_VALUE;
/* do not check nested or before all cpu start */
if ((LOS_AtomicRead(&g_checkDepth)) || (!OS_SCHEDULER_ALL_ACTIVE)) {
return 0;
}
LMS_LOCK(intSave);
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr);
if (node == NULL) {
LMS_UNLOCK(intSave);
return LMS_SHADOW_ACCESSABLE_U8;
}
OsLmsGetShadowValue(node, addr, &shadowValue);
LMS_UNLOCK(intSave);
return shadowValue;
}
#ifdef LOSCFG_LMS_CHECK_STRICT
STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
{
UINT32 i;
for (i = 0; i < size; i++) {
if (OsLmsCheckAddr(addr + i)) {
return LOS_NOK;
}
}
return LOS_OK;
}
#else
STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
{
if (OsLmsCheckAddr(addr) || OsLmsCheckAddr(addr + size - 1)) {
return LOS_NOK;
} else {
return LOS_OK;
}
}
#endif
VOID OsLmsPrintPoolListInfo(VOID)
{
UINT32 count = 0;
UINT32 intSave;
LmsMemListNode *current = NULL;
LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
LMS_LOCK(intSave);
LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node)
{
count++;
PRINT_DEBUG(
"[LMS]memory pool[%1u]: totalsize 0x%-8x memstart 0x%-8x memstop 0x%-8x memsize 0x%-8x shadowstart 0x%-8x "
"shadowSize 0x%-8x\n",
count, current->poolSize + current->shadowSize, current->poolAddr, current->poolAddr + current->poolSize,
current->poolSize, current->shadowStart, current->shadowSize);
}
LMS_UNLOCK(intSave);
}
VOID OsLmsPrintMemInfo(UINTPTR addr)
{
#define LMS_DUMP_OFFSET 16
#define LMS_DUMP_RANGE_DOUBLE 2
PRINTK("\n[LMS] Dump info around address [0x%8x]:\n", addr);
const UINT32 printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1;
const UINT32 printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE;
UINTPTR dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX;
UINT32 shadowValue = 0;
UINTPTR shadowAddr = 0;
UINT32 shadowOffset = 0;
LmsMemListNode *nodeInfo = NULL;
INT32 isCheckAddr, x, y;
nodeInfo = OsLmsGetPoolNodeFromAddr(addr);
if (nodeInfo == NULL) {
PRINT_ERR("[LMS]addr is not in checkpool\n");
return;
}
for (y = 0; y < printY; y++, dumpAddr += printX) {
if (dumpAddr < nodeInfo->poolAddr) { /* find util dumpAddr in pool region */
continue;
}
if ((dumpAddr + printX) >=
nodeInfo->poolAddr + nodeInfo->poolSize) { /* finish if dumpAddr exceeds pool's upper region */
goto END;
}
PRINTK("\n\t[0x%x]: ", dumpAddr);
for (x = 0; x < printX; x++) {
if ((dumpAddr + x) == addr) {
PRINTK("[%02x]", *(UINT8 *)(dumpAddr + x));
} else {
PRINTK(" %02x ", *(UINT8 *)(dumpAddr + x));
}
}
if (OsLmsMem2Shadow(nodeInfo, dumpAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
goto END;
}
PRINTK("|\t[0x%x | %2u]: ", shadowAddr, shadowOffset);
for (x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) {
OsLmsGetShadowValue(nodeInfo, dumpAddr + x, &shadowValue);
isCheckAddr = dumpAddr + x - (UINTPTR)addr + LMS_MEM_BYTES_PER_SHADOW_CELL;
if ((isCheckAddr > 0) && (isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL)) {
PRINTK("[%1x]", shadowValue);
} else {
PRINTK(" %1x ", shadowValue);
}
}
}
END:
PRINTK("\n");
}
STATIC VOID OsLmsGetErrorInfo(UINTPTR addr, UINT32 size, LmsAddrInfo *info)
{
LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr);
OsLmsGetShadowInfo(node, addr, info);
if (info->shadowValue != LMS_SHADOW_ACCESSABLE_U8) {
return;
} else {
OsLmsGetShadowInfo(node, addr + size - 1, info);
}
}
STATIC VOID OsLmsPrintErrInfo(LmsAddrInfo *info, UINT32 errMod)
{
switch (info->shadowValue) {
case LMS_SHADOW_AFTERFREE:
PRINT_ERR("Use after free error detected\n");
break;
case LMS_SHADOW_REDZONE:
PRINT_ERR("Heap buffer overflow error detected\n");
break;
case LMS_SHADOW_ACCESSABLE:
PRINT_ERR("No error\n");
break;
default:
PRINT_ERR("UnKnown Error detected\n");
break;
}
switch (errMod) {
case FREE_ERRORMODE:
PRINT_ERR("Illegal Double free address at: [0x%lx]\n", info->memAddr);
break;
case LOAD_ERRMODE:
PRINT_ERR("Illegal READ address at: [0x%lx]\n", info->memAddr);
break;
case STORE_ERRMODE:
PRINT_ERR("Illegal WRITE address at: [0x%lx]\n", info->memAddr);
break;
case COMMON_ERRMODE:
PRINT_ERR("Common Error at: [0x%lx]\n", info->memAddr);
break;
default:
PRINT_ERR("UnKnown Error mode at: [0x%lx]\n", info->memAddr);
break;
}
PRINT_ERR("Shadow memory address: [0x%lx : %1u] Shadow memory value: [%u] \n", info->shadowAddr,
info->shadowOffset, info->shadowValue);
}
VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod)
{
UINT32 intSave;
LmsAddrInfo info;
(VOID)LOS_AtomicAdd(&g_checkDepth, 1);
LMS_LOCK(intSave);
(VOID)memset(&info, 0, sizeof(LmsAddrInfo));
PRINT_ERR("***** Kernel Address Sanitizer Error Detected Start *****\n");
OsLmsGetErrorInfo(p, size, &info);
OsLmsPrintErrInfo(&info, errMod);
OsBackTrace();
OsLmsPrintMemInfo(info.memAddr);
LMS_UNLOCK(intSave);
PRINT_ERR("***** Kernel Address Sanitizer Error Detected End *****\n");
(VOID)LOS_AtomicSub(&g_checkDepth, 1);
}
#ifdef LOSCFG_LMS_STORE_CHECK
VOID __asan_store1_noabort(UINTPTR p)
{
if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) {
OsLmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE);
}
}
VOID __asan_store2_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE);
}
}
VOID __asan_store4_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE);
}
}
VOID __asan_store8_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE);
}
}
VOID __asan_store16_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE);
}
}
VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
{
if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
OsLmsReportError(p, size, STORE_ERRMODE);
}
}
#else
VOID __asan_store1_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_store2_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_store4_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_store8_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_store16_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
{
(VOID)p;
(VOID)size;
}
#endif
#ifdef LOSCFG_LMS_LOAD_CHECK
VOID __asan_load1_noabort(UINTPTR p)
{
if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) {
OsLmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE);
}
}
VOID __asan_load2_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE);
}
}
VOID __asan_load4_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE);
}
}
VOID __asan_load8_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE);
}
}
VOID __asan_load16_noabort(UINTPTR p)
{
if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
OsLmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE);
}
}
VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
{
if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
OsLmsReportError(p, size, LOAD_ERRMODE);
}
}
#else
VOID __asan_load1_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_load2_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_load4_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_load8_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_load16_noabort(UINTPTR p)
{
(VOID)p;
}
VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
{
(VOID)p;
(VOID)size;
}
#endif
VOID __asan_handle_no_return(VOID)
{
return;
}
LOS_MODULE_INIT(OsLmsInit, LOS_INIT_LEVEL_KMOD_PREVM);
+135
View File
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_LMS_PRI_H
#define _LOS_LMS_PRI_H
#include "los_lms.h"
#include "los_typedef.h"
#include "los_list.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define COMMON_ERRMODE 3
#define FREE_ERRORMODE 2
#define STORE_ERRMODE 1
#define LOAD_ERRMODE 0
#define SANITIZER_INTERFACE_ATTRIBUTE
#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#define LMS_SHADOW_BITS_PER_CELL 2
#define LMS_MEM_BYTES_PER_SHADOW_CELL 4
#define LMS_SHADOW_U8_CELL_NUM 4
#define LMS_SHADOW_U8_REFER_BYTES 16
#define LMS_POOL_RESIZE(size) ((size) / (LMS_SHADOW_U8_REFER_BYTES + 1) * LMS_SHADOW_U8_REFER_BYTES)
#define LMS_ADDR_ALIGN(p) (((UINTPTR)(p) + sizeof(UINTPTR) - 1) & ~((UINTPTR)(sizeof(UINTPTR) - 1)))
#define LMS_SHADOW_ACCESSABLE 0x00
#define LMS_SHADOW_AFTERFREE 0x03
#define LMS_SHADOW_REDZONE 0x02
#define LMS_SHADOW_PAINT 0x01
#define LMS_SHADOW_MASK 0x03
#define LMS_SHADOW_ACCESSABLE_U8 0x00
#define LMS_SHADOW_AFTERFREE_U8 0xFF
#define LMS_SHADOW_REDZONE_U8 0xAA
#define LMS_SHADOW_MASK_U8 0xFF
#define LMS_SHADOW_PAINT_U8 0x55
#define MEM_REGION_SIZE_1 1
#define MEM_REGION_SIZE_2 2
#define MEM_REGION_SIZE_4 4
#define MEM_REGION_SIZE_8 8
#define MEM_REGION_SIZE_16 16
typedef struct {
LOS_DL_LIST node;
UINT32 used;
UINTPTR poolAddr;
UINT32 poolSize;
UINTPTR shadowStart;
UINT32 shadowSize;
} LmsMemListNode;
typedef struct {
UINTPTR memAddr;
UINTPTR shadowAddr;
UINT32 shadowOffset;
UINT32 shadowValue;
} LmsAddrInfo;
typedef struct {
UINT32 (*init)(const VOID *pool, UINT32 size);
VOID (*mallocMark)(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize);
VOID (*freeMark)(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize);
VOID (*simpleMark)(UINTPTR startAddr, UINTPTR endAddr, UINT32 value);
VOID (*check)(UINTPTR checkAddr, BOOL isFreeCheck);
} LmsHook;
extern LmsHook* g_lms;
VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck);
VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize);
VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize);
VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value);
VOID OsLmsPrintPoolListInfo(VOID);
VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod);
VOID CheckValid(const CHAR *dest, const CHAR *src);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store1_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store4_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load4_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load1_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_loadN_noabort(UINTPTR p, UINT32 size);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_storeN_noabort(UINTPTR p, UINT32 size);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store2_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load2_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store8_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load8_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load16_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store16_noabort(UINTPTR p);
extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_handle_no_return(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_LMS_PRI_H */
+59
View File
@@ -0,0 +1,59 @@
# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//build/lite/config/component/lite_component.gni")
copy("usrlmslib") {
deps = [ ":usrlms" ]
sources = [ get_path_info(".", "out_dir") + "/libusrlms.a" ]
outputs = [ "$root_out_dir/libusrlms.a" ]
}
lite_library("usrlms") {
target_type = "static_library"
sources = [
"los_lms.c",
"los_lmslibc.c",
]
include_dirs = [ "." ]
cflags = [
"-fPIC",
"-funwind-tables",
"-fasynchronous-unwind-tables",
]
ldflags = [
"-rdynamic",
"-lunwind",
]
output_dir = target_out_dir
}
+486
View File
@@ -0,0 +1,486 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/mman.h>
#include "los_lms_pri.h"
#include "debug.h"
#define LMS_FREE_NODE_SIZE 16
struct MmapNode {
uintptr_t addr;
size_t mapSize;
struct MmapNode *next;
};
struct MmapNode g_freeNode[LMS_FREE_NODE_SIZE];
struct MmapNode *g_mmapNode = NULL;
uint32_t g_shadowStartAddr = SHADOW_BASE;
pthread_mutex_t g_lmsMutex = PTHREAD_MUTEX_INITIALIZER;
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsMem2Shadow(uintptr_t memAddr, uintptr_t *shadowAddr, uint32_t *shadowOffset)
{
uint32_t memOffset = memAddr - USPACE_MAP_BASE;
*shadowAddr = g_shadowStartAddr + memOffset / LMS_SHADOW_U8_REFER_BYTES;
*shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) * LMS_SHADOW_BITS_PER_CELL;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS uint32_t LmsIsShadowAddrMapped(uintptr_t sdStartAddr, uintptr_t sdEndAddr)
{
struct MmapNode *node = g_mmapNode;
while (node != NULL) {
if ((sdStartAddr >= node->addr) && (sdEndAddr < node->addr + node->mapSize)) {
return LMS_OK;
}
node = node->next;
}
return LMS_NOK;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsAddMapNode(uintptr_t sdStartAddr, uintptr_t sdEndAddr)
{
static uint32_t freeNodeIdx = 0;
struct MmapNode *node = g_mmapNode;
size_t mapSize;
uintptr_t shadowPageStartAddr = LMS_MEM_ALIGN_DOWN(sdStartAddr, 0x1000);
uintptr_t shadowPageEndAddr = LMS_MEM_ALIGN_UP(sdEndAddr, 0x1000);
struct MmapNode *expandNode = NULL;
while (node != NULL) {
if ((shadowPageStartAddr >= node->addr) && (shadowPageStartAddr <= node->addr + node->mapSize)) {
expandNode = node;
break;
}
node = node->next;
}
if (expandNode != NULL) {
shadowPageStartAddr = expandNode->addr + expandNode->mapSize;
expandNode->mapSize = shadowPageEndAddr - expandNode->addr;
}
mapSize = shadowPageEndAddr - shadowPageStartAddr;
void *mapPtr =
mmap((void *)shadowPageStartAddr, mapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mapPtr == (void *)-1) {
LMS_OUTPUT_INFO("mmap error! file:%s line:%d\n", __FILE__, __LINE__);
return;
}
__real_memset(mapPtr, 0, mapSize);
if (expandNode != NULL) {
return;
}
if (freeNodeIdx >= LMS_FREE_NODE_SIZE) {
LMS_OUTPUT_INFO("Add new mmap node error! file:%s line:%d\n", __FILE__, __LINE__);
return;
}
struct MmapNode *newNode = &g_freeNode[freeNodeIdx];
freeNodeIdx++;
newNode->addr = shadowPageStartAddr;
newNode->mapSize = mapSize;
newNode->next = g_mmapNode;
g_mmapNode = newNode;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsSetShadowValue(uintptr_t startAddr, uintptr_t endAddr, char value)
{
uintptr_t shadowStart;
uintptr_t shadowEnd;
uint32_t startOffset;
uint32_t endOffset;
char shadowValueMask;
char shadowValue;
/* endAddr - 1, then we mark [startAddr, endAddr) to value */
LmsMem2Shadow(startAddr, &shadowStart, &startOffset);
LmsMem2Shadow(endAddr - 1, &shadowEnd, &endOffset);
if (shadowStart == shadowEnd) { /* in the same u8 */
/* because endAddr - 1, the endOffset falls into the previous cell,
so endOffset + 2 is required for calculation */
shadowValueMask = LMS_SHADOW_MASK_U8;
shadowValueMask =
(shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)));
shadowValue = value & shadowValueMask;
*(char *)shadowStart &= ~shadowValueMask;
*(char *)shadowStart |= shadowValue;
} else {
/* Adjust startAddr to left util it reach the beginning of a u8 */
if (startOffset > 0) {
shadowValueMask = LMS_SHADOW_MASK_U8;
shadowValueMask = shadowValueMask << startOffset;
shadowValue = value & shadowValueMask;
*(char *)shadowStart &= ~shadowValueMask;
*(char *)shadowStart |= shadowValue;
shadowStart += 1;
}
/* Adjust endAddr to right util it reach the end of a u8 */
if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) {
shadowValueMask = LMS_SHADOW_MASK_U8;
shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL));
shadowValue = value & shadowValueMask;
*(char *)shadowEnd &= ~shadowValueMask;
*(char *)shadowEnd |= shadowValue;
shadowEnd -= 1;
}
if (shadowEnd + 1 > shadowStart) {
(void)__real_memset((void *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart);
}
}
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsGetShadowValue(uintptr_t addr, uint32_t *shadowValue)
{
uintptr_t shadowAddr;
uint32_t shadowOffset;
LmsMem2Shadow(addr, &shadowAddr, &shadowOffset);
/* If the shadow addr is not mapped then regarded as legal access */
if (LmsIsShadowAddrMapped(shadowAddr, shadowAddr) != LMS_OK) {
*shadowValue = LMS_SHADOW_ACCESSABLE_U8;
return;
}
*shadowValue = ((*(char *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsMallocMark(uintptr_t preRzStart, uintptr_t accessMemStart, uintptr_t nextRzStart,
uintptr_t RzEndAddr)
{
LmsSetShadowValue(preRzStart, accessMemStart, LMS_SHADOW_REDZONE_U8);
LmsSetShadowValue(accessMemStart, nextRzStart, LMS_SHADOW_ACCESSABLE_U8);
LmsSetShadowValue(nextRzStart, RzEndAddr, LMS_SHADOW_REDZONE_U8);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsTagMem(void *ptr, size_t origSize)
{
g_shadowStartAddr = SHADOW_BASE;
size_t mSize = malloc_usable_size(ptr);
uint32_t memOffset = (uintptr_t)ptr + mSize + OVERHEAD - USPACE_MAP_BASE;
uintptr_t shadowEndAddr = g_shadowStartAddr + memOffset / LMS_SHADOW_U8_REFER_BYTES;
LMS_OUTPUT_INFO("SHADOW_BASE:%x g_shadowStartAddr:%x memOffset: %x\n", SHADOW_BASE, g_shadowStartAddr, memOffset);
memOffset = (uintptr_t)ptr - OVERHEAD - USPACE_MAP_BASE;
uintptr_t shadowStartAddr = g_shadowStartAddr + memOffset / LMS_SHADOW_U8_REFER_BYTES;
LmsLock(&g_lmsMutex);
if (LmsIsShadowAddrMapped(shadowStartAddr, shadowEndAddr) != LMS_OK) {
LmsAddMapNode(shadowStartAddr, shadowEndAddr);
}
LmsMallocMark((uintptr_t)ptr - OVERHEAD, (uintptr_t)ptr, (uintptr_t)ptr + LMS_MEM_ALIGN_UP(origSize, LMS_RZ_SIZE),
(uintptr_t)((uintptr_t)ptr + mSize + OVERHEAD));
LmsUnlock(&g_lmsMutex);
return ptr;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS uint32_t LmsCheckAddr(uintptr_t addr)
{
LmsLock(&g_lmsMutex);
uint32_t shadowValue = -1;
LmsGetShadowValue(addr, &shadowValue);
LmsUnlock(&g_lmsMutex);
return shadowValue;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS uint32_t LmsCheckAddrRegion(uintptr_t addr, size_t size)
{
if (LmsCheckAddr(addr) || LmsCheckAddr(addr + size - 1)) {
return LMS_NOK;
} else {
return LMS_OK;
}
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsPrintMemInfo(uintptr_t addr)
{
#define LMS_DUMP_OFFSET 4
#define LMS_DUMP_RANGE_DOUBLE 2
LMS_OUTPUT_INFO("\nDump info around address [0x%8x]:\n", addr);
uint32_t printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1;
uint32_t printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE;
uintptr_t dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX;
uint32_t shadowValue = 0;
uintptr_t shadowAddr = 0;
uint32_t shadowOffset = 0;
int isCheckAddr;
for (int y = 0; y < printY; y++, dumpAddr += printX) {
LmsMem2Shadow(dumpAddr, &shadowAddr, &shadowOffset);
/* find util dumpAddr in pool region */
if (LmsIsShadowAddrMapped(shadowAddr, shadowAddr) != LMS_OK) {
continue;
}
uintptr_t maxShadowAddr;
uint32_t maxShadowOffset;
LmsMem2Shadow(dumpAddr + printX, &maxShadowAddr, &maxShadowOffset);
/* finish if dumpAddr exceeds pool's upper region */
if (LmsIsShadowAddrMapped(maxShadowAddr, maxShadowAddr) != LMS_OK) {
goto END;
}
LMS_OUTPUT_INFO("\n\t[0x%x]: ", dumpAddr);
for (int x = 0; x < printX; x++) {
if (dumpAddr + x == addr) {
LMS_OUTPUT_INFO("[%02x]", *(uint8_t *)(dumpAddr + x));
} else {
LMS_OUTPUT_INFO(" %02x ", *(uint8_t *)(dumpAddr + x));
}
}
LMS_OUTPUT_INFO("|\t[0x%x | %2d]: ", shadowAddr, shadowOffset);
for (int x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) {
LmsGetShadowValue(dumpAddr + x, &shadowValue);
isCheckAddr = dumpAddr + x - (uintptr_t)addr + LMS_MEM_BYTES_PER_SHADOW_CELL;
if (isCheckAddr > 0 && isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL) {
LMS_OUTPUT_INFO("[%1x]", shadowValue);
} else {
LMS_OUTPUT_INFO(" %1x ", shadowValue);
}
}
}
END:
LMS_OUTPUT_INFO("\n");
}
ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsGetShadowInfo(uintptr_t memAddr, LmsAddrInfo *info)
{
uintptr_t shadowAddr;
uint32_t shadowOffset;
uint32_t shadowValue;
LmsMem2Shadow(memAddr, &shadowAddr, &shadowOffset);
shadowValue = ((*(char *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
info->memAddr = memAddr;
info->shadowAddr = shadowAddr;
info->shadowOffset = shadowOffset;
info->shadowValue = shadowValue;
}
ATTRIBUTE_NO_SANITIZE_ADDRESS static void LmsGetErrorInfo(uintptr_t addr, size_t size, LmsAddrInfo *info)
{
LmsGetShadowInfo(addr, info);
if (info->shadowValue != LMS_SHADOW_ACCESSABLE_U8) {
return;
} else {
LmsGetShadowInfo(addr + size - 1, info);
}
}
ATTRIBUTE_NO_SANITIZE_ADDRESS static void LmsPrintErrInfo(LmsAddrInfo *info, uint32_t errMod)
{
switch (info->shadowValue) {
case LMS_SHADOW_AFTERFREE:
LMS_OUTPUT_ERROR("Use after free error detected!\n");
break;
case LMS_SHADOW_REDZONE:
LMS_OUTPUT_ERROR("Heap buffer overflow error detected!\n");
break;
case LMS_SHADOW_ACCESSABLE:
LMS_OUTPUT_ERROR("No error!\n");
break;
default:
LMS_OUTPUT_ERROR("UnKnown Error detected!\n");
break;
}
switch (errMod) {
case FREE_ERRORMODE:
LMS_OUTPUT_ERROR("Illegal Double free address at: [0x%x]\n", info->memAddr);
break;
case LOAD_ERRMODE:
LMS_OUTPUT_ERROR("Illegal READ address at: [0x%x]\n", info->memAddr);
break;
case STORE_ERRMODE:
LMS_OUTPUT_ERROR("Illegal WRITE address at: [0x%x]\n", info->memAddr);
break;
default:
LMS_OUTPUT_ERROR("UnKnown Error mode at: [0x%x]\n", info->memAddr);
break;
}
LMS_OUTPUT_INFO("Shadow memory address: [0x%x : %d] Shadow memory value: [%d] \n", info->shadowAddr,
info->shadowOffset, info->shadowValue);
LMS_OUTPUT_INFO("\n");
LMS_OUTPUT_INFO("%-25s%d\n", "Accessable heap addr", LMS_SHADOW_ACCESSABLE);
LMS_OUTPUT_INFO("%-25s%d\n", "Heap red zone", LMS_SHADOW_REDZONE);
LMS_OUTPUT_INFO("%-25s%d\n", "Heap freed buffer", LMS_SHADOW_AFTERFREE);
LMS_OUTPUT_INFO("\n");
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsReportError(uintptr_t p, size_t size, uint32_t errMod)
{
LmsAddrInfo info;
(void)__real_memset(&info, 0, sizeof(LmsAddrInfo));
int locked = LmsTrylock(&g_lmsMutex);
LMS_OUTPUT_ERROR("\n***** Lite Memory Sanitizer Error Detected *****\n");
LmsGetErrorInfo(p, size, &info);
LmsPrintErrInfo(&info, errMod);
LmsPrintMemInfo(info.memAddr);
LMS_OUTPUT_ERROR("***** Lite Memory Sanitizer Error Detected End *****\n");
if (!locked) {
LmsUnlock(&g_lmsMutex);
}
if (LMS_CRASH_MODE > 0) {
LmsCrash();
} else {
print_trace();
}
}
void LmsCheckValid(const char *dest, const char *src)
{
if (LmsCheckAddr((uintptr_t)dest) != LMS_SHADOW_ACCESSABLE_U8) {
LmsReportError((uintptr_t)dest, MEM_REGION_SIZE_1, STORE_ERRMODE);
return;
}
if (LmsCheckAddr((uintptr_t)src) != LMS_SHADOW_ACCESSABLE_U8) {
LmsReportError((uintptr_t)src, MEM_REGION_SIZE_1, LOAD_ERRMODE);
return;
}
for (uint32_t i = 0; *(src + i) != '\0'; i++) {
if (LmsCheckAddr((uintptr_t)dest + i + 1) != LMS_SHADOW_ACCESSABLE_U8) {
LmsReportError((uintptr_t)dest + i + 1, MEM_REGION_SIZE_1, STORE_ERRMODE);
return;
}
if (LmsCheckAddr((uintptr_t)src + i + 1) != LMS_SHADOW_ACCESSABLE_U8) {
LmsReportError((uintptr_t)src + i + 1, MEM_REGION_SIZE_1, LOAD_ERRMODE);
return;
}
}
}
void __asan_store1_noabort(uintptr_t p)
{
if (LmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) {
LmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE);
}
}
void __asan_store2_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE);
}
}
void __asan_store4_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE);
}
}
void __asan_store8_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE);
}
}
void __asan_store16_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LMS_OK) { /* 16 byte memory for check */
LmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE);
}
}
void __asan_storeN_noabort(uintptr_t p, size_t size)
{
if (LmsCheckAddrRegion(p, size) != LMS_OK) {
LmsReportError(p, size, STORE_ERRMODE);
}
}
void __asan_load1_noabort(uintptr_t p)
{
if (LmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) {
LmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE);
}
}
void __asan_load2_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE);
}
}
void __asan_load4_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE);
}
}
void __asan_load8_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE);
}
}
void __asan_load16_noabort(uintptr_t p)
{
if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LMS_OK) {
LmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE);
}
}
void __asan_loadN_noabort(uintptr_t p, size_t size)
{
if (LmsCheckAddrRegion(p, size) != LMS_OK) {
LmsReportError(p, size, LOAD_ERRMODE);
}
}
void __asan_handle_no_return(void)
{
return;
}
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_LMS_H
#define _LOS_LMS_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*
* If LMS_CRASH_MODE == 0
* the program would NOT be crashed once the sanitizer detected an error.
* If LMS_CRASM_MODE > 0
* the program would be crashed once the sanitizer detected an error.
*/
#define LMS_CRASH_MODE 0
/*
* USPACE_MAP_BASE
* is the start address of user space.
*/
#define USPACE_MAP_BASE 0x00000000
/*
* USPACE_MAP_SIZE
* is the address size of the user space, and [USPACE_MAP_BASE, USPACE_MAP_BASE + USPACE_MAP_SIZE]
* must cover the HEAP section.
*/
#define USPACE_MAP_SIZE 0x3ef00000
/*
* LMS_OUTPUT_ERROR can be redefined to redirect output logs.
*/
#ifndef LMS_OUTPUT_ERROR
#define LMS_OUTPUT_ERROR(fmt, ...) \
do { \
(printf("\033[31;1m"), printf(fmt, ##__VA_ARGS__), printf("\033[0m")); \
} while (0)
#endif
/*
* LMS_OUTPUT_INFO can be redefined to redirect output logs.
*/
#ifndef LMS_OUTPUT_INFO
#define LMS_OUTPUT_INFO(fmt, ...) \
do { \
(printf("\033[33;1m"), printf(fmt, ##__VA_ARGS__), printf("\033[0m")); \
} while (0)
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_LMS_H */
+172
View File
@@ -0,0 +1,172 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_LMS_PRI_H
#define _LOS_LMS_PRI_H
#include <pthread.h>
#include <malloc.h>
#include "los_lms.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define UNKNOWN_ERROR 3
#define FREE_ERRORMODE 2
#define STORE_ERRMODE 1
#define LOAD_ERRMODE 0
#define SANITIZER_INTERFACE_ATTRIBUTE
#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#define LMS_SHADOW_ACCESSABLE 0x00
#define LMS_SHADOW_AFTERFREE 0x03
#define LMS_SHADOW_REDZONE 0x02
#define LMS_SHADOW_PAINT 0x01
#define LMS_SHADOW_MASK 0x03
#define LMS_SHADOW_BITS_PER_CELL 2
#define LMS_MEM_BYTES_PER_SHADOW_CELL 4
#define LMS_SHADOW_U8_CELL_NUM 4
#define LMS_SHADOW_U8_REFER_BYTES 16
#define LMS_SHADOW_ACCESSABLE_U8 0x00
#define LMS_SHADOW_AFTERFREE_U8 0xFF
#define LMS_SHADOW_REDZONE_U8 0xAA
#define LMS_SHADOW_MASK_U8 0xFF
#define LMS_SHADOW_PAINT_U8 0x55
#define MEM_REGION_SIZE_1 1
#define MEM_REGION_SIZE_2 2
#define MEM_REGION_SIZE_4 4
#define MEM_REGION_SIZE_8 8
#define MEM_REGION_SIZE_16 16
#define LMS_RZ_SIZE 4
#define LMS_OK 0
#define LMS_NOK 1
#define PAGE_ADDR_MASK 0xFFFFE000
#define SHADOW_BASE \
((USPACE_MAP_BASE + (USPACE_MAP_SIZE / (LMS_SHADOW_U8_REFER_BYTES + 1)) * LMS_SHADOW_U8_REFER_BYTES) & \
PAGE_ADDR_MASK)
#define OVERHEAD (2 * sizeof(size_t))
#define LMS_MEM_ALIGN_DOWN(value, align) (((uint32_t)(value)) & ~((uint32_t)((align) - 1)))
#define LMS_MEM_ALIGN_UP(value, align) (((uint32_t)(value) + ((align) - 1)) & ~((uint32_t)((align) - 1)))
typedef struct {
uintptr_t memAddr;
uintptr_t shadowAddr;
uint32_t shadowOffset;
uint32_t shadowValue;
} LmsAddrInfo;
extern pthread_mutex_t g_lmsMutex;
ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsLock(pthread_mutex_t *lock)
{
(void)pthread_mutex_lock(lock);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS static inline int LmsTrylock(pthread_mutex_t *lock)
{
return pthread_mutex_trylock(lock);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsUnlock(pthread_mutex_t *lock)
{
(void)pthread_mutex_unlock(lock);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsCrash(void)
{
*(volatile char *)(SHADOW_BASE - 1) = 0;
}
uint32_t LmsIsShadowAddrMapped(uintptr_t sdStartAddr, uintptr_t sdEndAddr);
void LmsSetShadowValue(uintptr_t startAddr, uintptr_t endAddr, char value);
void LmsGetShadowValue(uintptr_t addr, uint32_t *shadowValue);
void LmsReportError(uintptr_t p, size_t size, uint32_t errMod);
void LmsMem2Shadow(uintptr_t memAddr, uintptr_t *shadowAddr, uint32_t *shadowOffset);
void LmsCheckValid(const char *dest, const char *src);
void *__real_malloc(size_t);
void __real_free(void *);
void *__real_calloc(size_t, size_t);
void *__real_realloc(void *, size_t);
void *__real_valloc(size_t);
void *__real_aligned_alloc(size_t, size_t);
void *__real_memcpy(void *__restrict, const void *__restrict, size_t);
void *__real_memmove(void *, const void *, size_t);
char *__real_strcat(char *, const char *);
char *__real_strcpy(char *, const char *);
void *__real_memset(void *, int, size_t);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uintptr_t p, uint32_t size);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uintptr_t p, uint32_t size);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uintptr_t p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_no_return(void);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_LMS_PRI_H */
+210
View File
@@ -0,0 +1,210 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_lms_pri.h"
ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsFree(void *ptr)
{
if (ptr == NULL) {
return;
}
size_t allocSize = malloc_usable_size(ptr);
uintptr_t shadowAddr, offset;
LmsMem2Shadow((uintptr_t)ptr, &shadowAddr, &offset);
LmsLock(&g_lmsMutex);
if (LmsIsShadowAddrMapped(shadowAddr, shadowAddr) == LMS_OK) {
uint32_t acShadowValue;
LmsGetShadowValue((uintptr_t)ptr, &acShadowValue);
if (acShadowValue != LMS_SHADOW_ACCESSABLE) {
char erroMode = (acShadowValue == LMS_SHADOW_AFTERFREE ? FREE_ERRORMODE : UNKNOWN_ERROR);
LmsReportError((uintptr_t)ptr, MEM_REGION_SIZE_1, erroMode);
goto UNLOCK_OUT;
}
} else {
LMS_OUTPUT_ERROR("Error! Free an unallocated memory:%p!\n", ptr);
goto UNLOCK_OUT;
}
__real_free(ptr);
LmsSetShadowValue((uintptr_t)ptr, (uintptr_t)ptr + allocSize, LMS_SHADOW_AFTERFREE_U8);
UNLOCK_OUT:
LmsUnlock(&g_lmsMutex);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMalloc(size_t size)
{
void *ptr = __real_malloc(size);
if (ptr == NULL) {
return ptr;
}
return LmsTagMem(ptr, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsRealloc(void *ptr, size_t size)
{
void *p = __real_realloc(ptr, size);
if (p == NULL) {
return p;
}
return LmsTagMem(p, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsCalloc(size_t m, size_t n)
{
void *p = __real_calloc(m, n);
if (p == NULL) {
return p;
}
return LmsTagMem(p, n * m);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsValloc(size_t size)
{
void *p = __real_valloc(size);
if (p == NULL) {
return p;
}
return LmsTagMem(p, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsAlignedAlloc(size_t align, size_t len)
{
void *p = __real_aligned_alloc(align, len);
if (p == NULL) {
return p;
}
return LmsTagMem(p, len);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_aligned_alloc(size_t align, size_t len)
{
return LmsAlignedAlloc(align, len);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_valloc(size_t size)
{
return LmsValloc(size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_calloc(size_t m, size_t n)
{
return LmsCalloc(m, n);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_realloc(void *p, size_t n)
{
return LmsRealloc(p, n);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_malloc(size_t size)
{
return LmsMalloc(size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void __wrap_free(void *ptr)
{
return LmsFree(ptr);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMemset(void *p, int n, size_t size)
{
__asan_storeN_noabort((uintptr_t)p, size);
return __real_memset(p, n, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_memset(void *p, int n, size_t size)
{
return LmsMemset(p, n, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMemcpy(void *__restrict dest, const void *__restrict src, size_t size)
{
__asan_loadN_noabort((uintptr_t)src, size);
__asan_storeN_noabort((uintptr_t)dest, size);
return __real_memcpy(dest, src, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_memcpy(void *__restrict dest, const void *__restrict src, size_t size)
{
return LmsMemcpy(dest, src, size);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMemmove(void *dest, const void *src, size_t len)
{
__asan_loadN_noabort((uintptr_t)src, len);
__asan_storeN_noabort((uintptr_t)dest, len);
return __real_memmove(dest, src, len);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_memmove(void *dest, const void *src, size_t len)
{
return LmsMemmove(dest, src, len);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS char *LmsStrcat(char *s, const char *append)
{
if ((s == NULL) || (append == NULL)) {
return NULL;
}
char *save = s;
for (; *s != '\0'; ++s) {
}
LmsCheckValid(s, append);
return __real_strcat(save, append);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS char *__wrap_strcat(char *s, const char *append)
{
return LmsStrcat(s, append);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS char *LmsStrcpy(char *dest, const char *src)
{
if ((dest == NULL) || (src == NULL)) {
return NULL;
}
LmsCheckValid(dest, src);
return __real_strcpy(dest, src);
}
ATTRIBUTE_NO_SANITIZE_ADDRESS char *__wrap_strcpy(char *dest, const char *src)
{
return LmsStrcpy(dest, src);
}