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:
@@ -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 = [ "." ]
|
||||
}
|
||||
Executable
+41
@@ -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
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
include $(LITEOSTOPDIR)/config.mk
|
||||
|
||||
MODULE_NAME := $(notdir $(shell pwd))
|
||||
|
||||
LOCAL_SRCS := $(wildcard *.c)
|
||||
|
||||
LOCAL_FLAGS := $(LOCAL_INCLUDE)
|
||||
|
||||
include $(MODULE)
|
||||
|
||||
Executable
+122
@@ -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);
|
||||
}
|
||||
Executable
+769
@@ -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);
|
||||
Executable
+135
@@ -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 */
|
||||
@@ -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
|
||||
}
|
||||
Executable
+486
@@ -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;
|
||||
}
|
||||
Executable
+93
@@ -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 */
|
||||
Executable
+172
@@ -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 */
|
||||
Executable
+210
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user