更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_lms.c 文件参考

检测内存主文件 更多...

浏览源代码.

函数

LITE_OS_SEC_BSS SPIN_LOCK_INIT (g_lmsSpin)
 
STATIC UINT32 OsLmsPoolResize (UINT32 size)
 
STATIC LmsMemListNodeOsLmsGetPoolNode (const VOID *pool)
 
STATIC LmsMemListNodeOsLmsGetPoolNodeFromAddr (UINTPTR addr)
 
STATIC LmsMemListNodeOsLmsCheckPoolCreate (VOID)
 
UINT32 LOS_LmsCheckPoolAdd (const VOID *pool, UINT32 size)
 
VOID LOS_LmsCheckPoolDel (const VOID *pool)
 
STATIC UINT32 OsLmsInit (VOID)
 初始化 LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具 更多...
 
STATIC INLINE UINT32 OsLmsMem2Shadow (LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset)
 
STATIC INLINE VOID OsLmsGetShadowInfo (LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info)
 
VOID OsLmsSetShadowValue (LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value)
 
VOID OsLmsGetShadowValue (LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue)
 
VOID OsLmsSimpleMark (UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
 
VOID OsLmsLosMallocMark (const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
 
VOID OsLmsCheckValid (UINTPTR checkAddr, BOOL isFreeCheck)
 
VOID OsLmsLosFreeMark (const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
 
VOID LOS_LmsAddrProtect (UINTPTR addrStart, UINTPTR addrEnd)
 
VOID LOS_LmsAddrDisableProtect (UINTPTR addrStart, UINTPTR addrEnd)
 
STATIC UINT32 OsLmsCheckAddr (UINTPTR addr)
 
STATIC INLINE UINT32 OsLmsCheckAddrRegion (UINTPTR addr, UINT32 size)
 
VOID OsLmsPrintPoolListInfo (VOID)
 
VOID OsLmsPrintMemInfo (UINTPTR addr)
 
STATIC VOID OsLmsGetErrorInfo (UINTPTR addr, UINT32 size, LmsAddrInfo *info)
 
STATIC VOID OsLmsPrintErrInfo (LmsAddrInfo *info, UINT32 errMod)
 
VOID OsLmsReportError (UINTPTR p, UINT32 size, UINT32 errMod)
 
VOID __asan_store1_noabort (UINTPTR p)
 
VOID __asan_store2_noabort (UINTPTR p)
 
VOID __asan_store4_noabort (UINTPTR p)
 
VOID __asan_store8_noabort (UINTPTR p)
 
VOID __asan_store16_noabort (UINTPTR p)
 
VOID __asan_storeN_noabort (UINTPTR p, UINT32 size)
 
VOID __asan_load1_noabort (UINTPTR p)
 
VOID __asan_load2_noabort (UINTPTR p)
 
VOID __asan_load4_noabort (UINTPTR p)
 
VOID __asan_load8_noabort (UINTPTR p)
 
VOID __asan_load16_noabort (UINTPTR p)
 
VOID __asan_loadN_noabort (UINTPTR p, UINT32 size)
 
VOID __asan_handle_no_return (VOID)
 
 LOS_MODULE_INIT (OsLmsInit, LOS_INIT_LEVEL_KMOD_PREVM)
 

变量

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
 
LmsHookg_lms = NULL
 

详细描述

检测内存主文件

 基本概念
    LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具。LMS能够实时检测缓冲区溢出(buffer overflow),
    释放后使用(use after free) 和重复释放(double Free), 在异常发生的第一时间通知操作系统,结合backtrace等定位手段,
    能准确定位到产生内存问题的代码行,极大提升内存问题定位效率。
    OpenHarmony LiteOS-M内核的LMS模块提供下面几种功能:
    支持多内存池检测。
    支持LOS_MemAlloc、LOS_MemAllocAlign、LOS_MemRealloc申请出的内存检测。
    支持安全函数的访问检测(默认开启)。
    支持libc 高频函数的访问检测,包括:memset、memcpy、memmove、strcat、strcpy、strncat、strncpy。
 运行机制
    LMS使用影子内存映射标记系统内存的状态,一共可标记为三个状态:可读写,不可读写,已释放。影子内存存放在内存池的尾部。
    内存从堆上申请后,会将数据区的影子内存设置为“可读写”状态,并将头结点区的影子内存设置为“不可读写”状态。
    内存在堆上被释放时,会将被释放内存的影子内存设置为“已释放”状态。
    编译代码时,会在代码中的读写指令前插入检测函数,对地址的合法性进行检验。主要是检测访问内存的影子内存的状态值,
    若检测到影子内存为不可读写,则会报溢出错误;若检测到影子内存为已释放,则会报释放后使用错误。
    在内存释放时,会检测被释放地址的影子内存状态值,若检测到影子内存非可读写,则会报重复释放错误。
版本
作者
weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
日期
2022-03-22

在文件 los_lms.c 中定义.

函数说明

◆ __asan_handle_no_return()

VOID __asan_handle_no_return ( VOID  )

在文件 los_lms.c792 行定义.

793{
794 return;
795}

◆ __asan_load16_noabort()

VOID __asan_load16_noabort ( UINTPTR  p)

在文件 los_lms.c747 行定义.

748{
749 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
750 OsLmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE);
751 }
752}
STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
Definition: los_lms.c:466
VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod)
Definition: los_lms.c:619
函数调用图:

