• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_lms_pri.h"
33 #include "los_config.h"
34 #include "los_debug.h"
35 #if (LOSCFG_KERNEL_SMP == 1)
36 #include "los_spinlock.h"
37 #else
38 #include "los_interrupt.h"
39 #endif
40 
41 #if (LOSCFG_BACKTRACE_TYPE != 0)
42 #include "los_backtrace.h"
43 #endif
44 #include "los_sched.h"
45 
46 LITE_OS_SEC_BSS STATIC LmsMemListNode g_lmsCheckPoolArray[LOSCFG_LMS_MAX_RECORD_POOL_NUM];
47 LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_lmsCheckPoolList;
48 STATIC UINT32 g_checkDepth = 0;
49 LmsHook *g_lms = NULL;
50 
51 #if (LOSCFG_KERNEL_SMP == 1)
52 LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_lmsSpin);
53 #define LMS_LOCK(state)                 LOS_SpinLockSave(&g_lmsSpin, &(state))
54 #define LMS_UNLOCK(state)               LOS_SpinUnlockRestore(&g_lmsSpin, (state))
55 #else
56 #define LMS_LOCK(state)                 (state) = LOS_IntLock()
57 #define LMS_UNLOCK(state)               LOS_IntRestore(state)
58 #endif
59 
60 #define OS_MEM_ALIGN_BACK(value, align) (((UINT32)(value)) & ~((UINT32)((align) - 1)))
61 #define IS_ALIGNED(value, align)        ((((UINTPTR)(value)) & ((UINTPTR)((align) - 1))) == 0)
62 #define OS_MEM_ALIGN_SIZE               sizeof(UINTPTR)
63 #define POOL_ADDR_ALIGNSIZE             64
64 #define LMS_POOL_UNUSED                 0
65 #define LMS_POOL_USED                   1
66 #define INVALID_SHADOW_VALUE            0xFFFFFFFF
67 
OsLmsPoolResize(UINT32 size)68 STATIC UINT32 OsLmsPoolResize(UINT32 size)
69 {
70     return OS_MEM_ALIGN_BACK(LMS_POOL_RESIZE(size), POOL_ADDR_ALIGNSIZE);
71 }
72 
OsLmsGetPoolNode(const VOID * pool)73 STATIC LmsMemListNode *OsLmsGetPoolNode(const VOID *pool)
74 {
75     UINTPTR poolAddr = (UINTPTR)pool;
76     LmsMemListNode *current = NULL;
77     LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
78 
79     if (LOS_ListEmpty(&g_lmsCheckPoolList)) {
80         goto EXIT;
81     }
82 
83     LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
84         if (current->poolAddr == poolAddr) {
85             return current;
86         }
87     }
88 
89 EXIT:
90     return NULL;
91 }
92 
OsLmsGetPoolNodeFromAddr(UINTPTR addr)93 STATIC LmsMemListNode *OsLmsGetPoolNodeFromAddr(UINTPTR addr)
94 {
95     LmsMemListNode *current = NULL;
96     LmsMemListNode *previous = NULL;
97     LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
98 
99     if (LOS_ListEmpty(&g_lmsCheckPoolList)) {
100         return NULL;
101     }
102 
103     LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
104         if ((addr < current->poolAddr) || (addr >= (current->poolAddr + current->poolSize))) {
105             continue;
106         }
107         if ((previous == NULL) ||
108             ((previous->poolAddr <= current->poolAddr) &&
109             ((current->poolAddr + current->poolSize) <= (previous->poolAddr + previous->poolSize)))) {
110             previous = current;
111         }
112     }
113 
114     return previous;
115 }
116 
OsLmsCheckPoolCreate(VOID)117 STATIC LmsMemListNode *OsLmsCheckPoolCreate(VOID)
118 {
119     UINT32 i;
120     LmsMemListNode *current = NULL;
121     for (i = 0; i < LOSCFG_LMS_MAX_RECORD_POOL_NUM; i++) {
122         current = &g_lmsCheckPoolArray[i];
123         if (current->used == LMS_POOL_UNUSED) {
124             current->used = LMS_POOL_USED;
125             return current;
126         }
127     }
128     return NULL;
129 }
130 
LOS_LmsCheckPoolAdd(const VOID * pool,UINT32 size)131 UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size)
132 {
133     UINT32 intSave;
134     UINTPTR poolAddr = (UINTPTR)pool;
135     UINT32 realSize;
136     LmsMemListNode *lmsPoolNode = NULL;
137 
138     if (pool == NULL) {
139         return 0;
140     }
141 
142     LMS_LOCK(intSave);
143 
144     lmsPoolNode = OsLmsGetPoolNode(pool);
145     if (lmsPoolNode != NULL) { /* if pool already on checklist */
146         /* Re-initialize the same pool, maybe with different size */
147         /* delete the old node, then add a new one */
148         lmsPoolNode->used = LMS_POOL_UNUSED;
149         LOS_ListDelete(&(lmsPoolNode->node));
150     }
151 
152     lmsPoolNode = OsLmsCheckPoolCreate();
153     if (lmsPoolNode == NULL) {
154         PRINT_DEBUG("[LMS]the num of lms check pool is max already !\n");
155         LMS_UNLOCK(intSave);
156         return 0;
157     }
158     realSize = OsLmsPoolResize(size);
159 
160     lmsPoolNode->poolAddr = poolAddr;
161     lmsPoolNode->poolSize = realSize;
162     lmsPoolNode->shadowStart = (UINTPTR)poolAddr + realSize;
163     lmsPoolNode->shadowSize = poolAddr + size - lmsPoolNode->shadowStart;
164     /* init shadow value */
165     (VOID)memset_s((VOID *)lmsPoolNode->shadowStart, lmsPoolNode->shadowSize, LMS_SHADOW_AFTERFREE_U8,
166                    lmsPoolNode->shadowSize);
167 
168     LOS_ListAdd(&g_lmsCheckPoolList, &(lmsPoolNode->node));
169 
170     LMS_UNLOCK(intSave);
171     return realSize;
172 }
173 
LOS_LmsCheckPoolDel(const VOID * pool)174 VOID LOS_LmsCheckPoolDel(const VOID *pool)
175 {
176     UINT32 intSave;
177     if (pool == NULL) {
178         return;
179     }
180 
181     LMS_LOCK(intSave);
182     LmsMemListNode *delNode = OsLmsGetPoolNode(pool);
183     if (delNode == NULL) {
184         PRINT_ERR("[LMS]pool %p is not on lms checklist !\n", pool);
185         goto RELEASE;
186     }
187     delNode->used = LMS_POOL_UNUSED;
188     LOS_ListDelete(&(delNode->node));
189 
190 RELEASE:
191     LMS_UNLOCK(intSave);
192 }
193 
OsLmsInit(VOID)194 VOID OsLmsInit(VOID)
195 {
196     (VOID)memset_s(g_lmsCheckPoolArray, sizeof(g_lmsCheckPoolArray), 0, sizeof(g_lmsCheckPoolArray));
197     LOS_ListInit(&g_lmsCheckPoolList);
198     static LmsHook hook = {
199         .init = LOS_LmsCheckPoolAdd,
200         .deInit = LOS_LmsCheckPoolDel,
201         .mallocMark = OsLmsLosMallocMark,
202         .freeMark = OsLmsLosFreeMark,
203         .simpleMark = OsLmsSimpleMark,
204         .check = OsLmsCheckValid,
205     };
206     g_lms = &hook;
207 }
208 
OsLmsMem2Shadow(LmsMemListNode * node,UINTPTR memAddr,UINTPTR * shadowAddr,UINT32 * shadowOffset)209 STATIC INLINE UINT32 OsLmsMem2Shadow(LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset)
210 {
211     if ((memAddr < node->poolAddr) || (memAddr >= node->poolAddr + node->poolSize)) { /* check ptr valid */
212         PRINT_ERR("[LMS]memAddr %p is not in pool region [%p, %p)\n", memAddr, node->poolAddr,
213             node->poolAddr + node->poolSize);
214         return LOS_NOK;
215     }
216 
217     UINT32 memOffset = memAddr - node->poolAddr;
218     *shadowAddr = node->shadowStart + memOffset / LMS_SHADOW_U8_REFER_BYTES;
219     *shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) *
220         LMS_SHADOW_BITS_PER_CELL; /* (memOffset % 16) / 4 */
221     return LOS_OK;
222 }
223 
OsLmsGetShadowInfo(LmsMemListNode * node,UINTPTR memAddr,LmsAddrInfo * info)224 STATIC INLINE VOID OsLmsGetShadowInfo(LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info)
225 {
226     UINTPTR shadowAddr;
227     UINT32 shadowOffset;
228     UINT32 shadowValue;
229 
230     if (OsLmsMem2Shadow(node, memAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
231         return;
232     }
233 
234     shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
235     info->memAddr = memAddr;
236     info->shadowAddr = shadowAddr;
237     info->shadowOffset = shadowOffset;
238     info->shadowValue = shadowValue;
239 }
240 
OsLmsSetShadowValue(LmsMemListNode * node,UINTPTR startAddr,UINTPTR endAddr,UINT8 value)241 VOID OsLmsSetShadowValue(LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value)
242 {
243     UINTPTR shadowStart;
244     UINTPTR shadowEnd;
245     UINT32 startOffset;
246     UINT32 endOffset;
247 
248     UINT8 shadowValueMask;
249     UINT8 shadowValue;
250 
251     /* endAddr -1, then we mark [startAddr, endAddr) to value */
252     if (OsLmsMem2Shadow(node, startAddr, &shadowStart, &startOffset) ||
253         OsLmsMem2Shadow(node, endAddr - 1, &shadowEnd, &endOffset)) {
254         return;
255     }
256 
257     if (shadowStart == shadowEnd) { /* in the same u8 */
258         /* because endAddr - 1, the endOffset falls into the previous cell,
259         so endOffset + 2 is required for calculation */
260         shadowValueMask = LMS_SHADOW_MASK_U8;
261         shadowValueMask =
262             (shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)));
263         shadowValue = value & shadowValueMask;
264         *(UINT8 *)shadowStart &= ~shadowValueMask;
265         *(UINT8 *)shadowStart |= shadowValue;
266     } else {
267         /* Adjust startAddr to left util it reach the beginning of a u8 */
268         if (startOffset > 0) {
269             shadowValueMask = LMS_SHADOW_MASK_U8;
270             shadowValueMask = shadowValueMask << startOffset;
271             shadowValue = value & shadowValueMask;
272             *(UINT8 *)shadowStart &= ~shadowValueMask;
273             *(UINT8 *)shadowStart |= shadowValue;
274             shadowStart += 1;
275         }
276 
277         /* Adjust endAddr to right util it reach the end of a u8 */
278         if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) {
279             shadowValueMask = LMS_SHADOW_MASK_U8;
280             shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL));
281             shadowValue = value & shadowValueMask;
282             *(UINT8 *)shadowEnd &= ~shadowValueMask;
283             *(UINT8 *)shadowEnd |= shadowValue;
284             shadowEnd -= 1;
285         }
286 
287         if (shadowEnd + 1 > shadowStart) {
288             (VOID)memset((VOID *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart);
289         }
290     }
291 }
292 
OsLmsGetShadowValue(LmsMemListNode * node,UINTPTR addr,UINT32 * shadowValue)293 VOID OsLmsGetShadowValue(LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue)
294 {
295     UINTPTR shadowAddr;
296     UINT32 shadowOffset;
297     if (OsLmsMem2Shadow(node, addr, &shadowAddr, &shadowOffset) != LOS_OK) {
298         return;
299     }
300 
301     *shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
302 }
303 
OsLmsSimpleMark(UINTPTR startAddr,UINTPTR endAddr,UINT32 value)304 VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
305 {
306     UINT32 intSave;
307     if (endAddr <= startAddr) {
308         PRINT_DEBUG("[LMS]mark 0x%x, 0x%x, 0x%x\n", startAddr, endAddr, (UINTPTR)__builtin_return_address(0));
309         return;
310     }
311 
312     if (!IS_ALIGNED(startAddr, OS_MEM_ALIGN_SIZE) || !IS_ALIGNED(endAddr, OS_MEM_ALIGN_SIZE)) {
313         PRINT_ERR("[LMS]mark addr is not aligned! 0x%x, 0x%x\n", startAddr, endAddr);
314         return;
315     }
316 
317     LMS_LOCK(intSave);
318 
319     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(startAddr);
320     if (node == NULL) {
321         LMS_UNLOCK(intSave);
322         return;
323     }
324 
325     OsLmsSetShadowValue(node, startAddr, endAddr, value);
326     LMS_UNLOCK(intSave);
327 }
328 
OsLmsLosMallocMark(const VOID * curNodeStart,const VOID * nextNodeStart,UINT32 nodeHeadSize)329 VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
330 {
331     UINT32 intSave;
332     UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
333     UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
334 
335     LMS_LOCK(intSave);
336     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
337     if (node == NULL) {
338         LMS_UNLOCK(intSave);
339         return;
340     }
341 
342     OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
343     OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_ACCESSIBLE_U8);
344     OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
345     LMS_UNLOCK(intSave);
346 }
347 
OsLmsCheckValid(UINTPTR checkAddr,BOOL isFreeCheck)348 VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck)
349 {
350     UINT32 intSave;
351     UINT32 shadowValue = INVALID_SHADOW_VALUE;
352     LMS_LOCK(intSave);
353     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(checkAddr);
354     if (node == NULL) {
355         LMS_UNLOCK(intSave);
356         return;
357     }
358 
359     OsLmsGetShadowValue(node, checkAddr, &shadowValue);
360     LMS_UNLOCK(intSave);
361     if ((shadowValue == LMS_SHADOW_ACCESSIBLE) || ((isFreeCheck) && (shadowValue == LMS_SHADOW_PAINT))) {
362         return;
363     }
364 
365     OsLmsReportError(checkAddr, MEM_REGION_SIZE_1, isFreeCheck ? FREE_ERRORMODE : COMMON_ERRMODE);
366 }
367 
OsLmsLosFreeMark(const VOID * curNodeStart,const VOID * nextNodeStart,UINT32 nodeHeadSize)368 VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
369 {
370     UINT32 intSave;
371     UINT32 shadowValue = INVALID_SHADOW_VALUE;
372 
373     LMS_LOCK(intSave);
374     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
375     if (node == NULL) {
376         LMS_UNLOCK(intSave);
377         return;
378     }
379 
380     UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
381     UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
382 
383     OsLmsGetShadowValue(node, curNodeStartAddr + nodeHeadSize, &shadowValue);
384     if ((shadowValue != LMS_SHADOW_ACCESSIBLE) && (shadowValue != LMS_SHADOW_PAINT)) {
385         LMS_UNLOCK(intSave);
386         OsLmsReportError(curNodeStartAddr + nodeHeadSize, MEM_REGION_SIZE_1, FREE_ERRORMODE);
387         return;
388     }
389 
390     if (*((UINT8 *)curNodeStart) == 0) { /* if merge the node has memset with 0 */
391         OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
392     }
393     OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_AFTERFREE_U8);
394 
395     if (*((UINT8 *)nextNodeStart) == 0) { /* if merge the node has memset with 0 */
396         OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
397     }
398 
399     LMS_UNLOCK(intSave);
400 }
401 
LOS_LmsAddrProtect(UINTPTR addrStart,UINTPTR addrEnd)402 VOID LOS_LmsAddrProtect(UINTPTR addrStart, UINTPTR addrEnd)
403 {
404     UINT32 intSave;
405     if (addrEnd <= addrStart) {
406         return;
407     }
408     LMS_LOCK(intSave);
409     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
410     if (node != NULL) {
411         OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_REDZONE_U8);
412     }
413     LMS_UNLOCK(intSave);
414 }
415 
LOS_LmsAddrDisableProtect(UINTPTR addrStart,UINTPTR addrEnd)416 VOID LOS_LmsAddrDisableProtect(UINTPTR addrStart, UINTPTR addrEnd)
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_ACCESSIBLE_U8);
426     }
427     LMS_UNLOCK(intSave);
428 }
429 
OsLmsCheckAddr(UINTPTR addr)430 STATIC UINT32 OsLmsCheckAddr(UINTPTR addr)
431 {
432     UINT32 intSave;
433     UINT32 shadowValue = INVALID_SHADOW_VALUE;
434     /* do not check nested or before all cpu start */
435     LMS_LOCK(intSave);
436     if ((g_checkDepth != 0) || (!g_taskScheduled)) {
437         LMS_UNLOCK(intSave);
438         return 0;
439     }
440 
441     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr);
442     if (node == NULL) {
443         LMS_UNLOCK(intSave);
444         return LMS_SHADOW_ACCESSIBLE_U8;
445     }
446 
447     OsLmsGetShadowValue(node, addr, &shadowValue);
448     LMS_UNLOCK(intSave);
449     return shadowValue;
450 }
451 
452 #if (LOSCFG_LMS_CHECK_STRICT == 1)
OsLmsCheckAddrRegion(UINTPTR addr,UINT32 size)453 STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
454 {
455     UINT32 i;
456     for (i = 0; i < size; i++) {
457         if (OsLmsCheckAddr(addr + i)) {
458             return LOS_NOK;
459         }
460     }
461     return LOS_OK;
462 }
463 
464 #else
OsLmsCheckAddrRegion(UINTPTR addr,UINT32 size)465 STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
466 {
467     if (OsLmsCheckAddr(addr) || OsLmsCheckAddr(addr + size - 1)) {
468         return LOS_NOK;
469     } else {
470         return LOS_OK;
471     }
472 }
473 #endif
474 
OsLmsPrintPoolListInfo(VOID)475 VOID OsLmsPrintPoolListInfo(VOID)
476 {
477     UINT32 count = 0;
478     UINT32 intSave;
479     LmsMemListNode *current = NULL;
480     LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
481 
482     LMS_LOCK(intSave);
483     LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node)
484     {
485         count++;
486         PRINT_DEBUG(
487             "[LMS]memory pool[%1u]: totalsize 0x%-8x  memstart 0x%-8x memstop 0x%-8x memsize 0x%-8x shadowstart 0x%-8x "
488             "shadowSize 0x%-8x\n",
489             count, current->poolSize + current->shadowSize, current->poolAddr, current->poolAddr + current->poolSize,
490             current->poolSize, current->shadowStart, current->shadowSize);
491     }
492 
493     LMS_UNLOCK(intSave);
494 }
495 
OsLmsPrintMemInfo(UINTPTR addr)496 VOID OsLmsPrintMemInfo(UINTPTR addr)
497 {
498 #define LMS_DUMP_OFFSET 16
499 #define LMS_DUMP_RANGE_DOUBLE 2
500 
501     PRINTK("\n[LMS] Dump info around address [0x%8x]:\n", addr);
502     const UINT32 printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1;
503     const UINT32 printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE;
504     UINTPTR dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX;
505     UINT32 shadowValue = 0;
506     UINTPTR shadowAddr = 0;
507     UINT32 shadowOffset = 0;
508     LmsMemListNode *nodeInfo = NULL;
509     INT32 isCheckAddr, x, y;
510 
511     nodeInfo = OsLmsGetPoolNodeFromAddr(addr);
512     if (nodeInfo == NULL) {
513         PRINT_ERR("[LMS]addr is not in checkpool\n");
514         return;
515     }
516 
517     for (y = 0; y < printY; y++, dumpAddr += printX) {
518         if (dumpAddr < nodeInfo->poolAddr) { /* find util dumpAddr in pool region */
519             continue;
520         }
521 
522         if ((dumpAddr + printX) >=
523             nodeInfo->poolAddr + nodeInfo->poolSize) { /* finish if dumpAddr exceeds pool's upper region */
524             goto END;
525         }
526 
527         PRINTK("\n\t[0x%x]: ", dumpAddr);
528         for (x = 0; x < printX; x++) {
529             if ((dumpAddr + x) == addr) {
530                 PRINTK("[%02x]", *(UINT8 *)(dumpAddr + x));
531             } else {
532                 PRINTK(" %02x ", *(UINT8 *)(dumpAddr + x));
533             }
534         }
535 
536         if (OsLmsMem2Shadow(nodeInfo, dumpAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
537             goto END;
538         }
539 
540         PRINTK("|\t[0x%x | %2u]: ", shadowAddr, shadowOffset);
541 
542         for (x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) {
543             OsLmsGetShadowValue(nodeInfo, dumpAddr + x, &shadowValue);
544             isCheckAddr = dumpAddr + x - (UINTPTR)addr + LMS_MEM_BYTES_PER_SHADOW_CELL;
545             if ((isCheckAddr > 0) && (isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL)) {
546                 PRINTK("[%1x]", shadowValue);
547             } else {
548                 PRINTK(" %1x ", shadowValue);
549             }
550         }
551     }
552 END:
553     PRINTK("\n");
554 }
555 
OsLmsGetErrorInfo(UINTPTR addr,UINT32 size,LmsAddrInfo * info)556 STATIC VOID OsLmsGetErrorInfo(UINTPTR addr, UINT32 size, LmsAddrInfo *info)
557 {
558     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr);
559     OsLmsGetShadowInfo(node, addr, info);
560     if (info->shadowValue != LMS_SHADOW_ACCESSIBLE_U8) {
561         return;
562     } else {
563         OsLmsGetShadowInfo(node, addr + size - 1, info);
564     }
565 }
566 
OsLmsPrintErrInfo(LmsAddrInfo * info,UINT32 errMod)567 STATIC VOID OsLmsPrintErrInfo(LmsAddrInfo *info, UINT32 errMod)
568 {
569     switch (info->shadowValue) {
570         case LMS_SHADOW_AFTERFREE:
571             PRINT_ERR("Use after free error detected\n");
572             break;
573         case LMS_SHADOW_REDZONE:
574             PRINT_ERR("Heap buffer overflow error detected\n");
575             break;
576         case LMS_SHADOW_ACCESSIBLE:
577             PRINT_ERR("No error\n");
578             break;
579         default:
580             PRINT_ERR("UnKnown Error detected\n");
581             break;
582     }
583 
584     switch (errMod) {
585         case FREE_ERRORMODE:
586             PRINT_ERR("Illegal Double free address at: [0x%lx]\n", info->memAddr);
587             break;
588         case LOAD_ERRMODE:
589             PRINT_ERR("Illegal READ address at: [0x%lx]\n", info->memAddr);
590             break;
591         case STORE_ERRMODE:
592             PRINT_ERR("Illegal WRITE address at: [0x%lx]\n", info->memAddr);
593             break;
594         case COMMON_ERRMODE:
595             PRINT_ERR("Common Error at: [0x%lx]\n", info->memAddr);
596             break;
597         default:
598             PRINT_ERR("UnKnown Error mode at: [0x%lx]\n", info->memAddr);
599             break;
600     }
601 
602     PRINT_ERR("Shadow memory address: [0x%lx : %1u]  Shadow memory value: [%u] \n", info->shadowAddr,
603         info->shadowOffset, info->shadowValue);
604 }
605 
OsLmsReportError(UINTPTR p,UINT32 size,UINT32 errMod)606 VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod)
607 {
608     UINT32 intSave;
609     LmsAddrInfo info;
610 
611     LMS_LOCK(intSave);
612     g_checkDepth += 1;
613     (VOID)memset_s(&info, sizeof(LmsAddrInfo), 0, sizeof(LmsAddrInfo));
614 
615     PRINT_ERR("*****  Kernel Address Sanitizer Error Detected Start *****\n");
616 
617     OsLmsGetErrorInfo(p, size, &info);
618 
619     OsLmsPrintErrInfo(&info, errMod);
620 #if (LOSCFG_BACKTRACE_TYPE != 0)
621     LOS_BackTrace();
622 #endif
623     OsLmsPrintMemInfo(info.memAddr);
624     g_checkDepth -= 1;
625     LMS_UNLOCK(intSave);
626     PRINT_ERR("*****  Kernel Address Sanitizer Error Detected End *****\n");
627 }
628 
629 #if (LOSCFG_LMS_STORE_CHECK == 1)
__asan_store1_noabort(UINTPTR p)630 VOID __asan_store1_noabort(UINTPTR p)
631 {
632     if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSIBLE_U8) {
633         OsLmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE);
634     }
635 }
636 
__asan_store2_noabort(UINTPTR p)637 VOID __asan_store2_noabort(UINTPTR p)
638 {
639     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
640         OsLmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE);
641     }
642 }
643 
__asan_store4_noabort(UINTPTR p)644 VOID __asan_store4_noabort(UINTPTR p)
645 {
646     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
647         OsLmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE);
648     }
649 }
650 
__asan_store8_noabort(UINTPTR p)651 VOID __asan_store8_noabort(UINTPTR p)
652 {
653     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
654         OsLmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE);
655     }
656 }
657 
__asan_store16_noabort(UINTPTR p)658 VOID __asan_store16_noabort(UINTPTR p)
659 {
660     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
661         OsLmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE);
662     }
663 }
664 
__asan_storeN_noabort(UINTPTR p,UINT32 size)665 VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
666 {
667     if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
668         OsLmsReportError(p, size, STORE_ERRMODE);
669     }
670 }
671 #else
__asan_store1_noabort(UINTPTR p)672 VOID __asan_store1_noabort(UINTPTR p)
673 {
674     (VOID)p;
675 }
676 
__asan_store2_noabort(UINTPTR p)677 VOID __asan_store2_noabort(UINTPTR p)
678 {
679     (VOID)p;
680 }
681 
__asan_store4_noabort(UINTPTR p)682 VOID __asan_store4_noabort(UINTPTR p)
683 {
684     (VOID)p;
685 }
686 
__asan_store8_noabort(UINTPTR p)687 VOID __asan_store8_noabort(UINTPTR p)
688 {
689     (VOID)p;
690 }
691 
__asan_store16_noabort(UINTPTR p)692 VOID __asan_store16_noabort(UINTPTR p)
693 {
694     (VOID)p;
695 }
696 
__asan_storeN_noabort(UINTPTR p,UINT32 size)697 VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
698 {
699     (VOID)p;
700     (VOID)size;
701 }
702 
703 #endif
704 
705 #if (LOSCFG_LMS_LOAD_CHECK == 1)
__asan_load1_noabort(UINTPTR p)706 VOID __asan_load1_noabort(UINTPTR p)
707 {
708     if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSIBLE_U8) {
709         OsLmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE);
710     }
711 }
712 
__asan_load2_noabort(UINTPTR p)713 VOID __asan_load2_noabort(UINTPTR p)
714 {
715     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
716         OsLmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE);
717     }
718 }
719 
__asan_load4_noabort(UINTPTR p)720 VOID __asan_load4_noabort(UINTPTR p)
721 {
722     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
723         OsLmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE);
724     }
725 }
726 
__asan_load8_noabort(UINTPTR p)727 VOID __asan_load8_noabort(UINTPTR p)
728 {
729     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
730         OsLmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE);
731     }
732 }
733 
__asan_load16_noabort(UINTPTR p)734 VOID __asan_load16_noabort(UINTPTR p)
735 {
736     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
737         OsLmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE);
738     }
739 }
740 
__asan_loadN_noabort(UINTPTR p,UINT32 size)741 VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
742 {
743     if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
744         OsLmsReportError(p, size, LOAD_ERRMODE);
745     }
746 }
747 #else
__asan_load1_noabort(UINTPTR p)748 VOID __asan_load1_noabort(UINTPTR p)
749 {
750     (VOID)p;
751 }
752 
__asan_load2_noabort(UINTPTR p)753 VOID __asan_load2_noabort(UINTPTR p)
754 {
755     (VOID)p;
756 }
757 
__asan_load4_noabort(UINTPTR p)758 VOID __asan_load4_noabort(UINTPTR p)
759 {
760     (VOID)p;
761 }
762 
__asan_load8_noabort(UINTPTR p)763 VOID __asan_load8_noabort(UINTPTR p)
764 {
765     (VOID)p;
766 }
767 
__asan_load16_noabort(UINTPTR p)768 VOID __asan_load16_noabort(UINTPTR p)
769 {
770     (VOID)p;
771 }
772 
__asan_loadN_noabort(UINTPTR p,UINT32 size)773 VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
774 {
775     (VOID)p;
776     (VOID)size;
777 }
778 #endif
__asan_handle_no_return(VOID)779 VOID __asan_handle_no_return(VOID)
780 {
781     return;
782 }
783