• 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     LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
97 
98     if (LOS_ListEmpty(&g_lmsCheckPoolList)) {
99         goto EXIT;
100     }
101 
102     LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) {
103         if ((addr >= current->poolAddr) && (addr < current->poolAddr + current->poolSize)) {
104             return current;
105         }
106     }
107 
108 EXIT:
109     return NULL;
110 }
111 
OsLmsCheckPoolCreate(VOID)112 STATIC LmsMemListNode *OsLmsCheckPoolCreate(VOID)
113 {
114     UINT32 i;
115     LmsMemListNode *current = NULL;
116     for (i = 0; i < LOSCFG_LMS_MAX_RECORD_POOL_NUM; i++) {
117         current = &g_lmsCheckPoolArray[i];
118         if (current->used == LMS_POOL_UNUSED) {
119             current->used = LMS_POOL_USED;
120             return current;
121         }
122     }
123     return NULL;
124 }
125 
LOS_LmsCheckPoolAdd(const VOID * pool,UINT32 size)126 UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size)
127 {
128     UINT32 intSave;
129     UINTPTR poolAddr = (UINTPTR)pool;
130     UINT32 realSize;
131     LmsMemListNode *lmsPoolNode = NULL;
132 
133     if (pool == NULL) {
134         return 0;
135     }
136 
137     LMS_LOCK(intSave);
138 
139     lmsPoolNode = OsLmsGetPoolNodeFromAddr((UINTPTR)pool);
140     if (lmsPoolNode != NULL) { /* if pool range already on checklist */
141         if (lmsPoolNode->poolAddr != (UINTPTR)pool) { /* pool is a subset of lmsPoolNode->poolAddr */
142             /* do not add it again, just return */
143             PRINT_DEBUG("[LMS]pool %p already on lms checklist !\n", pool);
144             LMS_UNLOCK(intSave);
145             return size; /* return size indicate the shadow memory init successful */
146         } else { /* 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 
153     lmsPoolNode = OsLmsCheckPoolCreate();
154     if (lmsPoolNode == NULL) {
155         PRINT_DEBUG("[LMS]the num of lms check pool is max already !\n");
156         LMS_UNLOCK(intSave);
157         return 0;
158     }
159     realSize = OsLmsPoolResize(size);
160 
161     lmsPoolNode->poolAddr = poolAddr;
162     lmsPoolNode->poolSize = realSize;
163     lmsPoolNode->shadowStart = (UINTPTR)poolAddr + realSize;
164     lmsPoolNode->shadowSize = poolAddr + size - lmsPoolNode->shadowStart;
165     /* init shadow value */
166     (VOID)memset((VOID *)lmsPoolNode->shadowStart, LMS_SHADOW_AFTERFREE_U8, 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(g_lmsCheckPoolArray, 0, sizeof(g_lmsCheckPoolArray));
197     LOS_ListInit(&g_lmsCheckPoolList);
198     static LmsHook hook = {
199         .init = LOS_LmsCheckPoolAdd,
200         .mallocMark = OsLmsLosMallocMark,
201         .freeMark = OsLmsLosFreeMark,
202         .simpleMark = OsLmsSimpleMark,
203         .check = OsLmsCheckValid,
204     };
205     g_lms = &hook;
206 }
207 
OsLmsMem2Shadow(LmsMemListNode * node,UINTPTR memAddr,UINTPTR * shadowAddr,UINT32 * shadowOffset)208 STATIC INLINE UINT32 OsLmsMem2Shadow(LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset)
209 {
210     if ((memAddr < node->poolAddr) || (memAddr >= node->poolAddr + node->poolSize)) { /* check ptr valid */
211         PRINT_ERR("[LMS]memAddr %p is not in pool region [%p, %p)\n", memAddr, node->poolAddr,
212             node->poolAddr + node->poolSize);
213         return LOS_NOK;
214     }
215 
216     UINT32 memOffset = memAddr - node->poolAddr;
217     *shadowAddr = node->shadowStart + memOffset / LMS_SHADOW_U8_REFER_BYTES;
218     *shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) *
219         LMS_SHADOW_BITS_PER_CELL; /* (memOffset % 16) / 4 */
220     return LOS_OK;
221 }
222 
OsLmsGetShadowInfo(LmsMemListNode * node,UINTPTR memAddr,LmsAddrInfo * info)223 STATIC INLINE VOID OsLmsGetShadowInfo(LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info)
224 {
225     UINTPTR shadowAddr;
226     UINT32 shadowOffset;
227     UINT32 shadowValue;
228 
229     if (OsLmsMem2Shadow(node, memAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
230         return;
231     }
232 
233     shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
234     info->memAddr = memAddr;
235     info->shadowAddr = shadowAddr;
236     info->shadowOffset = shadowOffset;
237     info->shadowValue = shadowValue;
238 }
239 
OsLmsSetShadowValue(LmsMemListNode * node,UINTPTR startAddr,UINTPTR endAddr,UINT8 value)240 VOID OsLmsSetShadowValue(LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value)
241 {
242     UINTPTR shadowStart;
243     UINTPTR shadowEnd;
244     UINT32 startOffset;
245     UINT32 endOffset;
246 
247     UINT8 shadowValueMask;
248     UINT8 shadowValue;
249 
250     /* endAddr -1, then we mark [startAddr, endAddr) to value */
251     if (OsLmsMem2Shadow(node, startAddr, &shadowStart, &startOffset) ||
252         OsLmsMem2Shadow(node, endAddr - 1, &shadowEnd, &endOffset)) {
253         return;
254     }
255 
256     if (shadowStart == shadowEnd) { /* in the same u8 */
257         /* because endAddr - 1, the endOffset falls into the previous cell,
258         so endOffset + 2 is required for calculation */
259         shadowValueMask = LMS_SHADOW_MASK_U8;
260         shadowValueMask =
261             (shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)));
262         shadowValue = value & shadowValueMask;
263         *(UINT8 *)shadowStart &= ~shadowValueMask;
264         *(UINT8 *)shadowStart |= shadowValue;
265     } else {
266         /* Adjust startAddr to left util it reach the beginning of a u8 */
267         if (startOffset > 0) {
268             shadowValueMask = LMS_SHADOW_MASK_U8;
269             shadowValueMask = shadowValueMask << startOffset;
270             shadowValue = value & shadowValueMask;
271             *(UINT8 *)shadowStart &= ~shadowValueMask;
272             *(UINT8 *)shadowStart |= shadowValue;
273             shadowStart += 1;
274         }
275 
276         /* Adjust endAddr to right util it reach the end of a u8 */
277         if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) {
278             shadowValueMask = LMS_SHADOW_MASK_U8;
279             shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL));
280             shadowValue = value & shadowValueMask;
281             *(UINT8 *)shadowEnd &= ~shadowValueMask;
282             *(UINT8 *)shadowEnd |= shadowValue;
283             shadowEnd -= 1;
284         }
285 
286         if (shadowEnd + 1 > shadowStart) {
287             (VOID)memset((VOID *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart);
288         }
289     }
290 }
291 
OsLmsGetShadowValue(LmsMemListNode * node,UINTPTR addr,UINT32 * shadowValue)292 VOID OsLmsGetShadowValue(LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue)
293 {
294     UINTPTR shadowAddr;
295     UINT32 shadowOffset;
296     if (OsLmsMem2Shadow(node, addr, &shadowAddr, &shadowOffset) != LOS_OK) {
297         return;
298     }
299 
300     *shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK;
301 }
302 
OsLmsSimpleMark(UINTPTR startAddr,UINTPTR endAddr,UINT32 value)303 VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
304 {
305     UINT32 intSave;
306     if (endAddr <= startAddr) {
307         PRINT_DEBUG("[LMS]mark 0x%x, 0x%x, 0x%x\n", startAddr, endAddr, (UINTPTR)__builtin_return_address(0));
308         return;
309     }
310 
311     if (!IS_ALIGNED(startAddr, OS_MEM_ALIGN_SIZE) || !IS_ALIGNED(endAddr, OS_MEM_ALIGN_SIZE)) {
312         PRINT_ERR("[LMS]mark addr is not aligned! 0x%x, 0x%x\n", startAddr, endAddr);
313         return;
314     }
315 
316     LMS_LOCK(intSave);
317 
318     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(startAddr);
319     if (node == NULL) {
320         LMS_UNLOCK(intSave);
321         return;
322     }
323 
324     OsLmsSetShadowValue(node, startAddr, endAddr, value);
325     LMS_UNLOCK(intSave);
326 }
327 
OsLmsLosMallocMark(const VOID * curNodeStart,const VOID * nextNodeStart,UINT32 nodeHeadSize)328 VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
329 {
330     UINT32 intSave;
331     UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
332     UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
333 
334     LMS_LOCK(intSave);
335     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
336     if (node == NULL) {
337         LMS_UNLOCK(intSave);
338         return;
339     }
340 
341     OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
342     OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_ACCESSIBLE_U8);
343     OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8);
344     LMS_UNLOCK(intSave);
345 }
346 
OsLmsCheckValid(UINTPTR checkAddr,BOOL isFreeCheck)347 VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck)
348 {
349     UINT32 intSave;
350     UINT32 shadowValue = INVALID_SHADOW_VALUE;
351     LMS_LOCK(intSave);
352     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(checkAddr);
353     if (node == NULL) {
354         LMS_UNLOCK(intSave);
355         return;
356     }
357 
358     OsLmsGetShadowValue(node, checkAddr, &shadowValue);
359     LMS_UNLOCK(intSave);
360     if ((shadowValue == LMS_SHADOW_ACCESSIBLE) || ((isFreeCheck) && (shadowValue == LMS_SHADOW_PAINT))) {
361         return;
362     }
363 
364     OsLmsReportError(checkAddr, MEM_REGION_SIZE_1, isFreeCheck ? FREE_ERRORMODE : COMMON_ERRMODE);
365 }
366 
OsLmsLosFreeMark(const VOID * curNodeStart,const VOID * nextNodeStart,UINT32 nodeHeadSize)367 VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
368 {
369     UINT32 intSave;
370     UINT32 shadowValue = INVALID_SHADOW_VALUE;
371 
372     LMS_LOCK(intSave);
373     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart);
374     if (node == NULL) {
375         LMS_UNLOCK(intSave);
376         return;
377     }
378 
379     UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart;
380     UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart;
381 
382     OsLmsGetShadowValue(node, curNodeStartAddr + nodeHeadSize, &shadowValue);
383     if ((shadowValue != LMS_SHADOW_ACCESSIBLE) && (shadowValue != LMS_SHADOW_PAINT)) {
384         LMS_UNLOCK(intSave);
385         OsLmsReportError(curNodeStartAddr + nodeHeadSize, MEM_REGION_SIZE_1, FREE_ERRORMODE);
386         return;
387     }
388 
389     if (*((UINT8 *)curNodeStart) == 0) { /* if merge the node has memset with 0 */
390         OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
391     }
392     OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_AFTERFREE_U8);
393 
394     if (*((UINT8 *)nextNodeStart) == 0) { /* if merge the node has memset with 0 */
395         OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8);
396     }
397 
398     LMS_UNLOCK(intSave);
399 }
400 
LOS_LmsAddrProtect(UINTPTR addrStart,UINTPTR addrEnd)401 VOID LOS_LmsAddrProtect(UINTPTR addrStart, UINTPTR addrEnd)
402 {
403     UINT32 intSave;
404     if (addrEnd <= addrStart) {
405         return;
406     }
407     LMS_LOCK(intSave);
408     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
409     if (node != NULL) {
410         OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_REDZONE_U8);
411     }
412     LMS_UNLOCK(intSave);
413 }
414 
LOS_LmsAddrDisableProtect(UINTPTR addrStart,UINTPTR addrEnd)415 VOID LOS_LmsAddrDisableProtect(UINTPTR addrStart, UINTPTR addrEnd)
416 {
417     UINT32 intSave;
418     if (addrEnd <= addrStart) {
419         return;
420     }
421     LMS_LOCK(intSave);
422     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart);
423     if (node != NULL) {
424         OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_ACCESSIBLE_U8);
425     }
426     LMS_UNLOCK(intSave);
427 }
428 
OsLmsCheckAddr(UINTPTR addr)429 STATIC UINT32 OsLmsCheckAddr(UINTPTR addr)
430 {
431     UINT32 intSave;
432     UINT32 shadowValue = INVALID_SHADOW_VALUE;
433     /* do not check nested or before all cpu start */
434     LMS_LOCK(intSave);
435     if ((g_checkDepth != 0) || (!g_taskScheduled)) {
436         LMS_UNLOCK(intSave);
437         return 0;
438     }
439 
440     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr);
441     if (node == NULL) {
442         LMS_UNLOCK(intSave);
443         return LMS_SHADOW_ACCESSIBLE_U8;
444     }
445 
446     OsLmsGetShadowValue(node, addr, &shadowValue);
447     LMS_UNLOCK(intSave);
448     return shadowValue;
449 }
450 
451 #if (LOSCFG_LMS_CHECK_STRICT == 1)
OsLmsCheckAddrRegion(UINTPTR addr,UINT32 size)452 STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
453 {
454     UINT32 i;
455     for (i = 0; i < size; i++) {
456         if (OsLmsCheckAddr(addr + i)) {
457             return LOS_NOK;
458         }
459     }
460     return LOS_OK;
461 }
462 
463 #else
OsLmsCheckAddrRegion(UINTPTR addr,UINT32 size)464 STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size)
465 {
466     if (OsLmsCheckAddr(addr) || OsLmsCheckAddr(addr + size - 1)) {
467         return LOS_NOK;
468     } else {
469         return LOS_OK;
470     }
471 }
472 #endif
473 
OsLmsPrintPoolListInfo(VOID)474 VOID OsLmsPrintPoolListInfo(VOID)
475 {
476     UINT32 count = 0;
477     UINT32 intSave;
478     LmsMemListNode *current = NULL;
479     LOS_DL_LIST *listHead = &g_lmsCheckPoolList;
480 
481     LMS_LOCK(intSave);
482     LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node)
483     {
484         count++;
485         PRINT_DEBUG(
486             "[LMS]memory pool[%1u]: totalsize 0x%-8x  memstart 0x%-8x memstop 0x%-8x memsize 0x%-8x shadowstart 0x%-8x "
487             "shadowSize 0x%-8x\n",
488             count, current->poolSize + current->shadowSize, current->poolAddr, current->poolAddr + current->poolSize,
489             current->poolSize, current->shadowStart, current->shadowSize);
490     }
491 
492     LMS_UNLOCK(intSave);
493 }
494 
OsLmsPrintMemInfo(UINTPTR addr)495 VOID OsLmsPrintMemInfo(UINTPTR addr)
496 {
497 #define LMS_DUMP_OFFSET 16
498 #define LMS_DUMP_RANGE_DOUBLE 2
499 
500     PRINTK("\n[LMS] Dump info around address [0x%8x]:\n", addr);
501     const UINT32 printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1;
502     const UINT32 printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE;
503     UINTPTR dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX;
504     UINT32 shadowValue = 0;
505     UINTPTR shadowAddr = 0;
506     UINT32 shadowOffset = 0;
507     LmsMemListNode *nodeInfo = NULL;
508     INT32 isCheckAddr, x, y;
509 
510     nodeInfo = OsLmsGetPoolNodeFromAddr(addr);
511     if (nodeInfo == NULL) {
512         PRINT_ERR("[LMS]addr is not in checkpool\n");
513         return;
514     }
515 
516     for (y = 0; y < printY; y++, dumpAddr += printX) {
517         if (dumpAddr < nodeInfo->poolAddr) { /* find util dumpAddr in pool region */
518             continue;
519         }
520 
521         if ((dumpAddr + printX) >=
522             nodeInfo->poolAddr + nodeInfo->poolSize) { /* finish if dumpAddr exceeds pool's upper region */
523             goto END;
524         }
525 
526         PRINTK("\n\t[0x%x]: ", dumpAddr);
527         for (x = 0; x < printX; x++) {
528             if ((dumpAddr + x) == addr) {
529                 PRINTK("[%02x]", *(UINT8 *)(dumpAddr + x));
530             } else {
531                 PRINTK(" %02x ", *(UINT8 *)(dumpAddr + x));
532             }
533         }
534 
535         if (OsLmsMem2Shadow(nodeInfo, dumpAddr, &shadowAddr, &shadowOffset) != LOS_OK) {
536             goto END;
537         }
538 
539         PRINTK("|\t[0x%x | %2u]: ", shadowAddr, shadowOffset);
540 
541         for (x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) {
542             OsLmsGetShadowValue(nodeInfo, dumpAddr + x, &shadowValue);
543             isCheckAddr = dumpAddr + x - (UINTPTR)addr + LMS_MEM_BYTES_PER_SHADOW_CELL;
544             if ((isCheckAddr > 0) && (isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL)) {
545                 PRINTK("[%1x]", shadowValue);
546             } else {
547                 PRINTK(" %1x ", shadowValue);
548             }
549         }
550     }
551 END:
552     PRINTK("\n");
553 }
554 
OsLmsGetErrorInfo(UINTPTR addr,UINT32 size,LmsAddrInfo * info)555 STATIC VOID OsLmsGetErrorInfo(UINTPTR addr, UINT32 size, LmsAddrInfo *info)
556 {
557     LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr);
558     OsLmsGetShadowInfo(node, addr, info);
559     if (info->shadowValue != LMS_SHADOW_ACCESSIBLE_U8) {
560         return;
561     } else {
562         OsLmsGetShadowInfo(node, addr + size - 1, info);
563     }
564 }
565 
OsLmsPrintErrInfo(LmsAddrInfo * info,UINT32 errMod)566 STATIC VOID OsLmsPrintErrInfo(LmsAddrInfo *info, UINT32 errMod)
567 {
568     switch (info->shadowValue) {
569         case LMS_SHADOW_AFTERFREE:
570             PRINT_ERR("Use after free error detected\n");
571             break;
572         case LMS_SHADOW_REDZONE:
573             PRINT_ERR("Heap buffer overflow error detected\n");
574             break;
575         case LMS_SHADOW_ACCESSIBLE:
576             PRINT_ERR("No error\n");
577             break;
578         default:
579             PRINT_ERR("UnKnown Error detected\n");
580             break;
581     }
582 
583     switch (errMod) {
584         case FREE_ERRORMODE:
585             PRINT_ERR("Illegal Double free address at: [0x%lx]\n", info->memAddr);
586             break;
587         case LOAD_ERRMODE:
588             PRINT_ERR("Illegal READ address at: [0x%lx]\n", info->memAddr);
589             break;
590         case STORE_ERRMODE:
591             PRINT_ERR("Illegal WRITE address at: [0x%lx]\n", info->memAddr);
592             break;
593         case COMMON_ERRMODE:
594             PRINT_ERR("Common Error at: [0x%lx]\n", info->memAddr);
595             break;
596         default:
597             PRINT_ERR("UnKnown Error mode at: [0x%lx]\n", info->memAddr);
598             break;
599     }
600 
601     PRINT_ERR("Shadow memory address: [0x%lx : %1u]  Shadow memory value: [%u] \n", info->shadowAddr,
602         info->shadowOffset, info->shadowValue);
603 }
604 
OsLmsReportError(UINTPTR p,UINT32 size,UINT32 errMod)605 VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod)
606 {
607     UINT32 intSave;
608     LmsAddrInfo info;
609 
610     LMS_LOCK(intSave);
611     g_checkDepth += 1;
612     (VOID)memset(&info, 0, sizeof(LmsAddrInfo));
613 
614     PRINT_ERR("*****  Kernel Address Sanitizer Error Detected Start *****\n");
615 
616     OsLmsGetErrorInfo(p, size, &info);
617 
618     OsLmsPrintErrInfo(&info, errMod);
619 #if (LOSCFG_BACKTRACE_TYPE != 0)
620     LOS_BackTrace();
621 #endif
622     OsLmsPrintMemInfo(info.memAddr);
623     g_checkDepth -= 1;
624     LMS_UNLOCK(intSave);
625     PRINT_ERR("*****  Kernel Address Sanitizer Error Detected End *****\n");
626 }
627 
628 #if (LOSCFG_LMS_STORE_CHECK == 1)
__asan_store1_noabort(UINTPTR p)629 VOID __asan_store1_noabort(UINTPTR p)
630 {
631     if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSIBLE_U8) {
632         OsLmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE);
633     }
634 }
635 
__asan_store2_noabort(UINTPTR p)636 VOID __asan_store2_noabort(UINTPTR p)
637 {
638     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
639         OsLmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE);
640     }
641 }
642 
__asan_store4_noabort(UINTPTR p)643 VOID __asan_store4_noabort(UINTPTR p)
644 {
645     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
646         OsLmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE);
647     }
648 }
649 
__asan_store8_noabort(UINTPTR p)650 VOID __asan_store8_noabort(UINTPTR p)
651 {
652     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
653         OsLmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE);
654     }
655 }
656 
__asan_store16_noabort(UINTPTR p)657 VOID __asan_store16_noabort(UINTPTR p)
658 {
659     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
660         OsLmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE);
661     }
662 }
663 
__asan_storeN_noabort(UINTPTR p,UINT32 size)664 VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
665 {
666     if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
667         OsLmsReportError(p, size, STORE_ERRMODE);
668     }
669 }
670 #else
__asan_store1_noabort(UINTPTR p)671 VOID __asan_store1_noabort(UINTPTR p)
672 {
673     (VOID)p;
674 }
675 
__asan_store2_noabort(UINTPTR p)676 VOID __asan_store2_noabort(UINTPTR p)
677 {
678     (VOID)p;
679 }
680 
__asan_store4_noabort(UINTPTR p)681 VOID __asan_store4_noabort(UINTPTR p)
682 {
683     (VOID)p;
684 }
685 
__asan_store8_noabort(UINTPTR p)686 VOID __asan_store8_noabort(UINTPTR p)
687 {
688     (VOID)p;
689 }
690 
__asan_store16_noabort(UINTPTR p)691 VOID __asan_store16_noabort(UINTPTR p)
692 {
693     (VOID)p;
694 }
695 
__asan_storeN_noabort(UINTPTR p,UINT32 size)696 VOID __asan_storeN_noabort(UINTPTR p, UINT32 size)
697 {
698     (VOID)p;
699     (VOID)size;
700 }
701 
702 #endif
703 
704 #if (LOSCFG_LMS_LOAD_CHECK == 1)
__asan_load1_noabort(UINTPTR p)705 VOID __asan_load1_noabort(UINTPTR p)
706 {
707     if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSIBLE_U8) {
708         OsLmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE);
709     }
710 }
711 
__asan_load2_noabort(UINTPTR p)712 VOID __asan_load2_noabort(UINTPTR p)
713 {
714     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) {
715         OsLmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE);
716     }
717 }
718 
__asan_load4_noabort(UINTPTR p)719 VOID __asan_load4_noabort(UINTPTR p)
720 {
721     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) {
722         OsLmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE);
723     }
724 }
725 
__asan_load8_noabort(UINTPTR p)726 VOID __asan_load8_noabort(UINTPTR p)
727 {
728     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) {
729         OsLmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE);
730     }
731 }
732 
__asan_load16_noabort(UINTPTR p)733 VOID __asan_load16_noabort(UINTPTR p)
734 {
735     if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) {
736         OsLmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE);
737     }
738 }
739 
__asan_loadN_noabort(UINTPTR p,UINT32 size)740 VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
741 {
742     if (OsLmsCheckAddrRegion(p, size) != LOS_OK) {
743         OsLmsReportError(p, size, LOAD_ERRMODE);
744     }
745 }
746 #else
__asan_load1_noabort(UINTPTR p)747 VOID __asan_load1_noabort(UINTPTR p)
748 {
749     (VOID)p;
750 }
751 
__asan_load2_noabort(UINTPTR p)752 VOID __asan_load2_noabort(UINTPTR p)
753 {
754     (VOID)p;
755 }
756 
__asan_load4_noabort(UINTPTR p)757 VOID __asan_load4_noabort(UINTPTR p)
758 {
759     (VOID)p;
760 }
761 
__asan_load8_noabort(UINTPTR p)762 VOID __asan_load8_noabort(UINTPTR p)
763 {
764     (VOID)p;
765 }
766 
__asan_load16_noabort(UINTPTR p)767 VOID __asan_load16_noabort(UINTPTR p)
768 {
769     (VOID)p;
770 }
771 
__asan_loadN_noabort(UINTPTR p,UINT32 size)772 VOID __asan_loadN_noabort(UINTPTR p, UINT32 size)
773 {
774     (VOID)p;
775     (VOID)size;
776 }
777 #endif
__asan_handle_no_return(VOID)778 VOID __asan_handle_no_return(VOID)
779 {
780     return;
781 }
782