◆ __asan_load1_noabort()

VOID __asan_load1_noabort ( UINTPTR  p)

在文件 los_lms.c719 行定义.

720{
721 if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) {
722 OsLmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE);
723 }
724}
STATIC UINT32 OsLmsCheckAddr(UINTPTR addr)
Definition: los_lms.c:444
函数调用图:

◆ __asan_load2_noabort()

VOID __asan_load2_noabort ( UINTPTR  p)

在文件 los_lms.c726 行定义.

727{
728 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
729 OsLmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE);
730 }
731}
函数调用图:

◆ __asan_load4_noabort()

VOID __asan_load4_noabort ( UINTPTR  p)

在文件 los_lms.c733 行定义.

734{
735 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
736 OsLmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE);
737 }
738}
函数调用图:

◆ __asan_load8_noabort()

VOID __asan_load8_noabort ( UINTPTR  p)

在文件 los_lms.c740 行定义.

741{
742 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
743 OsLmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE);
744 }
745}
函数调用图:

◆ __asan_loadN_noabort()

VOID __asan_loadN_noabort ( UINTPTR  p,
UINT32  size 
)

在文件 los_lms.c754 行定义.

755{
756 if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
757 OsLmsReportError(p, size, LOAD_ERRMODE);
758 }
759}
函数调用图:
这是这个函数的调用关系图:

◆ __asan_store16_noabort()

VOID __asan_store16_noabort ( UINTPTR  p)

在文件 los_lms.c671 行定义.

672{
673 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
674 OsLmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE);
675 }
676}
函数调用图:

◆ __asan_store1_noabort()

VOID __asan_store1_noabort ( UINTPTR  p)

在文件 los_lms.c643 行定义.

644{
645 if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) {
646 OsLmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE);
647 }
648}
函数调用图:

◆ __asan_store2_noabort()

VOID __asan_store2_noabort ( UINTPTR  p)

在文件 los_lms.c650 行定义.

651{
652 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
653 OsLmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE);
654 }
655}
函数调用图:

◆ __asan_store4_noabort()

VOID __asan_store4_noabort ( UINTPTR  p)

在文件 los_lms.c657 行定义.

658{
659 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
660 OsLmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE);
661 }
662}
函数调用图:

◆ __asan_store8_noabort()

VOID __asan_store8_noabort ( UINTPTR  p)

在文件 los_lms.c664 行定义.

665{
666 if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
667 OsLmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE);
668 }
669}
函数调用图:

◆ __asan_storeN_noabort()

VOID __asan_storeN_noabort ( UINTPTR  p,
UINT32  size 
)

在文件 los_lms.c678 行定义.

679{
680 if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
681 OsLmsReportError(p, size, STORE_ERRMODE);
682 }
683}
函数调用图:
这是这个函数的调用关系图:

◆ LOS_LmsAddrDisableProtect()

VOID LOS_LmsAddrDisableProtect ( UINTPTR  addrStart,
UINTPTR  addrEnd 
)

