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