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