在文件 los_lms.c430 行定义.

431{
432 UINT32 intSave;
433 if (addrEnd <= addrStart) {
434 return;
435 }
436 LMS_LOCK(intSave);
437 LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
438 if (node != NULL) {
439 OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_ACCESSABLE_U8);
440 }
441 LMS_UNLOCK(intSave);
442}
STATIC LmsMemListNode * OsLmsGetPoolNodeFromAddr(UINTPTR addr)
Definition: los_lms.c:106
VOID OsLmsSetShadowValue(LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value)
Definition: los_lms.c:255
unsigned int UINT32
Definition: los_typedef.h:57
函数调用图:

◆ LOS_LmsAddrProtect()

VOID LOS_LmsAddrProtect ( UINTPTR  addrStart,
UINTPTR  addrEnd 
)

在文件 los_lms.c416 行定义.

417{
418 UINT32 intSave;
419 if (addrEnd <= addrStart) {
420 return;
421 }
422 LMS_LOCK(intSave);
423 LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
424 if (node != NULL) {
425 OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_REDZONE_U8);
426 }
427 LMS_UNLOCK(intSave);
428}
函数调用图:

◆ LOS_LmsCheckPoolAdd()

UINT32 LOS_LmsCheckPoolAdd ( const VOID *  pool,
UINT32  size 
)

添加指定内存池被检测 将指定内存池的地址范围添加到LMS的内存检测链表上,当访问的地址在链表范围内时,LMS才进行合法性校验; 且LOS_MemInit接口会调用该接口,默认将初始化的内存池挂入到检测链表中。

在文件 los_lms.c141 行定义.

142{
143 UINT32 intSave;
144 UINTPTR poolAddr = (UINTPTR)pool;
145 UINT32 realSize;
146 LmsMemListNode *lmsPoolNode = NULL;
147
148 if (pool == NULL) {
149 return 0;
150 }
151
152 LMS_LOCK(intSave);
153
154 lmsPoolNode = OsLmsGetPoolNodeFromAddr((UINTPTR)pool);
155 if (lmsPoolNode != NULL) { /* if pool range already on checklist */
156 if (lmsPoolNode->poolAddr != (UINTPTR)pool) { /* pool is a subset of lmsPoolNode->poolAddr */
157 /* do not add it again, just return */
158 PRINT_DEBUG("[LMS]pool %p already on lms checklist !\n", pool);
159 LMS_UNLOCK(intSave);
160 return size; /* return size indicate the shadow memory init successful */
161 } else { /* Re-initialize the same pool, maybe with different size */
162 /* delete the old node, then add a new one */
163 lmsPoolNode->used = LMS_POOL_UNUSED;
164 LOS_ListDelete(&(lmsPoolNode->node));
165 }
166 }
167
168 lmsPoolNode = OsLmsCheckPoolCreate();
169 if (lmsPoolNode == NULL) {
170 PRINT_DEBUG("[LMS]the num of lms check pool is max already !\n");
171 LMS_UNLOCK(intSave);
172 return 0;
173 }
174 realSize = OsLmsPoolResize(size);
175
176 lmsPoolNode->poolAddr = poolAddr;
177 lmsPoolNode->poolSize = realSize;
178 lmsPoolNode->shadowStart = (UINTPTR)poolAddr + realSize;
179 lmsPoolNode->shadowSize = poolAddr + size - lmsPoolNode->shadowStart;
180 /* init shadow value */
181 (VOID)memset((VOID *)lmsPoolNode->shadowStart, LMS_SHADOW_AFTERFREE_U8, lmsPoolNode->shadowSize);
182
183 LOS_ListAdd(&g_lmsCheckPoolList, &(lmsPoolNode->node));
184
185 LMS_UNLOCK(intSave);
186 return realSize;
187}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
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.
Definition: los_list.h:217
void * memset(void *addr, int c, size_t len)
Definition: lms_libc.c:36
LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_lmsCheckPoolList
Definition: los_lms.c:66
STATIC UINT32 OsLmsPoolResize(UINT32 size)
Definition: los_lms.c:81
STATIC LmsMemListNode * OsLmsCheckPoolCreate(VOID)
Definition: los_lms.c:125
unsigned long UINTPTR
Definition: los_typedef.h:68
UINT32 shadowSize
Definition: los_lms_pri.h:86
UINTPTR shadowStart
Definition: los_lms_pri.h:85
LOS_DL_LIST node
Definition: los_lms_pri.h:81
UINTPTR poolAddr
Definition: los_lms_pri.h:83
UINT32 poolSize
Definition: los_lms_pri.h:84
函数调用图:
这是这个函数的调用关系图:

