58#include "los_lms_pri.h"
71#define LMS_LOCK(state) LOS_SpinLockSave(&g_lmsSpin, &(state))
72#define LMS_UNLOCK(state) LOS_SpinUnlockRestore(&g_lmsSpin, (state))
74#define OS_MEM_ALIGN_BACK(value, align) (((UINT32)(value)) & ~((UINT32)((align) - 1)))
75#define OS_MEM_ALIGN_SIZE sizeof(UINTPTR)
76#define POOL_ADDR_ALIGNSIZE 64
77#define LMS_POOL_UNUSED 0
78#define LMS_POOL_USED 1
79#define INVALID_SHADOW_VALUE 0xFFFFFFFF
83 return OS_MEM_ALIGN_BACK(LMS_POOL_RESIZE(size), POOL_ADDR_ALIGNSIZE);
96 LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead,
LmsMemListNode, node) {
115 LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead,
LmsMemListNode, node) {
116 if ((addr >= current->
poolAddr) && (addr < current->poolAddr + current->
poolSize)) {
129 for (i = 0; i < LOSCFG_LMS_MAX_RECORD_POOL_NUM; i++) {
131 if (current->
used == LMS_POOL_UNUSED) {
132 current->
used = LMS_POOL_USED;
155 if (lmsPoolNode != NULL) {
158 PRINT_DEBUG(
"[LMS]pool %p already on lms checklist !\n", pool);
163 lmsPoolNode->
used = LMS_POOL_UNUSED;
169 if (lmsPoolNode == NULL) {
170 PRINT_DEBUG(
"[LMS]the num of lms check pool is max already !\n");
198 if (delNode == NULL) {
199 PRINT_ERR(
"[LMS]pool %p is not on lms checklist !\n", pool);
202 delNode->
used = LMS_POOL_UNUSED;
225 if ((memAddr < node->poolAddr) || (memAddr >= node->
poolAddr + node->
poolSize)) {
226 PRINT_ERR(
"[LMS]memAddr %p is not in pool region [%p, %p)\n", memAddr, node->
poolAddr,
232 *shadowAddr = node->
shadowStart + memOffset / LMS_SHADOW_U8_REFER_BYTES;
233 *shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) *
234 LMS_SHADOW_BITS_PER_CELL;
244 if (
OsLmsMem2Shadow(node, memAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
248 shadowValue = ((*(
UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
262 UINT8 shadowValueMask;
271 if (shadowStart == shadowEnd) {
274 shadowValueMask = LMS_SHADOW_MASK_U8;
276 (shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)));
277 shadowValue = value & shadowValueMask;
278 *(
UINT8 *)shadowStart &= ~shadowValueMask;
279 *(
UINT8 *)shadowStart |= shadowValue;
282 if (startOffset > 0) {
283 shadowValueMask = LMS_SHADOW_MASK_U8;
284 shadowValueMask = shadowValueMask << startOffset;
285 shadowValue = value & shadowValueMask;
286 *(
UINT8 *)shadowStart &= ~shadowValueMask;
287 *(
UINT8 *)shadowStart |= shadowValue;
292 if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) {
293 shadowValueMask = LMS_SHADOW_MASK_U8;
294 shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL));
295 shadowValue = value & shadowValueMask;
296 *(
UINT8 *)shadowEnd &= ~shadowValueMask;
297 *(
UINT8 *)shadowEnd |= shadowValue;
301 if (shadowEnd + 1 > shadowStart) {
302 (VOID)
memset((VOID *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart);
311 if (
OsLmsMem2Shadow(node, addr, &shadowAddr, &shadowOffset) != LOS_OK) {
315 *shadowValue = ((*(
UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
321 if (endAddr <= startAddr) {
322 PRINT_DEBUG(
"[LMS]mark 0x%x, 0x%x, 0x%x\n", startAddr, endAddr, (
UINTPTR)__builtin_return_address(0));
326 if (!IS_ALIGNED(startAddr, OS_MEM_ALIGN_SIZE) || !IS_ALIGNED(endAddr, OS_MEM_ALIGN_SIZE)) {
327 PRINT_ERR(
"[LMS]mark addr is not aligned! 0x%x, 0x%x\n", startAddr, endAddr);
356 OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
357 OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_ACCESSABLE_U8);
358 OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
365 UINT32 shadowValue = INVALID_SHADOW_VALUE;
375 if ((shadowValue == LMS_SHADOW_ACCESSABLE) || ((isFreeCheck) && (shadowValue == LMS_SHADOW_PAINT))) {
379 OsLmsReportError(checkAddr, MEM_REGION_SIZE_1, isFreeCheck ? FREE_ERRORMODE : COMMON_ERRMODE);
385 UINT32 shadowValue = INVALID_SHADOW_VALUE;
398 if ((shadowValue != LMS_SHADOW_ACCESSABLE) && (shadowValue != LMS_SHADOW_PAINT)) {
400 OsLmsReportError(curNodeStartAddr + nodeHeadSize, MEM_REGION_SIZE_1, FREE_ERRORMODE);
404 if (*((
UINT8 *)curNodeStart) == 0) {
405 OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
407 OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_AFTERFREE_U8);
409 if (*((
UINT8 *)nextNodeStart) == 0) {
410 OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
419 if (addrEnd <= addrStart) {
433 if (addrEnd <= addrStart) {
447 UINT32 shadowValue = INVALID_SHADOW_VALUE;
457 return LMS_SHADOW_ACCESSABLE_U8;
465#ifdef LOSCFG_LMS_CHECK_STRICT
469 for (i = 0; i < size; i++) {
496 LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead,
LmsMemListNode, node)
500 "[LMS]memory pool[%1u]: totalsize 0x%-8x memstart 0x%-8x memstop 0x%-8x memsize 0x%-8x shadowstart 0x%-8x "
501 "shadowSize 0x%-8x\n",
511#define LMS_DUMP_OFFSET 16
512#define LMS_DUMP_RANGE_DOUBLE 2
514 PRINTK(
"\n[LMS] Dump info around address [0x%8x]:\n", addr);
515 const UINT32 printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1;
516 const UINT32 printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE;
517 UINTPTR dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX;
522 INT32 isCheckAddr, x, y;
525 if (nodeInfo == NULL) {
526 PRINT_ERR(
"[LMS]addr is not in checkpool\n");
530 for (y = 0; y < printY; y++, dumpAddr += printX) {
531 if (dumpAddr < nodeInfo->poolAddr) {
535 if ((dumpAddr + printX) >=
540 PRINTK(
"\n\t[0x%x]: ", dumpAddr);
541 for (x = 0; x < printX; x++) {
542 if ((dumpAddr + x) == addr) {
543 PRINTK(
"[%02x]", *(
UINT8 *)(dumpAddr + x));
545 PRINTK(
" %02x ", *(
UINT8 *)(dumpAddr + x));
549 if (
OsLmsMem2Shadow(nodeInfo, dumpAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
553 PRINTK(
"|\t[0x%x | %2u]: ", shadowAddr, shadowOffset);
555 for (x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) {
557 isCheckAddr = dumpAddr + x - (
UINTPTR)addr + LMS_MEM_BYTES_PER_SHADOW_CELL;
558 if ((isCheckAddr > 0) && (isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL)) {
559 PRINTK(
"[%1x]", shadowValue);
561 PRINTK(
" %1x ", shadowValue);
573 if (info->
shadowValue != LMS_SHADOW_ACCESSABLE_U8) {
583 case LMS_SHADOW_AFTERFREE:
584 PRINT_ERR(
"Use after free error detected\n");
586 case LMS_SHADOW_REDZONE:
587 PRINT_ERR(
"Heap buffer overflow error detected\n");
589 case LMS_SHADOW_ACCESSABLE:
590 PRINT_ERR(
"No error\n");
593 PRINT_ERR(
"UnKnown Error detected\n");
599 PRINT_ERR(
"Illegal Double free address at: [0x%lx]\n", info->
memAddr);
602 PRINT_ERR(
"Illegal READ address at: [0x%lx]\n", info->
memAddr);
605 PRINT_ERR(
"Illegal WRITE address at: [0x%lx]\n", info->
memAddr);
608 PRINT_ERR(
"Common Error at: [0x%lx]\n", info->
memAddr);
611 PRINT_ERR(
"UnKnown Error mode at: [0x%lx]\n", info->
memAddr);
615 PRINT_ERR(
"Shadow memory address: [0x%lx : %1u] Shadow memory value: [%u] \n", info->
shadowAddr,
628 PRINT_ERR(
"***** Kernel Address Sanitizer Error Detected Start *****\n");
638 PRINT_ERR(
"***** Kernel Address Sanitizer Error Detected End *****\n");
642#ifdef LOSCFG_LMS_STORE_CHECK
718#ifdef LOSCFG_LMS_LOAD_CHECK
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
Atomic addition.
STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal)
Atomic subtraction.
VOID OsBackTrace(VOID)
Kernel backtrace function.
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
void * memset(void *addr, int c, size_t len)
原子操作 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-atomic....
STATIC VOID OsLmsPrintErrInfo(LmsAddrInfo *info, UINT32 errMod)
STATIC INLINE UINT32 OsLmsMem2Shadow(LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset)
STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
VOID __asan_load2_noabort(UINTPTR p)
VOID __asan_store16_noabort(UINTPTR p)
STATIC UINT32 OsLmsInit(VOID)
初始化 LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具
VOID __asan_store4_noabort(UINTPTR p)
LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_lmsCheckPoolList
VOID OsLmsPrintMemInfo(UINTPTR addr)
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_lmsSpin)
VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
VOID __asan_load8_noabort(UINTPTR p)
STATIC Atomic g_checkDepth
VOID __asan_store1_noabort(UINTPTR p)
VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
VOID __asan_store2_noabort(UINTPTR p)
STATIC UINT32 OsLmsPoolResize(UINT32 size)
STATIC UINT32 OsLmsCheckAddr(UINTPTR addr)
STATIC LmsMemListNode * OsLmsGetPoolNode(const VOID *pool)
VOID __asan_load16_noabort(UINTPTR p)
VOID __asan_handle_no_return(VOID)
UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size)
STATIC LmsMemListNode * OsLmsGetPoolNodeFromAddr(UINTPTR addr)
VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck)
VOID LOS_LmsCheckPoolDel(const VOID *pool)
VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
VOID LOS_LmsAddrProtect(UINTPTR addrStart, UINTPTR addrEnd)
STATIC LmsMemListNode * OsLmsCheckPoolCreate(VOID)
VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod)
VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
LOS_MODULE_INIT(OsLmsInit, LOS_INIT_LEVEL_KMOD_PREVM)
STATIC VOID OsLmsGetErrorInfo(UINTPTR addr, UINT32 size, LmsAddrInfo *info)
VOID OsLmsGetShadowValue(LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue)
VOID __asan_store8_noabort(UINTPTR p)
LITE_OS_SEC_BSS STATIC LmsMemListNode g_lmsCheckPoolArray[LOSCFG_LMS_MAX_RECORD_POOL_NUM]
VOID LOS_LmsAddrDisableProtect(UINTPTR addrStart, UINTPTR addrEnd)
VOID __asan_load4_noabort(UINTPTR p)
STATIC INLINE VOID OsLmsGetShadowInfo(LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info)
VOID __asan_load1_noabort(UINTPTR p)
VOID OsLmsSetShadowValue(LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value)
VOID OsLmsPrintPoolListInfo(VOID)
VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
UINT32(* init)(const VOID *pool, UINT32 size)