◆ LOS_LmsCheckPoolDel()

VOID LOS_LmsCheckPoolDel ( const VOID *  pool)

在文件 los_lms.c189 行定义.

190{
191 UINT32 intSave;
192 if (pool == NULL) {
193 return;
194 }
195
196 LMS_LOCK(intSave);
197 LmsMemListNode *delNode = OsLmsGetPoolNode(pool);
198 if (delNode == NULL) {
199 PRINT_ERR("[LMS]pool %p is not on lms checklist !\n", pool);
200 goto Release;
201 }
202 delNode->used = LMS_POOL_UNUSED;
203 LOS_ListDelete(&(delNode->node));
204Release:
205 LMS_UNLOCK(intSave);
206}
STATIC LmsMemListNode * OsLmsGetPoolNode(const VOID *pool)
Definition: los_lms.c:86
函数调用图:
这是这个函数的调用关系图:

◆ LOS_MODULE_INIT()

LOS_MODULE_INIT ( OsLmsInit  ,
LOS_INIT_LEVEL_KMOD_PREVM   
)

◆ OsLmsCheckAddr()

STATIC UINT32 OsLmsCheckAddr ( UINTPTR  addr)

在文件 los_lms.c444 行定义.

445{
446 UINT32 intSave;
447 UINT32 shadowValue = INVALID_SHADOW_VALUE;
448 /* do not check nested or before all cpu start */
449 if ((LOS_AtomicRead(&g_checkDepth)) || (!OS_SCHEDULER_ALL_ACTIVE)) {
450 return 0;
451 }
452
453 LMS_LOCK(intSave);
455 if (node == NULL) {
456 LMS_UNLOCK(intSave);
457 return LMS_SHADOW_ACCESSABLE_U8;
458 }
459
460 OsLmsGetShadowValue(node, addr, &shadowValue);
461 LMS_UNLOCK(intSave);
462 return shadowValue;
463}
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
Definition: los_atomic.h:123
STATIC Atomic g_checkDepth
Definition: los_lms.c:67
VOID OsLmsGetShadowValue(LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue)
Definition: los_lms.c:307
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsCheckAddrRegion()

STATIC INLINE UINT32 OsLmsCheckAddrRegion ( UINTPTR  addr,
UINT32  size 
)

在文件 los_lms.c466 行定义.

467{
468 UINT32 i;
469 for (i = 0; i < size; i++) {
470 if (OsLmsCheckAddr(addr + i)) {
471 return LOS_NOK;
472 }
473 }
474 return LOS_OK;
475}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsCheckPoolCreate()

STATIC LmsMemListNode * OsLmsCheckPoolCreate ( VOID  )

在文件 los_lms.c125 行定义.

126{
127 UINT32 i;
128 LmsMemListNode *current = NULL;
129 for (i = 0; i < LOSCFG_LMS_MAX_RECORD_POOL_NUM; i++) {
130 current = &g_lmsCheckPoolArray[i];
131 if (current->used == LMS_POOL_UNUSED) {
132 current->used = LMS_POOL_USED;
133 return current;
134 }
135 }
136 return NULL;
137}
LITE_OS_SEC_BSS STATIC LmsMemListNode g_lmsCheckPoolArray[LOSCFG_LMS_MAX_RECORD_POOL_NUM]
Definition: los_lms.c:65
这是这个函数的调用关系图:

◆ OsLmsCheckValid()

VOID OsLmsCheckValid ( UINTPTR  checkAddr,
BOOL  isFreeCheck 
)

在文件 los_lms.c362 行定义.

363{
364 UINT32 intSave;
365 UINT32 shadowValue = INVALID_SHADOW_VALUE;
366 LMS_LOCK(intSave);
367 LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(checkAddr);
368 if (node == NULL) {
369 LMS_UNLOCK(intSave);
370 return;
371 }
372
373 OsLmsGetShadowValue(node, checkAddr, &shadowValue);
374 LMS_UNLOCK(intSave);
375 if ((shadowValue == LMS_SHADOW_ACCESSABLE) || ((isFreeCheck) && (shadowValue == LMS_SHADOW_PAINT))) {
376 return;
377 }
378
379 OsLmsReportError(checkAddr, MEM_REGION_SIZE_1, isFreeCheck ? FREE_ERRORMODE : COMMON_ERRMODE);
380}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsGetErrorInfo()

STATIC VOID OsLmsGetErrorInfo ( UINTPTR  addr,
UINT32  size,
LmsAddrInfo info 
)

在文件 los_lms.c569 行定义.

570{
572 OsLmsGetShadowInfo(node, addr, info);
573 if (info->shadowValue != LMS_SHADOW_ACCESSABLE_U8) {
574 return;
575 } else {
576 OsLmsGetShadowInfo(node, addr + size - 1, info);
577 }
578}
STATIC INLINE VOID OsLmsGetShadowInfo(LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info)
Definition: los_lms.c:238
UINT32 shadowValue
Definition: los_lms_pri.h:93
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsGetPoolNode()

STATIC LmsMemListNode * OsLmsGetPoolNode ( const VOID *  pool)

在文件 los_lms.c86 行定义.

87{
88 UINTPTR poolAddr = (UINTPTR)pool;
89 LmsMemListNode *current = NULL;
91
93 goto EXIT;
94 }
95
96 LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
97 if (current->poolAddr == poolAddr) {
98 return current;
99 }
100 }
101
102EXIT:
103 return NULL;
104}
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsGetPoolNodeFromAddr()

STATIC LmsMemListNode * OsLmsGetPoolNodeFromAddr ( UINTPTR  addr)

在文件 los_lms.c106 行定义.

107{
108 LmsMemListNode *current = NULL;
109 LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
110
112 goto EXIT;
113 }
114
115 LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
116 if ((addr >= current->poolAddr) && (addr < current->poolAddr + current->poolSize)) {
117 return current;
118 }
119 }
120
121EXIT:
122 return NULL;
123}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsGetShadowInfo()

STATIC INLINE VOID OsLmsGetShadowInfo ( LmsMemListNode node,
UINTPTR  memAddr,
LmsAddrInfo info 
)

在文件 los_lms.c238 行定义.

239{
240 UINTPTR shadowAddr;
241 UINT32 shadowOffset;
242 UINT32 shadowValue;
243
244 if (OsLmsMem2Shadow(node, memAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
245 return;
246 }
247
248 shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
249 info->memAddr = memAddr;
250 info->shadowAddr = shadowAddr;
251 info->shadowOffset = shadowOffset;
252 info->shadowValue = shadowValue;
253}
STATIC INLINE UINT32 OsLmsMem2Shadow(LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset)
Definition: los_lms.c:223
unsigned char UINT8
Definition: los_typedef.h:55
UINTPTR shadowAddr
Definition: los_lms_pri.h:91
UINT32 shadowOffset
Definition: los_lms_pri.h:92
UINTPTR memAddr
Definition: los_lms_pri.h:90
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsGetShadowValue()

VOID OsLmsGetShadowValue ( LmsMemListNode node,
UINTPTR  addr,
UINT32 shadowValue 
)

在文件 los_lms.c307 行定义.

308{
309 UINTPTR shadowAddr;
310 UINT32 shadowOffset;
311 if (OsLmsMem2Shadow(node, addr, &shadowAddr, &shadowOffset) != LOS_OK) {
312 return;
313 }
314
315 *shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
316}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsInit()

STATIC UINT32 OsLmsInit ( VOID  )

初始化 LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具

在文件 los_lms.c208 行定义.

209{
212 static LmsHook hook = {
214 .mallocMark = OsLmsLosMallocMark,
215 .freeMark = OsLmsLosFreeMark,
216 .simpleMark = OsLmsSimpleMark,
217 .check = OsLmsCheckValid,
218 };
219 g_lms = &hook;
220 return LOS_OK;
221}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
LmsHook * g_lms
Definition: los_lms.c:68
UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size)
Definition: los_lms.c:141
VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck)
Definition: los_lms.c:362
VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
Definition: los_lms.c:382
VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
Definition: los_lms.c:318
VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
Definition: los_lms.c:343
UINT32(* init)(const VOID *pool, UINT32 size)
Definition: los_lms_pri.h:97
函数调用图:

◆ OsLmsLosFreeMark()

VOID OsLmsLosFreeMark ( const VOID *  curNodeStart,
const VOID *  nextNodeStart,
UINT32  nodeHeadSize 
)

在文件 los_lms.c382 行定义.

383{
384 UINT32 intSave;
385 UINT32 shadowValue = INVALID_SHADOW_VALUE;
386
387 LMS_LOCK(intSave);
388 LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
389 if (node == NULL) {
390 LMS_UNLOCK(intSave);
391 return;
392 }
393
394 UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
395 UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
396
397 OsLmsGetShadowValue(node, curNodeStartAddr + nodeHeadSize, &shadowValue);
398 if ((shadowValue != LMS_SHADOW_ACCESSABLE) && (shadowValue != LMS_SHADOW_PAINT)) {
399 LMS_UNLOCK(intSave);
400 OsLmsReportError(curNodeStartAddr + nodeHeadSize, MEM_REGION_SIZE_1, FREE_ERRORMODE);
401 return;
402 }
403
404 if (*((UINT8 *)curNodeStart) == 0) { /* if merge the node has memset with 0 */
405 OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
406 }
407 OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_AFTERFREE_U8);
408
409 if (*((UINT8 *)nextNodeStart) == 0) { /* if merge the node has memset with 0 */
410 OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
411 }
412
413 LMS_UNLOCK(intSave);
414}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsLosMallocMark()

VOID OsLmsLosMallocMark ( const VOID *  curNodeStart,
const VOID *  nextNodeStart,
UINT32  nodeHeadSize 
)

在文件 los_lms.c343 行定义.

344{
345 UINT32 intSave;
346 UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
347 UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
348
349 LMS_LOCK(intSave);
350 LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
351 if (node == NULL) {
352 LMS_UNLOCK(intSave);
353 return;
354 }
355
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);
359 LMS_UNLOCK(intSave);
360}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsMem2Shadow()

STATIC INLINE UINT32 OsLmsMem2Shadow ( LmsMemListNode node,
UINTPTR  memAddr,
UINTPTR shadowAddr,
UINT32 shadowOffset 
)

在文件 los_lms.c223 行定义.

224{
225 if ((memAddr < node->poolAddr) || (memAddr >= node->poolAddr + node->poolSize)) { /* check ptr valid */
226 PRINT_ERR("[LMS]memAddr %p is not in pool region [%p, %p)\n", memAddr, node->poolAddr,
227 node->poolAddr + node->poolSize);
228 return LOS_NOK;
229 }
230
231 UINT32 memOffset = 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; /* (memOffset % 16) / 4 */
235 return LOS_OK;
236}
这是这个函数的调用关系图:

◆ OsLmsPoolResize()

STATIC UINT32 OsLmsPoolResize ( UINT32  size)

在文件 los_lms.c81 行定义.

82{
83 return OS_MEM_ALIGN_BACK(LMS_POOL_RESIZE(size), POOL_ADDR_ALIGNSIZE);
84}
这是这个函数的调用关系图:

◆ OsLmsPrintErrInfo()

STATIC VOID OsLmsPrintErrInfo ( LmsAddrInfo info,
UINT32  errMod 
)

在文件 los_lms.c580 行定义.

581{
582 switch (info->shadowValue) {
583 case LMS_SHADOW_AFTERFREE:
584 PRINT_ERR("Use after free error detected\n");
585 break;
586 case LMS_SHADOW_REDZONE:
587 PRINT_ERR("Heap buffer overflow error detected\n");
588 break;
589 case LMS_SHADOW_ACCESSABLE:
590 PRINT_ERR("No error\n");
591 break;
592 default:
593 PRINT_ERR("UnKnown Error detected\n");
594 break;
595 }
596
597 switch (errMod) {
598 case FREE_ERRORMODE:
599 PRINT_ERR("Illegal Double free address at: [0x%lx]\n", info->memAddr);
600 break;
601 case LOAD_ERRMODE:
602 PRINT_ERR("Illegal READ address at: [0x%lx]\n", info->memAddr);
603 break;
604 case STORE_ERRMODE:
605 PRINT_ERR("Illegal WRITE address at: [0x%lx]\n", info->memAddr);
606 break;
607 case COMMON_ERRMODE:
608 PRINT_ERR("Common Error at: [0x%lx]\n", info->memAddr);
609 break;
610 default:
611 PRINT_ERR("UnKnown Error mode at: [0x%lx]\n", info->memAddr);
612 break;
613 }
614
615 PRINT_ERR("Shadow memory address: [0x%lx : %1u] Shadow memory value: [%u] \n", info->shadowAddr,
616 info->shadowOffset, info->shadowValue);
617}
这是这个函数的调用关系图:

◆ OsLmsPrintMemInfo()

VOID OsLmsPrintMemInfo ( UINTPTR  addr)

在文件 los_lms.c509 行定义.

510{
511#define LMS_DUMP_OFFSET 16
512#define LMS_DUMP_RANGE_DOUBLE 2
513
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;
518 UINT32 shadowValue = 0;
519 UINTPTR shadowAddr = 0;
520 UINT32 shadowOffset = 0;
521 LmsMemListNode *nodeInfo = NULL;
522 INT32 isCheckAddr, x, y;
523
524 nodeInfo = OsLmsGetPoolNodeFromAddr(addr);
525 if (nodeInfo == NULL) {
526 PRINT_ERR("[LMS]addr is not in checkpool\n");
527 return;
528 }
529
530 for (y = 0; y < printY; y++, dumpAddr += printX) {
531 if (dumpAddr < nodeInfo->poolAddr) { /* find util dumpAddr in pool region */
532 continue;
533 }
534
535 if ((dumpAddr + printX) >=
536 nodeInfo->poolAddr + nodeInfo->poolSize) { /* finish if dumpAddr exceeds pool's upper region */
537 goto END;
538 }
539
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));
544 } else {
545 PRINTK(" %02x ", *(UINT8 *)(dumpAddr + x));
546 }
547 }
548
549 if (OsLmsMem2Shadow(nodeInfo, dumpAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
550 goto END;
551 }
552
553 PRINTK("|\t[0x%x | %2u]: ", shadowAddr, shadowOffset);
554
555 for (x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) {
556 OsLmsGetShadowValue(nodeInfo, dumpAddr + x, &shadowValue);
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);
560 } else {
561 PRINTK(" %1x ", shadowValue);
562 }
563 }
564 }
565END:
566 PRINTK("\n");
567}
signed int INT32
Definition: los_typedef.h:60
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsPrintPoolListInfo()

VOID OsLmsPrintPoolListInfo ( VOID  )

在文件 los_lms.c488 行定义.

489{
490 UINT32 count = 0;
491 UINT32 intSave;
492 LmsMemListNode *current = NULL;
493 LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
494
495 LMS_LOCK(intSave);
496 LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node)
497 {
498 count++;
499 PRINT_DEBUG(
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",
502 count, current->poolSize + current->shadowSize, current->poolAddr, current->poolAddr + current->poolSize,
503 current->poolSize, current->shadowStart, current->shadowSize);
504 }
505
506 LMS_UNLOCK(intSave);
507}

◆ OsLmsReportError()

VOID OsLmsReportError ( UINTPTR  p,
UINT32  size,
UINT32  errMod 
)

在文件 los_lms.c619 行定义.

620{
621 UINT32 intSave;
622 LmsAddrInfo info;
623
624 (VOID)LOS_AtomicAdd(&g_checkDepth, 1);
625 LMS_LOCK(intSave);
626 (VOID)memset(&info, 0, sizeof(LmsAddrInfo));
627
628 PRINT_ERR("***** Kernel Address Sanitizer Error Detected Start *****\n");
629
630 OsLmsGetErrorInfo(p, size, &info);
631
632 OsLmsPrintErrInfo(&info, errMod);
633
634 OsBackTrace();
635
637 LMS_UNLOCK(intSave);
638 PRINT_ERR("***** Kernel Address Sanitizer Error Detected End *****\n");
639 (VOID)LOS_AtomicSub(&g_checkDepth, 1);
640}
STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
Atomic addition.
Definition: los_atomic.h:173
STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal)
Atomic subtraction.
Definition: los_atomic.h:217
VOID OsBackTrace(VOID)
Kernel backtrace function.
Definition: los_exc.c:1025
STATIC VOID OsLmsPrintErrInfo(LmsAddrInfo *info, UINT32 errMod)
Definition: los_lms.c:580
VOID OsLmsPrintMemInfo(UINTPTR addr)
Definition: los_lms.c:509
STATIC VOID OsLmsGetErrorInfo(UINTPTR addr, UINT32 size, LmsAddrInfo *info)
Definition: los_lms.c:569
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsSetShadowValue()

VOID OsLmsSetShadowValue ( LmsMemListNode node,
UINTPTR  startAddr,
UINTPTR  endAddr,
UINT8  value 
)

在文件 los_lms.c255 行定义.

256{
257 UINTPTR shadowStart;
258 UINTPTR shadowEnd;
259 UINT32 startOffset;
260 UINT32 endOffset;
261
262 UINT8 shadowValueMask;
263 UINT8 shadowValue;
264
265 /* endAddr -1, then we mark [startAddr, endAddr) to value */
266 if (OsLmsMem2Shadow(node, startAddr, &shadowStart, &startOffset) ||
267 OsLmsMem2Shadow(node, endAddr - 1, &shadowEnd, &endOffset)) {
268 return;
269 }
270
271 if (shadowStart == shadowEnd) { /* in the same u8 */
272 /* because endAddr - 1, the endOffset falls into the previous cell,
273 so endOffset + 2 is required for calculation */
274 shadowValueMask = LMS_SHADOW_MASK_U8;
275 shadowValueMask =
276 (shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)));
277 shadowValue = value & shadowValueMask;
278 *(UINT8 *)shadowStart &= ~shadowValueMask;
279 *(UINT8 *)shadowStart |= shadowValue;
280 } else {
281 /* Adjust startAddr to left util it reach the beginning of a u8 */
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;
288 shadowStart += 1;
289 }
290
291 /* Adjust endAddr to right util it reach the end of a u8 */
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;
298 shadowEnd -= 1;
299 }
300
301 if (shadowEnd + 1 > shadowStart) {
302 (VOID)memset((VOID *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart);
303 }
304 }
305}
函数调用图:
这是这个函数的调用关系图:

◆ OsLmsSimpleMark()

VOID OsLmsSimpleMark ( UINTPTR  startAddr,
UINTPTR  endAddr,
UINT32  value 
)

在文件 los_lms.c318 行定义.

319{
320 UINT32 intSave;
321 if (endAddr <= startAddr) {
322 PRINT_DEBUG("[LMS]mark 0x%x, 0x%x, 0x%x\n", startAddr, endAddr, (UINTPTR)__builtin_return_address(0));
323 return;
324 }
325
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);
328 return;
329 }
330
331 LMS_LOCK(intSave);
332
333 LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(startAddr);
334 if (node == NULL) {
335 LMS_UNLOCK(intSave);
336 return;
337 }
338
339 OsLmsSetShadowValue(node, startAddr, endAddr, value);
340 LMS_UNLOCK(intSave);
341}
函数调用图:
这是这个函数的调用关系图:

◆ SPIN_LOCK_INIT()

LITE_OS_SEC_BSS SPIN_LOCK_INIT ( g_lmsSpin  )

变量说明

◆ g_checkDepth

STATIC Atomic g_checkDepth = 0

在文件 los_lms.c67 行定义.

◆ g_lms

LmsHook* g_lms = NULL

在文件 los_lms.c68 行定义.

◆ g_lmsCheckPoolArray

LITE_OS_SEC_BSS STATIC LmsMemListNode g_lmsCheckPoolArray[LOSCFG_LMS_MAX_RECORD_POOL_NUM]

在文件 los_lms.c65 行定义.

◆ g_lmsCheckPoolList

LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_lmsCheckPoolList

在文件 los_lms.c66 行定义.