diff --git a/apps/BUILD.gn b/apps/BUILD.gn index eab6ff27..bf35c91a 100644 --- a/apps/BUILD.gn +++ b/apps/BUILD.gn @@ -55,4 +55,8 @@ group("apps") { if (defined(LOSCFG_DRIVERS_PERF)) { deps += [ "perf" ] } + + if (defined(LOSCFG_KERNEL_LMS)) { + deps += [ "lms:sample_usr_lms" ] + } } diff --git a/apps/lms/BUILD.gn b/apps/lms/BUILD.gn new file mode 100644 index 00000000..f90f6363 --- /dev/null +++ b/apps/lms/BUILD.gn @@ -0,0 +1,77 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//build/lite/config/component/lite_component.gni") +lite_component("LMS-Sample") { + features = [ ":sample_usr_lms" ] +} +executable("sample_usr_lms") { + output_name = "sample_usr_lms" + sources = [ "src/sample_usr_lms.c" ] + include_dirs = [] + defines = [] + if (ohos_build_compiler == "gcc") { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + "-funwind-tables", + "-fasynchronous-unwind-tables", + ] + } else { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + "-mllvm", + "-asan-instrumentation-with-call-threshold=0", + "-mllvm", + "-asan-stack=0", + "-mllvm", + "-asan-globals=0", + "-funwind-tables", + "-fasynchronous-unwind-tables", + ] + } + ldflags = [ + "-rdynamic", + "-lunwind", + "-lusrlms", + "-Wl,--wrap=realloc", + "-Wl,--wrap=calloc", + "-Wl,--wrap=malloc", + "-Wl,--wrap=free", + "-Wl,--wrap=valloc", + "-Wl,--wrap=aligned_alloc", + "-Wl,--wrap=memset", + "-Wl,--wrap=memcpy", + "-Wl,--wrap=memmove", + "-Wl,--wrap=strcpy", + "-Wl,--wrap=strcat", + ] + deps = [ "//kernel/liteos_a/kernel/extended/lms/usr:usrlmslib" ] +} diff --git a/apps/lms/src/sample_usr_lms.c b/apps/lms/src/sample_usr_lms.c new file mode 100755 index 00000000..208efb2f --- /dev/null +++ b/apps/lms/src/sample_usr_lms.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static void BufWriteTest(void *buf, int start, int end) +{ + for (int i = start; i <= end; i++) { + ((char *)buf)[i] = 'a'; + } +} + +static void BufReadTest(void *buf, int start, int end) +{ + char tmp; + for (int i = start; i <= end; i++) { + tmp = ((char *)buf)[i]; + } +} + +static void LmsMallocTest(void) +{ + printf("\n-------- LmsMallocTest Start --------\n"); + char *buf = (char *)malloc(16); + printf("[LmsMallocTest] malloc addr:%p size:%d\n", buf, 16); + + printf("[LmsMallocTest] read overflow & underflow error should be triggered, read range[-1,16]\n"); + BufReadTest(buf, -1, 16); + printf("[LmsMallocTest] write overflow error should be triggered, write range[0,16]\n"); + BufWriteTest(buf, 0, 16); + + free(buf); + printf("\n-------- LmsMallocTest End --------\n"); +} + +static void LmsReallocTest(void) +{ + printf("\n-------- LmsReallocTest Start --------\n"); + char *buf = (char *)malloc(64); + printf("[LmsReallocTest] malloc addr:%p size:%d\n", buf, 64); + printf("[LmsReallocTest] read overflow & underflow error should be triggered, read range[-1,64]\n"); + BufReadTest(buf, -1, 64); + buf = (char *)realloc(buf, 32); + printf("[LmsReallocTest] realloc addr:%p size:%d\n", buf, 32); + printf("[LmsReallocTest] read overflow & underflow error should be triggered, read range[-1,32]\n"); + BufReadTest(buf, -1, 32); + free(buf); + printf("\n-------- LmsReallocTest End --------\n"); +} + +static void LmsCallocTest(void) +{ + printf("\n-------- LmsCallocTest Start --------\n"); + char *buf = (char *)calloc(4, 4); + printf("[LmsCallocTest] calloc addr:%p size:%d\n", buf, 16); + printf("[LmsCallocTest] read overflow & underflow error should be triggered, read range[-1,16]\n"); + BufReadTest(buf, -1, 16); + free(buf); + printf("\n-------- LmsCallocTest End --------\n"); +} + +static void LmsVallocTest(void) +{ + printf("\n-------- LmsVallocTest Start --------\n"); + char *buf = (char *)valloc(4096); + printf("[LmsVallocTest] valloc addr:%p size:%d\n", buf, 4096); + printf("[LmsVallocTest] read overflow & underflow error should be triggered, read range[-1,4096]\n"); + BufReadTest(buf, -1, 4096); + free(buf); + printf("\n-------- LmsVallocTest End --------\n"); +} + +static void LmsAlignedAllocTest(void) +{ + printf("\n-------- LmsAlignedAllocTest Start --------\n"); + char *buf = (char *)aligned_alloc(64, 128); + printf("[LmsAlignedAllocTest] aligned_alloc boundsize:%d addr:%p size:%d\n", 64, buf, 128); + printf("[LmsAlignedAllocTest] read overflow & underflow error should be triggered, read range[-1,128]\n"); + BufReadTest(buf, -1, 128); + free(buf); + printf("\n-------- LmsAlignedAllocTest End --------\n"); +} + +static void LmsMemsetTest(void) +{ + printf("\n-------- LmsMemsetTest Start --------\n"); + char *buf = (char *)malloc(32); + printf("[LmsMemsetTest] malloc addr:%p size:%d\n", buf, 32); + printf("[LmsMemsetTest] memset overflow & underflow error should be triggered, memset size:%d\n", 33); + memset(buf, 0, 33); + free(buf); + printf("\n-------- LmsMemsetTest End --------\n"); +} + +static void LmsMemcpyTest(void) +{ + printf("\n-------- LmsMemcpyTest Start --------\n"); + char *buf = (char *)malloc(20); + printf("[LmsMemcpyTest] malloc addr:%p size:%d\n", buf, 20); + char localBuf[32] = {0}; + printf("[LmsMemcpyTest] memcpy overflow error should be triggered, memcpy size:%d\n", 21); + memcpy(buf, localBuf, 21); + free(buf); + printf("\n-------- LmsMemcpyTest End --------\n"); +} + +static void LmsMemmoveTest(void) +{ + printf("\n-------- LmsMemmoveTest Start --------\n"); + char *buf = (char *)malloc(20); + printf("[LmsMemmoveTest] malloc addr:%p size:%d\n", buf, 20); + printf("[LmsMemmoveTest] memmove overflow error should be triggered, dest addr:%p src addr:%p size:%d\n", buf + 12, + buf, 10); + memmove(buf + 12, buf, 10); + free(buf); + printf("\n-------- LmsMemmoveTest End --------\n"); +} + +static void LmsStrcpyTest(void) +{ + printf("\n-------- LmsStrcpyTest Start --------\n"); + char *buf = (char *)malloc(16); + printf("[LmsStrcpyTest] malloc addr:%p size:%d\n", buf, 16); + char *testStr = "bbbbbbbbbbbbbbbbb"; + printf("[LmsStrcpyTest] strcpy overflow error should be triggered, src string buf size:%d\n", strlen(testStr) + 1); + strcpy(buf, testStr); + free(buf); + printf("\n-------- LmsStrcpyTest End --------\n"); +} + +static void LmsStrcatTest(void) +{ + printf("\n-------- LmsStrcatTest Start --------\n"); + char *buf = (char *)malloc(16); + printf("[LmsStrcatTest] malloc addr:%p size:%d\n", buf, 16); + buf[0] = 'a'; + buf[1] = 'b'; + buf[2] = 0; + char *testStr = "cccccccccccccc"; + printf("[LmsStrcatTest] strcat overflow error should be triggered, src string:%s dest string:%s" + "total buf size:%d\n", + testStr, buf, strlen(testStr) + strlen(buf) + 1); + strcat(buf, testStr); + free(buf); + printf("\n-------- LmsStrcatTest End --------\n"); +} + +static void LmsFreeTest(void) +{ + printf("\n-------- LmsFreeTest Start --------\n"); + char *buf = (char *)malloc(16); + printf("[LmsFreeTest] malloc addr:%p size:%d\n", buf, 16); + printf("[LmsFreeTest] free addr:%p\n", buf, 16); + free(buf); + printf("[LmsFreeTest] Use after free error should be triggered, read addr:%p range[1,1]\n", buf); + BufReadTest(buf, 1, 1); + printf("[LmsFreeTest] double free error should be triggered, free addr:%p\n", buf); + free(buf); + printf("\n-------- LmsFreeTest End --------\n"); +} + +int main(int argc, char * const * argv) +{ + printf("\n############### Lms Test start ###############\n"); + char *tmp = (char *)malloc(5000); + LmsMallocTest(); + LmsReallocTest(); + LmsCallocTest(); + LmsVallocTest(); + LmsAlignedAllocTest(); + LmsMemsetTest(); + LmsMemcpyTest(); + LmsMemmoveTest(); + LmsStrcpyTest(); + LmsStrcatTest(); + LmsFreeTest(); + printf("\n############### Lms Test End ###############\n"); +} \ No newline at end of file diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index fc125597..646c9cc3 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -525,7 +525,9 @@ LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB *taskCB) OsTaskKernelResourcesToFree(syncSignal, topOfStack); SCHEDULER_LOCK(intSave); +#ifdef LOSCFG_KERNEL_VM OsClearSigInfoTmpList(&(taskCB->sig)); +#endif OsInsertTCBToFreeList(taskCB); SCHEDULER_UNLOCK(intSave); } diff --git a/kernel/base/include/los_sched_pri.h b/kernel/base/include/los_sched_pri.h index 98019369..1cf06bd1 100644 --- a/kernel/base/include/los_sched_pri.h +++ b/kernel/base/include/los_sched_pri.h @@ -88,6 +88,7 @@ STATIC INLINE VOID OsSchedIrqStartTime(VOID) } while (0); #define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid())) +#define OS_SCHEDULER_ALL_ACTIVE (g_taskScheduled == LOSCFG_KERNEL_CPU_MASK) typedef enum { INT_NO_RESCH = 0x0, /* no needs to schedule */ diff --git a/kernel/base/include/los_vm_filemap.h b/kernel/base/include/los_vm_filemap.h index 9d8ec5fb..7784cb56 100644 --- a/kernel/base/include/los_vm_filemap.h +++ b/kernel/base/include/los_vm_filemap.h @@ -183,7 +183,14 @@ STATIC INLINE BOOL OsIsPageShared(LosVmPage *page) return BIT_GET(page->flags, FILE_PAGE_SHARED); } +typedef struct ProcessCB LosProcessCB; + +#ifdef LOSCFG_FS_VFS INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region); +STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region); +VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB); +#endif + LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff); LosFilePage *OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff); LosMapInfo *OsGetMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr); @@ -198,14 +205,11 @@ VOID OsLruCacheDel(LosFilePage *fpage); LosFilePage *OsDumpDirtyPage(LosFilePage *oldPage); VOID OsDoFlushDirtyPage(LosFilePage *fpage); VOID OsDeletePageCacheLru(LosFilePage *page); -STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region); VOID OsPageRefDecNoLock(LosFilePage *page); VOID OsPageRefIncLocked(LosFilePage *page); int OsTryShrinkMemory(size_t nPage); VOID OsMarkPageDirty(LosFilePage *fpage, LosVmMapRegion *region, int off, int len); -typedef struct ProcessCB LosProcessCB; -VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB); #ifdef LOSCFG_DEBUG_VERSION VOID ResetPageCacheHitInfo(int *try, int *hit); struct file_map* GetFileMappingList(void); diff --git a/kernel/base/mem/tlsf/los_memory.c b/kernel/base/mem/tlsf/los_memory.c index d5e5b99a..05c02598 100644 --- a/kernel/base/mem/tlsf/los_memory.c +++ b/kernel/base/mem/tlsf/los_memory.c @@ -39,6 +39,10 @@ #include "los_task_pri.h" #include "los_hook.h" +#ifdef LOSCFG_KERNEL_LMS +#include "los_lms_pri.h" +#endif + /* Used to cut non-essential functions. */ #define OS_MEM_FREE_BY_TASKID 0 #ifdef LOSCFG_KERNEL_VM @@ -366,7 +370,9 @@ STATIC INLINE BOOL TryShrinkPool(const VOID *pool, const struct OsMemNodeHead *n PRINT_ERR("TryShrinkPool free %#x failed!\n", node); return FALSE; } - +#ifdef LOSCFG_KERNEL_LMS + LOS_LmsCheckPoolDel(node); +#endif return TRUE; } @@ -394,13 +400,24 @@ RETRY: PRINT_ERR("OsMemPoolExpand alloc failed size = %u\n", size); return -1; } +#ifdef LOSCFG_KERNEL_LMS + UINT32 resize = 0; + if (g_lms != NULL) { + /* + * resize == 0, shadow memory init failed, no shadow memory for this pool, set poolSize as original size. + * resize != 0, shadow memory init successful, set poolSize as resize. + */ + resize = g_lms->init(newNode, size); + size = (resize == 0) ? size : resize; + } +#endif newNode->sizeAndFlag = (size - OS_MEM_NODE_HEAD_SIZE); newNode->ptr.prev = OS_MEM_END_NODE(newNode, size); OsMemSentinelNodeSet(endNode, newNode, size); OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode); endNode = OS_MEM_END_NODE(newNode, size); - (VOID)memset_s(endNode, sizeof(*endNode), 0, sizeof(*endNode)); + (VOID)memset(endNode, 0, sizeof(*endNode)); endNode->ptr.next = NULL; endNode->magic = OS_MEM_NODE_MAGIC; OsMemSentinelNodeSet(endNode, NULL, 0); @@ -441,6 +458,71 @@ VOID LOS_MemExpandEnable(VOID *pool) } #endif +#ifdef LOSCFG_KERNEL_LMS +STATIC INLINE VOID OsLmsFirstNodeMark(VOID *pool, struct OsMemNodeHead *node) +{ + if (g_lms == NULL) { + return; + } + + g_lms->simpleMark((UINTPTR)pool, (UINTPTR)node, LMS_SHADOW_PAINT_U8); + g_lms->simpleMark((UINTPTR)node, (UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, LMS_SHADOW_REDZONE_U8); + g_lms->simpleMark((UINTPTR)OS_MEM_NEXT_NODE(node), (UINTPTR)OS_MEM_NEXT_NODE(node) + OS_MEM_NODE_HEAD_SIZE, + LMS_SHADOW_REDZONE_U8); + g_lms->simpleMark((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, (UINTPTR)OS_MEM_NEXT_NODE(node), + LMS_SHADOW_AFTERFREE_U8); +} + +STATIC INLINE VOID OsLmsAllocAlignMark(VOID *ptr, VOID *alignedPtr, UINT32 size) +{ + struct OsMemNodeHead *allocNode = NULL; + + if ((g_lms == NULL) || (ptr == NULL)) { + return; + } + allocNode = (struct OsMemNodeHead *)((struct OsMemUsedNodeHead *)ptr - 1); + if (ptr != alignedPtr) { + g_lms->simpleMark((UINTPTR)ptr, (UINTPTR)ptr + sizeof(UINT32), LMS_SHADOW_PAINT_U8); + g_lms->simpleMark((UINTPTR)ptr + sizeof(UINT32), (UINTPTR)alignedPtr, LMS_SHADOW_REDZONE_U8); + } + + /* mark remining as redzone */ + g_lms->simpleMark(LMS_ADDR_ALIGN((UINTPTR)alignedPtr + size), (UINTPTR)OS_MEM_NEXT_NODE(allocNode), + LMS_SHADOW_REDZONE_U8); +} + +STATIC INLINE VOID OsLmsReallocMergeNodeMark(struct OsMemNodeHead *node) +{ + if (g_lms == NULL) { + return; + } + + g_lms->simpleMark((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, (UINTPTR)OS_MEM_NEXT_NODE(node), + LMS_SHADOW_ACCESSABLE_U8); +} + +STATIC INLINE VOID OsLmsReallocSplitNodeMark(struct OsMemNodeHead *node) +{ + if (g_lms == NULL) { + return; + } + /* mark next node */ + g_lms->simpleMark((UINTPTR)OS_MEM_NEXT_NODE(node), + (UINTPTR)OS_MEM_NEXT_NODE(node) + OS_MEM_NODE_HEAD_SIZE, LMS_SHADOW_REDZONE_U8); + g_lms->simpleMark((UINTPTR)OS_MEM_NEXT_NODE(node) + OS_MEM_NODE_HEAD_SIZE, + (UINTPTR)OS_MEM_NEXT_NODE(OS_MEM_NEXT_NODE(node)), LMS_SHADOW_AFTERFREE_U8); +} + +STATIC INLINE VOID OsLmsReallocResizeMark(struct OsMemNodeHead *node, UINT32 resize) +{ + if (g_lms == NULL) { + return; + } + /* mark remaining as redzone */ + g_lms->simpleMark((UINTPTR)node + resize, (UINTPTR)OS_MEM_NEXT_NODE(node), LMS_SHADOW_REDZONE_U8); +} +#endif + #ifdef LOSCFG_MEM_LEAKCHECK STATIC INLINE VOID OsMemLinkRegisterRecord(struct OsMemNodeHead *node) { @@ -738,6 +820,12 @@ STATIC INLINE VOID *OsMemCreateUsedNode(VOID *addr) OsMemNodeSetTaskID(node); #endif +#ifdef LOSCFG_KERNEL_LMS + struct OsMemNodeHead *newNode = (struct OsMemNodeHead *)node; + if (g_lms != NULL) { + g_lms->mallocMark(newNode, OS_MEM_NEXT_NODE(newNode), OS_MEM_NODE_HEAD_SIZE); + } +#endif return node + 1; } @@ -746,8 +834,18 @@ STATIC UINT32 OsMemPoolInit(VOID *pool, UINT32 size) struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool; struct OsMemNodeHead *newNode = NULL; struct OsMemNodeHead *endNode = NULL; - - (VOID)memset_s(poolHead, sizeof(struct OsMemPoolHead), 0, sizeof(struct OsMemPoolHead)); +#ifdef LOSCFG_KERNEL_LMS + UINT32 resize = 0; + if (g_lms != NULL) { + /* + * resize == 0, shadow memory init failed, no shadow memory for this pool, set poolSize as original size. + * resize != 0, shadow memory init successful, set poolSize as resize. + */ + resize = g_lms->init(pool, size); + size = (resize == 0) ? size : resize; + } +#endif + (VOID)memset(poolHead, 0, sizeof(struct OsMemPoolHead)); LOS_SpinInit(&poolHead->spinlock); poolHead->info.pool = pool; @@ -775,14 +873,18 @@ STATIC UINT32 OsMemPoolInit(VOID *pool, UINT32 size) poolHead->info.curUsedSize = sizeof(struct OsMemPoolHead) + OS_MEM_NODE_HEAD_SIZE; poolHead->info.waterLine = poolHead->info.curUsedSize; #endif - +#ifdef LOSCFG_KERNEL_LMS + if (resize != 0) { + OsLmsFirstNodeMark(pool, newNode); + } +#endif return LOS_OK; } #ifdef LOSCFG_MEM_MUL_POOL STATIC VOID OsMemPoolDeinit(VOID *pool) { - (VOID)memset_s(pool, sizeof(struct OsMemPoolHead), 0, sizeof(struct OsMemPoolHead)); + (VOID)memset(pool, 0, sizeof(struct OsMemPoolHead)); } STATIC UINT32 OsMemPoolAdd(VOID *pool, UINT32 size) @@ -1009,6 +1111,9 @@ VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) MEM_UNLOCK(poolHead, intSave); alignedPtr = (VOID *)OS_MEM_ALIGN(ptr, boundary); if (ptr == alignedPtr) { +#ifdef LOSCFG_KERNEL_LMS + OsLmsAllocAlignMark(ptr, alignedPtr, size); +#endif break; } @@ -1018,6 +1123,9 @@ VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) OS_MEM_NODE_SET_ALIGNED_FLAG(allocNode->header.sizeAndFlag); OS_MEM_NODE_SET_ALIGNED_FLAG(gapSize); *(UINT32 *)((UINTPTR)alignedPtr - sizeof(gapSize)) = gapSize; +#ifdef LOSCFG_KERNEL_LMS + OsLmsAllocAlignMark(ptr, alignedPtr, size); +#endif ptr = alignedPtr; } while (0); @@ -1141,6 +1249,13 @@ STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead node->sizeAndFlag = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag); #ifdef LOSCFG_MEM_LEAKCHECK OsMemLinkRegisterRecord(node); +#endif +#ifdef LOSCFG_KERNEL_LMS + struct OsMemNodeHead *nextNodeBackup = OS_MEM_NEXT_NODE(node); + struct OsMemNodeHead *curNodeBackup = node; + if (g_lms != NULL) { + g_lms->check((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, TRUE); + } #endif struct OsMemNodeHead *preNode = node->ptr.prev; /* merage preNode */ if ((preNode != NULL) && !OS_MEM_NODE_GET_USED_FLAG(preNode->sizeAndFlag)) { @@ -1166,7 +1281,11 @@ STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead } #endif OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)node); - +#ifdef LOSCFG_KERNEL_LMS + if (g_lms != NULL) { + g_lms->freeMark(curNodeBackup, nextNodeBackup, OS_MEM_NODE_HEAD_SIZE); + } +#endif return ret; } @@ -1219,6 +1338,11 @@ STATIC INLINE VOID OsMemReAllocSmaller(VOID *pool, UINT32 allocSize, struct OsMe OS_MEM_NODE_SET_USED_FLAG(node->sizeAndFlag); #ifdef LOSCFG_MEM_WATERLINE poolInfo->info.curUsedSize -= nodeSize - allocSize; +#endif +#ifdef LOSCFG_KERNEL_LMS + OsLmsReallocSplitNodeMark(node); + } else { + OsLmsReallocResizeMark(node, allocSize); #endif } OS_MEM_NODE_SET_USED_FLAG(node->sizeAndFlag); @@ -1233,8 +1357,16 @@ STATIC INLINE VOID OsMemMergeNodeForReAllocBigger(VOID *pool, UINT32 allocSize, node->sizeAndFlag = nodeSize; OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode); OsMemMergeNode(nextNode); +#ifdef LOSCFG_KERNEL_LMS + OsLmsReallocMergeNodeMark(node); +#endif if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_MIN_ALLOC_SIZE) <= node->sizeAndFlag) { OsMemSplitNode(pool, node, allocSize); +#ifdef LOSCFG_KERNEL_LMS + OsLmsReallocSplitNodeMark(node); + } else { + OsLmsReallocResizeMark(node, allocSize); +#endif } OS_MEM_NODE_SET_USED_FLAG(node->sizeAndFlag); OsMemWaterUsedRecord((struct OsMemPoolHead *)pool, node->sizeAndFlag - nodeSize); @@ -1757,7 +1889,7 @@ UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus) return LOS_NOK; } - (VOID)memset_s(poolStatus, sizeof(LOS_MEM_POOL_STATUS), 0, sizeof(LOS_MEM_POOL_STATUS)); + (VOID)memset(poolStatus, 0, sizeof(LOS_MEM_POOL_STATUS)); struct OsMemNodeHead *tmpNode = NULL; struct OsMemNodeHead *endNode = NULL; diff --git a/kernel/extended/BUILD.gn b/kernel/extended/BUILD.gn index e33f36f9..e8b2f7a2 100644 --- a/kernel/extended/BUILD.gn +++ b/kernel/extended/BUILD.gn @@ -39,6 +39,7 @@ group("extended") { "hilog", "hook", "liteipc", + "lms", "perf", "pipes", "power", @@ -59,5 +60,6 @@ config("public") { "pipes:public", "vdso:public", "perf:public", + "lms:public", ] } diff --git a/kernel/extended/Kconfig b/kernel/extended/Kconfig index c826d3bc..0ae789b6 100644 --- a/kernel/extended/Kconfig +++ b/kernel/extended/Kconfig @@ -98,4 +98,7 @@ source "kernel/extended/blackbox/Kconfig" source "kernel/extended/hidumper/Kconfig" ######################### config options of perf ######################### -source "kernel/extended/perf/Kconfig" \ No newline at end of file +source "kernel/extended/perf/Kconfig" + +######################### config options of lms ######################### +source "kernel/extended/lms/Kconfig" \ No newline at end of file diff --git a/kernel/extended/lms/BUILD.gn b/kernel/extended/lms/BUILD.gn new file mode 100644 index 00000000..e0dd2cd2 --- /dev/null +++ b/kernel/extended/lms/BUILD.gn @@ -0,0 +1,43 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//kernel/liteos_a/liteos.gni") + +module_switch = defined(LOSCFG_KERNEL_LMS) +module_name = get_path_info(rebase_path("."), "name") +kernel_module(module_name) { + sources = [ + "lms_libc.c", + "los_lms.c", + ] +} + +config("public") { + include_dirs = [ "." ] +} diff --git a/kernel/extended/lms/Kconfig b/kernel/extended/lms/Kconfig new file mode 100755 index 00000000..77648874 --- /dev/null +++ b/kernel/extended/lms/Kconfig @@ -0,0 +1,41 @@ +config KERNEL_LMS + bool "Enable Lite Memory Sanitizer" + default n + depends on KERNEL_EXTKERNEL && DEBUG_VERSION && LIB_LIBC + help + Select y to build LiteOS with memory sanitizer. + +config LMS_MAX_RECORD_POOL_NUM + int "Lms check pool max num" + default 50 + depends on KERNEL_LMS + help + The Max num of lms check pool + +config LMS_LOAD_CHECK + bool "Enable lms read check" + default y + depends on KERNEL_LMS + help + Select y to enable read check. + +config LMS_STORE_CHECK + bool "Enable lms write check" + default y + depends on KERNEL_LMS + help + Select y to enable write check. + +config LMS_CHECK_STRICT + bool "Enable lms strict check, byte-by-byte" + default n + depends on KERNEL_LMS + help + Select y to enable byte-by-byte check in lms + +config LMS_LIBC_FULL_CHECK + bool "Enable libc all function do lms check" + default n + depends on KERNEL_LMS + help + Select y to enable libc full check diff --git a/kernel/extended/lms/Makefile b/kernel/extended/lms/Makefile new file mode 100755 index 00000000..304e9c6c --- /dev/null +++ b/kernel/extended/lms/Makefile @@ -0,0 +1,10 @@ +include $(LITEOSTOPDIR)/config.mk + +MODULE_NAME := $(notdir $(shell pwd)) + +LOCAL_SRCS := $(wildcard *.c) + +LOCAL_FLAGS := $(LOCAL_INCLUDE) + +include $(MODULE) + diff --git a/kernel/extended/lms/lms_libc.c b/kernel/extended/lms/lms_libc.c new file mode 100755 index 00000000..1b7fef39 --- /dev/null +++ b/kernel/extended/lms/lms_libc.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "string.h" +#include "los_lms_pri.h" + +#undef memset +void *memset(void *addr, int c, size_t len) +{ + __asan_storeN_noabort((UINTPTR)addr, len); + return __memset(addr, c, len); +} + +#undef memmove +void *memmove(void *dest, const void *src, size_t len) +{ + __asan_loadN_noabort((UINTPTR)src, len); + __asan_storeN_noabort((UINTPTR)dest, len); + return __memmove(dest, src, len); +} + +#undef memcpy +void *memcpy(void *dest, const void *src, size_t len) +{ + __asan_loadN_noabort((UINTPTR)src, len); + __asan_storeN_noabort((UINTPTR)dest, len); + return __memcpy(dest, src, len); +} + +#undef strcat +char *strcat (char *s, const char *append) +{ + if ((s == NULL) || (append == NULL)) { + return NULL; + } + + CHAR *end = s; + size_t len = strlen(append); + for (; *end != '\0'; ++end) { + } + + __asan_storeN_noabort((UINTPTR)end, len + 1); + __asan_loadN_noabort((UINTPTR)append, len + 1); + + return __strcat(s, append); +} + +#undef strcpy +char *strcpy(char *dest, const char *src) +{ + if ((dest == NULL) || (src == NULL)) { + return NULL; + } + + size_t len = strlen(src); + __asan_storeN_noabort((UINTPTR)dest, len + 1); + __asan_loadN_noabort((UINTPTR)src, len + 1); + + return __strcpy(dest, src); +} + +#undef strncat +char *strncat(char *dest, const char *src, size_t n) +{ + if ((dest == NULL) || (src == NULL)) { + return NULL; + } + + CHAR *end = dest; + size_t len = strlen(src); + size_t size = len > n ? n : len; + for (; *end != '\0'; ++end) { + } + + __asan_storeN_noabort((UINTPTR)end, size + 1); + __asan_loadN_noabort((UINTPTR)src, size + 1); + + return __strncat(dest, src, n); +} + +#undef strncpy +char *strncpy(char *dest, const char *src, size_t n) +{ + if ((dest == NULL) || (src == NULL)) { + return NULL; + } + + size_t len = strlen(src); + size_t size = len > n ? n : len; + + __asan_storeN_noabort((UINTPTR)dest, n); + __asan_loadN_noabort((UINTPTR)src, size + 1); + return __strncpy(dest, src, n); +} \ No newline at end of file diff --git a/kernel/extended/lms/los_lms.c b/kernel/extended/lms/los_lms.c new file mode 100755 index 00000000..64ada0f1 --- /dev/null +++ b/kernel/extended/lms/los_lms.c @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_lms_pri.h" +#include "los_spinlock.h" +#include "los_exc.h" +#include "los_sched_pri.h" +#include "los_atomic.h" +#include "los_init.h" + +LITE_OS_SEC_BSS STATIC LmsMemListNode g_lmsCheckPoolArray[LOSCFG_LMS_MAX_RECORD_POOL_NUM]; +LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_lmsCheckPoolList; +STATIC Atomic g_checkDepth = 0; +LmsHook *g_lms = NULL; + +LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_lmsSpin); +#define LMS_LOCK(state) LOS_SpinLockSave(&g_lmsSpin, &(state)) +#define LMS_UNLOCK(state) LOS_SpinUnlockRestore(&g_lmsSpin, (state)) + +#define OS_MEM_ALIGN_BACK(value, align) (((UINT32)(value)) & ~((UINT32)((align) - 1))) +#define OS_MEM_ALIGN_SIZE sizeof(UINTPTR) +#define POOL_ADDR_ALIGNSIZE 64 +#define LMS_POOL_UNUSED 0 +#define LMS_POOL_USED 1 +#define INVALID_SHADOW_VALUE 0xFFFFFFFF + +STATIC UINT32 OsLmsPoolResize(UINT32 size) +{ + return OS_MEM_ALIGN_BACK(LMS_POOL_RESIZE(size), POOL_ADDR_ALIGNSIZE); +} + +STATIC LmsMemListNode *OsLmsGetPoolNode(const VOID *pool) +{ + UINTPTR poolAddr = (UINTPTR)pool; + LmsMemListNode *current = NULL; + LOS_DL_LIST *listHead = &g_lmsCheckPoolList; + + if (LOS_ListEmpty(&g_lmsCheckPoolList)) { + goto EXIT; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) { + if (current->poolAddr == poolAddr) { + return current; + } + } + +EXIT: + return NULL; +} + +STATIC LmsMemListNode *OsLmsGetPoolNodeFromAddr(UINTPTR addr) +{ + LmsMemListNode *current = NULL; + LOS_DL_LIST *listHead = &g_lmsCheckPoolList; + + if (LOS_ListEmpty(&g_lmsCheckPoolList)) { + goto EXIT; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) { + if ((addr >= current->poolAddr) && (addr < current->poolAddr + current->poolSize)) { + return current; + } + } + +EXIT: + return NULL; +} + +STATIC LmsMemListNode *OsLmsCheckPoolCreate(VOID) +{ + UINT32 i; + LmsMemListNode *current = NULL; + for (i = 0; i < LOSCFG_LMS_MAX_RECORD_POOL_NUM; i++) { + current = &g_lmsCheckPoolArray[i]; + if (current->used == LMS_POOL_UNUSED) { + current->used = LMS_POOL_USED; + return current; + } + } + return NULL; +} + +UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size) +{ + UINT32 intSave; + UINTPTR poolAddr = (UINTPTR)pool; + UINT32 realSize; + LmsMemListNode *lmsPoolNode = NULL; + + if (pool == NULL) { + return 0; + } + + LMS_LOCK(intSave); + + lmsPoolNode = OsLmsGetPoolNodeFromAddr((UINTPTR)pool); + if (lmsPoolNode != NULL) { /* if pool range already on checklist */ + if (lmsPoolNode->poolAddr != (UINTPTR)pool) { /* pool is a subset of lmsPoolNode->poolAddr */ + /* do not add it again, just return */ + PRINT_DEBUG("[LMS]pool %p already on lms checklist !\n", pool); + LMS_UNLOCK(intSave); + return size; /* return size indicate the shadow memory init successful */ + } else { /* Re-initialize the same pool, maybe with different size */ + /* delete the old node, then add a new one */ + lmsPoolNode->used = LMS_POOL_UNUSED; + LOS_ListDelete(&(lmsPoolNode->node)); + } + } + + lmsPoolNode = OsLmsCheckPoolCreate(); + if (lmsPoolNode == NULL) { + PRINT_DEBUG("[LMS]the num of lms check pool is max already !\n"); + LMS_UNLOCK(intSave); + return 0; + } + realSize = OsLmsPoolResize(size); + + lmsPoolNode->poolAddr = poolAddr; + lmsPoolNode->poolSize = realSize; + lmsPoolNode->shadowStart = (UINTPTR)poolAddr + realSize; + lmsPoolNode->shadowSize = poolAddr + size - lmsPoolNode->shadowStart; + /* init shadow value */ + (VOID)memset((VOID *)lmsPoolNode->shadowStart, LMS_SHADOW_AFTERFREE_U8, lmsPoolNode->shadowSize); + + LOS_ListAdd(&g_lmsCheckPoolList, &(lmsPoolNode->node)); + + LMS_UNLOCK(intSave); + return realSize; +} + +VOID LOS_LmsCheckPoolDel(const VOID *pool) +{ + UINT32 intSave; + if (pool == NULL) { + return; + } + + LMS_LOCK(intSave); + LmsMemListNode *delNode = OsLmsGetPoolNode(pool); + if (delNode == NULL) { + PRINT_ERR("[LMS]pool %p is not on lms checklist !\n", pool); + goto Release; + } + delNode->used = LMS_POOL_UNUSED; + LOS_ListDelete(&(delNode->node)); +Release: + LMS_UNLOCK(intSave); +} + +STATIC UINT32 OsLmsInit(VOID) +{ + (VOID)memset(g_lmsCheckPoolArray, 0, sizeof(g_lmsCheckPoolArray)); + LOS_ListInit(&g_lmsCheckPoolList); + static LmsHook hook = { + .init = LOS_LmsCheckPoolAdd, + .mallocMark = OsLmsLosMallocMark, + .freeMark = OsLmsLosFreeMark, + .simpleMark = OsLmsSimpleMark, + .check = OsLmsCheckValid, + }; + g_lms = &hook; + return LOS_OK; +} + +STATIC INLINE UINT32 OsLmsMem2Shadow(LmsMemListNode *node, UINTPTR memAddr, UINTPTR *shadowAddr, UINT32 *shadowOffset) +{ + if ((memAddr < node->poolAddr) || (memAddr >= node->poolAddr + node->poolSize)) { /* check ptr valid */ + PRINT_ERR("[LMS]memAddr %p is not in pool region [%p, %p)\n", memAddr, node->poolAddr, + node->poolAddr + node->poolSize); + return LOS_NOK; + } + + UINT32 memOffset = memAddr - node->poolAddr; + *shadowAddr = node->shadowStart + memOffset / LMS_SHADOW_U8_REFER_BYTES; + *shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) * + LMS_SHADOW_BITS_PER_CELL; /* (memOffset % 16) / 4 */ + return LOS_OK; +} + +STATIC INLINE VOID OsLmsGetShadowInfo(LmsMemListNode *node, UINTPTR memAddr, LmsAddrInfo *info) +{ + UINTPTR shadowAddr; + UINT32 shadowOffset; + UINT32 shadowValue; + + if (OsLmsMem2Shadow(node, memAddr, &shadowAddr, &shadowOffset) != LOS_OK) { + return; + } + + shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK; + info->memAddr = memAddr; + info->shadowAddr = shadowAddr; + info->shadowOffset = shadowOffset; + info->shadowValue = shadowValue; +} + +VOID OsLmsSetShadowValue(LmsMemListNode *node, UINTPTR startAddr, UINTPTR endAddr, UINT8 value) +{ + UINTPTR shadowStart; + UINTPTR shadowEnd; + UINT32 startOffset; + UINT32 endOffset; + + UINT8 shadowValueMask; + UINT8 shadowValue; + + /* endAddr -1, then we mark [startAddr, endAddr) to value */ + if (OsLmsMem2Shadow(node, startAddr, &shadowStart, &startOffset) || + OsLmsMem2Shadow(node, endAddr - 1, &shadowEnd, &endOffset)) { + return; + } + + if (shadowStart == shadowEnd) { /* in the same u8 */ + /* because endAddr - 1, the endOffset falls into the previous cell, + so endOffset + 2 is required for calculation */ + shadowValueMask = LMS_SHADOW_MASK_U8; + shadowValueMask = + (shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL))); + shadowValue = value & shadowValueMask; + *(UINT8 *)shadowStart &= ~shadowValueMask; + *(UINT8 *)shadowStart |= shadowValue; + } else { + /* Adjust startAddr to left util it reach the beginning of a u8 */ + if (startOffset > 0) { + shadowValueMask = LMS_SHADOW_MASK_U8; + shadowValueMask = shadowValueMask << startOffset; + shadowValue = value & shadowValueMask; + *(UINT8 *)shadowStart &= ~shadowValueMask; + *(UINT8 *)shadowStart |= shadowValue; + shadowStart += 1; + } + + /* Adjust endAddr to right util it reach the end of a u8 */ + if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) { + shadowValueMask = LMS_SHADOW_MASK_U8; + shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)); + shadowValue = value & shadowValueMask; + *(UINT8 *)shadowEnd &= ~shadowValueMask; + *(UINT8 *)shadowEnd |= shadowValue; + shadowEnd -= 1; + } + + if (shadowEnd + 1 > shadowStart) { + (VOID)memset((VOID *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart); + } + } +} + +VOID OsLmsGetShadowValue(LmsMemListNode *node, UINTPTR addr, UINT32 *shadowValue) +{ + UINTPTR shadowAddr; + UINT32 shadowOffset; + if (OsLmsMem2Shadow(node, addr, &shadowAddr, &shadowOffset) != LOS_OK) { + return; + } + + *shadowValue = ((*(UINT8 *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK; +} + +VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value) +{ + UINT32 intSave; + if (endAddr <= startAddr) { + PRINT_DEBUG("[LMS]mark 0x%x, 0x%x, 0x%x\n", startAddr, endAddr, (UINTPTR)__builtin_return_address(0)); + return; + } + + if (!IS_ALIGNED(startAddr, OS_MEM_ALIGN_SIZE) || !IS_ALIGNED(endAddr, OS_MEM_ALIGN_SIZE)) { + PRINT_ERR("[LMS]mark addr is not aligned! 0x%x, 0x%x\n", startAddr, endAddr); + return; + } + + LMS_LOCK(intSave); + + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(startAddr); + if (node == NULL) { + LMS_UNLOCK(intSave); + return; + } + + OsLmsSetShadowValue(node, startAddr, endAddr, value); + LMS_UNLOCK(intSave); +} + +VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize) +{ + UINT32 intSave; + UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart; + UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart; + + LMS_LOCK(intSave); + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart); + if (node == NULL) { + LMS_UNLOCK(intSave); + return; + } + + OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8); + OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_ACCESSABLE_U8); + OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_REDZONE_U8); + LMS_UNLOCK(intSave); +} + +VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck) +{ + UINT32 intSave; + UINT32 shadowValue = INVALID_SHADOW_VALUE; + LMS_LOCK(intSave); + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(checkAddr); + if (node == NULL) { + LMS_UNLOCK(intSave); + return; + } + + OsLmsGetShadowValue(node, checkAddr, &shadowValue); + LMS_UNLOCK(intSave); + if ((shadowValue == LMS_SHADOW_ACCESSABLE) || ((isFreeCheck) && (shadowValue == LMS_SHADOW_PAINT))) { + return; + } + + OsLmsReportError(checkAddr, MEM_REGION_SIZE_1, isFreeCheck ? FREE_ERRORMODE : COMMON_ERRMODE); +} + +VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize) +{ + UINT32 intSave; + UINT32 shadowValue = INVALID_SHADOW_VALUE; + + LMS_LOCK(intSave); + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr((UINTPTR)curNodeStart); + if (node == NULL) { + LMS_UNLOCK(intSave); + return; + } + + UINTPTR curNodeStartAddr = (UINTPTR)curNodeStart; + UINTPTR nextNodeStartAddr = (UINTPTR)nextNodeStart; + + OsLmsGetShadowValue(node, curNodeStartAddr + nodeHeadSize, &shadowValue); + if ((shadowValue != LMS_SHADOW_ACCESSABLE) && (shadowValue != LMS_SHADOW_PAINT)) { + LMS_UNLOCK(intSave); + OsLmsReportError(curNodeStartAddr + nodeHeadSize, MEM_REGION_SIZE_1, FREE_ERRORMODE); + return; + } + + if (*((UINT8 *)curNodeStart) == 0) { /* if merge the node has memset with 0 */ + OsLmsSetShadowValue(node, curNodeStartAddr, curNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8); + } + OsLmsSetShadowValue(node, curNodeStartAddr + nodeHeadSize, nextNodeStartAddr, LMS_SHADOW_AFTERFREE_U8); + + if (*((UINT8 *)nextNodeStart) == 0) { /* if merge the node has memset with 0 */ + OsLmsSetShadowValue(node, nextNodeStartAddr, nextNodeStartAddr + nodeHeadSize, LMS_SHADOW_AFTERFREE_U8); + } + + LMS_UNLOCK(intSave); +} + +VOID LOS_LmsAddrProtect(UINTPTR addrStart, UINTPTR addrEnd) +{ + UINT32 intSave; + if (addrEnd <= addrStart) { + return; + } + LMS_LOCK(intSave); + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart); + if (node != NULL) { + OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_REDZONE_U8); + } + LMS_UNLOCK(intSave); +} + +VOID LOS_LmsAddrDisableProtect(UINTPTR addrStart, UINTPTR addrEnd) +{ + UINT32 intSave; + if (addrEnd <= addrStart) { + return; + } + LMS_LOCK(intSave); + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addrStart); + if (node != NULL) { + OsLmsSetShadowValue(node, addrStart, addrEnd, LMS_SHADOW_ACCESSABLE_U8); + } + LMS_UNLOCK(intSave); +} + +STATIC UINT32 OsLmsCheckAddr(UINTPTR addr) +{ + UINT32 intSave; + UINT32 shadowValue = INVALID_SHADOW_VALUE; + /* do not check nested or before all cpu start */ + if ((LOS_AtomicRead(&g_checkDepth)) || (!OS_SCHEDULER_ALL_ACTIVE)) { + return 0; + } + + LMS_LOCK(intSave); + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr); + if (node == NULL) { + LMS_UNLOCK(intSave); + return LMS_SHADOW_ACCESSABLE_U8; + } + + OsLmsGetShadowValue(node, addr, &shadowValue); + LMS_UNLOCK(intSave); + return shadowValue; +} + +#ifdef LOSCFG_LMS_CHECK_STRICT +STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size) +{ + UINT32 i; + for (i = 0; i < size; i++) { + if (OsLmsCheckAddr(addr + i)) { + return LOS_NOK; + } + } + return LOS_OK; +} + +#else +STATIC INLINE UINT32 OsLmsCheckAddrRegion(UINTPTR addr, UINT32 size) +{ + if (OsLmsCheckAddr(addr) || OsLmsCheckAddr(addr + size - 1)) { + return LOS_NOK; + } else { + return LOS_OK; + } +} +#endif + +VOID OsLmsPrintPoolListInfo(VOID) +{ + UINT32 count = 0; + UINT32 intSave; + LmsMemListNode *current = NULL; + LOS_DL_LIST *listHead = &g_lmsCheckPoolList; + + LMS_LOCK(intSave); + LOS_DL_LIST_FOR_EACH_ENTRY(current, listHead, LmsMemListNode, node) + { + count++; + PRINT_DEBUG( + "[LMS]memory pool[%1u]: totalsize 0x%-8x memstart 0x%-8x memstop 0x%-8x memsize 0x%-8x shadowstart 0x%-8x " + "shadowSize 0x%-8x\n", + count, current->poolSize + current->shadowSize, current->poolAddr, current->poolAddr + current->poolSize, + current->poolSize, current->shadowStart, current->shadowSize); + } + + LMS_UNLOCK(intSave); +} + +VOID OsLmsPrintMemInfo(UINTPTR addr) +{ +#define LMS_DUMP_OFFSET 16 +#define LMS_DUMP_RANGE_DOUBLE 2 + + PRINTK("\n[LMS] Dump info around address [0x%8x]:\n", addr); + const UINT32 printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1; + const UINT32 printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE; + UINTPTR dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX; + UINT32 shadowValue = 0; + UINTPTR shadowAddr = 0; + UINT32 shadowOffset = 0; + LmsMemListNode *nodeInfo = NULL; + INT32 isCheckAddr, x, y; + + nodeInfo = OsLmsGetPoolNodeFromAddr(addr); + if (nodeInfo == NULL) { + PRINT_ERR("[LMS]addr is not in checkpool\n"); + return; + } + + for (y = 0; y < printY; y++, dumpAddr += printX) { + if (dumpAddr < nodeInfo->poolAddr) { /* find util dumpAddr in pool region */ + continue; + } + + if ((dumpAddr + printX) >= + nodeInfo->poolAddr + nodeInfo->poolSize) { /* finish if dumpAddr exceeds pool's upper region */ + goto END; + } + + PRINTK("\n\t[0x%x]: ", dumpAddr); + for (x = 0; x < printX; x++) { + if ((dumpAddr + x) == addr) { + PRINTK("[%02x]", *(UINT8 *)(dumpAddr + x)); + } else { + PRINTK(" %02x ", *(UINT8 *)(dumpAddr + x)); + } + } + + if (OsLmsMem2Shadow(nodeInfo, dumpAddr, &shadowAddr, &shadowOffset) != LOS_OK) { + goto END; + } + + PRINTK("|\t[0x%x | %2u]: ", shadowAddr, shadowOffset); + + for (x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) { + OsLmsGetShadowValue(nodeInfo, dumpAddr + x, &shadowValue); + isCheckAddr = dumpAddr + x - (UINTPTR)addr + LMS_MEM_BYTES_PER_SHADOW_CELL; + if ((isCheckAddr > 0) && (isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL)) { + PRINTK("[%1x]", shadowValue); + } else { + PRINTK(" %1x ", shadowValue); + } + } + } +END: + PRINTK("\n"); +} + +STATIC VOID OsLmsGetErrorInfo(UINTPTR addr, UINT32 size, LmsAddrInfo *info) +{ + LmsMemListNode *node = OsLmsGetPoolNodeFromAddr(addr); + OsLmsGetShadowInfo(node, addr, info); + if (info->shadowValue != LMS_SHADOW_ACCESSABLE_U8) { + return; + } else { + OsLmsGetShadowInfo(node, addr + size - 1, info); + } +} + +STATIC VOID OsLmsPrintErrInfo(LmsAddrInfo *info, UINT32 errMod) +{ + switch (info->shadowValue) { + case LMS_SHADOW_AFTERFREE: + PRINT_ERR("Use after free error detected\n"); + break; + case LMS_SHADOW_REDZONE: + PRINT_ERR("Heap buffer overflow error detected\n"); + break; + case LMS_SHADOW_ACCESSABLE: + PRINT_ERR("No error\n"); + break; + default: + PRINT_ERR("UnKnown Error detected\n"); + break; + } + + switch (errMod) { + case FREE_ERRORMODE: + PRINT_ERR("Illegal Double free address at: [0x%lx]\n", info->memAddr); + break; + case LOAD_ERRMODE: + PRINT_ERR("Illegal READ address at: [0x%lx]\n", info->memAddr); + break; + case STORE_ERRMODE: + PRINT_ERR("Illegal WRITE address at: [0x%lx]\n", info->memAddr); + break; + case COMMON_ERRMODE: + PRINT_ERR("Common Error at: [0x%lx]\n", info->memAddr); + break; + default: + PRINT_ERR("UnKnown Error mode at: [0x%lx]\n", info->memAddr); + break; + } + + PRINT_ERR("Shadow memory address: [0x%lx : %1u] Shadow memory value: [%u] \n", info->shadowAddr, + info->shadowOffset, info->shadowValue); +} + +VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod) +{ + UINT32 intSave; + LmsAddrInfo info; + + (VOID)LOS_AtomicAdd(&g_checkDepth, 1); + LMS_LOCK(intSave); + (VOID)memset(&info, 0, sizeof(LmsAddrInfo)); + + PRINT_ERR("***** Kernel Address Sanitizer Error Detected Start *****\n"); + + OsLmsGetErrorInfo(p, size, &info); + + OsLmsPrintErrInfo(&info, errMod); + + OsBackTrace(); + + OsLmsPrintMemInfo(info.memAddr); + LMS_UNLOCK(intSave); + PRINT_ERR("***** Kernel Address Sanitizer Error Detected End *****\n"); + (VOID)LOS_AtomicSub(&g_checkDepth, 1); +} + +#ifdef LOSCFG_LMS_STORE_CHECK +VOID __asan_store1_noabort(UINTPTR p) +{ + if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) { + OsLmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE); + } +} + +VOID __asan_store2_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE); + } +} + +VOID __asan_store4_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE); + } +} + +VOID __asan_store8_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE); + } +} + +VOID __asan_store16_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE); + } +} + +VOID __asan_storeN_noabort(UINTPTR p, UINT32 size) +{ + if (OsLmsCheckAddrRegion(p, size) != LOS_OK) { + OsLmsReportError(p, size, STORE_ERRMODE); + } +} +#else +VOID __asan_store1_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_store2_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_store4_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_store8_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_store16_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_storeN_noabort(UINTPTR p, UINT32 size) +{ + (VOID)p; + (VOID)size; +} + +#endif + +#ifdef LOSCFG_LMS_LOAD_CHECK +VOID __asan_load1_noabort(UINTPTR p) +{ + if (OsLmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) { + OsLmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE); + } +} + +VOID __asan_load2_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE); + } +} + +VOID __asan_load4_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE); + } +} + +VOID __asan_load8_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE); + } +} + +VOID __asan_load16_noabort(UINTPTR p) +{ + if (OsLmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LOS_OK) { + OsLmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE); + } +} + +VOID __asan_loadN_noabort(UINTPTR p, UINT32 size) +{ + if (OsLmsCheckAddrRegion(p, size) != LOS_OK) { + OsLmsReportError(p, size, LOAD_ERRMODE); + } +} +#else +VOID __asan_load1_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_load2_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_load4_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_load8_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_load16_noabort(UINTPTR p) +{ + (VOID)p; +} + +VOID __asan_loadN_noabort(UINTPTR p, UINT32 size) +{ + (VOID)p; + (VOID)size; +} +#endif +VOID __asan_handle_no_return(VOID) +{ + return; +} + +LOS_MODULE_INIT(OsLmsInit, LOS_INIT_LEVEL_KMOD_PREVM); \ No newline at end of file diff --git a/kernel/extended/lms/los_lms_pri.h b/kernel/extended/lms/los_lms_pri.h new file mode 100755 index 00000000..1eec619c --- /dev/null +++ b/kernel/extended/lms/los_lms_pri.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOS_LMS_PRI_H +#define _LOS_LMS_PRI_H + +#include "los_lms.h" +#include "los_typedef.h" +#include "los_list.h" +#include "securec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define COMMON_ERRMODE 3 +#define FREE_ERRORMODE 2 +#define STORE_ERRMODE 1 +#define LOAD_ERRMODE 0 + +#define SANITIZER_INTERFACE_ATTRIBUTE +#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) + +#define LMS_SHADOW_BITS_PER_CELL 2 +#define LMS_MEM_BYTES_PER_SHADOW_CELL 4 +#define LMS_SHADOW_U8_CELL_NUM 4 +#define LMS_SHADOW_U8_REFER_BYTES 16 + +#define LMS_POOL_RESIZE(size) ((size) / (LMS_SHADOW_U8_REFER_BYTES + 1) * LMS_SHADOW_U8_REFER_BYTES) +#define LMS_ADDR_ALIGN(p) (((UINTPTR)(p) + sizeof(UINTPTR) - 1) & ~((UINTPTR)(sizeof(UINTPTR) - 1))) + +#define LMS_SHADOW_ACCESSABLE 0x00 +#define LMS_SHADOW_AFTERFREE 0x03 +#define LMS_SHADOW_REDZONE 0x02 +#define LMS_SHADOW_PAINT 0x01 +#define LMS_SHADOW_MASK 0x03 + +#define LMS_SHADOW_ACCESSABLE_U8 0x00 +#define LMS_SHADOW_AFTERFREE_U8 0xFF +#define LMS_SHADOW_REDZONE_U8 0xAA +#define LMS_SHADOW_MASK_U8 0xFF +#define LMS_SHADOW_PAINT_U8 0x55 + +#define MEM_REGION_SIZE_1 1 +#define MEM_REGION_SIZE_2 2 +#define MEM_REGION_SIZE_4 4 +#define MEM_REGION_SIZE_8 8 +#define MEM_REGION_SIZE_16 16 + +typedef struct { + LOS_DL_LIST node; + UINT32 used; + UINTPTR poolAddr; + UINT32 poolSize; + UINTPTR shadowStart; + UINT32 shadowSize; +} LmsMemListNode; + +typedef struct { + UINTPTR memAddr; + UINTPTR shadowAddr; + UINT32 shadowOffset; + UINT32 shadowValue; +} LmsAddrInfo; + +typedef struct { + UINT32 (*init)(const VOID *pool, UINT32 size); + VOID (*mallocMark)(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize); + VOID (*freeMark)(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize); + VOID (*simpleMark)(UINTPTR startAddr, UINTPTR endAddr, UINT32 value); + VOID (*check)(UINTPTR checkAddr, BOOL isFreeCheck); +} LmsHook; +extern LmsHook* g_lms; + +VOID OsLmsCheckValid(UINTPTR checkAddr, BOOL isFreeCheck); +VOID OsLmsLosMallocMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize); +VOID OsLmsLosFreeMark(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize); +VOID OsLmsSimpleMark(UINTPTR startAddr, UINTPTR endAddr, UINT32 value); + +VOID OsLmsPrintPoolListInfo(VOID); +VOID OsLmsReportError(UINTPTR p, UINT32 size, UINT32 errMod); + +VOID CheckValid(const CHAR *dest, const CHAR *src); + +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store1_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store4_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load4_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load1_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_loadN_noabort(UINTPTR p, UINT32 size); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_storeN_noabort(UINTPTR p, UINT32 size); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store2_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load2_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store8_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load8_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_load16_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_store16_noabort(UINTPTR p); +extern SANITIZER_INTERFACE_ATTRIBUTE VOID __asan_handle_no_return(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_LMS_PRI_H */ \ No newline at end of file diff --git a/kernel/extended/lms/usr/BUILD.gn b/kernel/extended/lms/usr/BUILD.gn new file mode 100644 index 00000000..69433d1d --- /dev/null +++ b/kernel/extended/lms/usr/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//build/lite/config/component/lite_component.gni") + +copy("usrlmslib") { + deps = [ ":usrlms" ] + sources = [ get_path_info(".", "out_dir") + "/libusrlms.a" ] + outputs = [ "$root_out_dir/libusrlms.a" ] +} + +lite_library("usrlms") { + target_type = "static_library" + sources = [ + "los_lms.c", + "los_lmslibc.c", + ] + + include_dirs = [ "." ] + + cflags = [ + "-fPIC", + "-funwind-tables", + "-fasynchronous-unwind-tables", + ] + + ldflags = [ + "-rdynamic", + "-lunwind", + ] + + output_dir = target_out_dir +} diff --git a/kernel/extended/lms/usr/los_lms.c b/kernel/extended/lms/usr/los_lms.c new file mode 100755 index 00000000..524c2db7 --- /dev/null +++ b/kernel/extended/lms/usr/los_lms.c @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "los_lms_pri.h" +#include "debug.h" + +#define LMS_FREE_NODE_SIZE 16 + +struct MmapNode { + uintptr_t addr; + size_t mapSize; + struct MmapNode *next; +}; + +struct MmapNode g_freeNode[LMS_FREE_NODE_SIZE]; + +struct MmapNode *g_mmapNode = NULL; + +uint32_t g_shadowStartAddr = SHADOW_BASE; + +pthread_mutex_t g_lmsMutex = PTHREAD_MUTEX_INITIALIZER; + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsMem2Shadow(uintptr_t memAddr, uintptr_t *shadowAddr, uint32_t *shadowOffset) +{ + uint32_t memOffset = memAddr - USPACE_MAP_BASE; + *shadowAddr = g_shadowStartAddr + memOffset / LMS_SHADOW_U8_REFER_BYTES; + *shadowOffset = ((memOffset % LMS_SHADOW_U8_REFER_BYTES) / LMS_SHADOW_U8_CELL_NUM) * LMS_SHADOW_BITS_PER_CELL; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS uint32_t LmsIsShadowAddrMapped(uintptr_t sdStartAddr, uintptr_t sdEndAddr) +{ + struct MmapNode *node = g_mmapNode; + while (node != NULL) { + if ((sdStartAddr >= node->addr) && (sdEndAddr < node->addr + node->mapSize)) { + return LMS_OK; + } + node = node->next; + } + return LMS_NOK; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsAddMapNode(uintptr_t sdStartAddr, uintptr_t sdEndAddr) +{ + static uint32_t freeNodeIdx = 0; + struct MmapNode *node = g_mmapNode; + size_t mapSize; + uintptr_t shadowPageStartAddr = LMS_MEM_ALIGN_DOWN(sdStartAddr, 0x1000); + uintptr_t shadowPageEndAddr = LMS_MEM_ALIGN_UP(sdEndAddr, 0x1000); + + struct MmapNode *expandNode = NULL; + + while (node != NULL) { + if ((shadowPageStartAddr >= node->addr) && (shadowPageStartAddr <= node->addr + node->mapSize)) { + expandNode = node; + break; + } + node = node->next; + } + + if (expandNode != NULL) { + shadowPageStartAddr = expandNode->addr + expandNode->mapSize; + expandNode->mapSize = shadowPageEndAddr - expandNode->addr; + } + + mapSize = shadowPageEndAddr - shadowPageStartAddr; + void *mapPtr = + mmap((void *)shadowPageStartAddr, mapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mapPtr == (void *)-1) { + LMS_OUTPUT_INFO("mmap error! file:%s line:%d\n", __FILE__, __LINE__); + return; + } + __real_memset(mapPtr, 0, mapSize); + + if (expandNode != NULL) { + return; + } + + if (freeNodeIdx >= LMS_FREE_NODE_SIZE) { + LMS_OUTPUT_INFO("Add new mmap node error! file:%s line:%d\n", __FILE__, __LINE__); + return; + } + + struct MmapNode *newNode = &g_freeNode[freeNodeIdx]; + freeNodeIdx++; + newNode->addr = shadowPageStartAddr; + newNode->mapSize = mapSize; + newNode->next = g_mmapNode; + g_mmapNode = newNode; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsSetShadowValue(uintptr_t startAddr, uintptr_t endAddr, char value) +{ + uintptr_t shadowStart; + uintptr_t shadowEnd; + uint32_t startOffset; + uint32_t endOffset; + + char shadowValueMask; + char shadowValue; + + /* endAddr - 1, then we mark [startAddr, endAddr) to value */ + LmsMem2Shadow(startAddr, &shadowStart, &startOffset); + LmsMem2Shadow(endAddr - 1, &shadowEnd, &endOffset); + + if (shadowStart == shadowEnd) { /* in the same u8 */ + /* because endAddr - 1, the endOffset falls into the previous cell, + so endOffset + 2 is required for calculation */ + shadowValueMask = LMS_SHADOW_MASK_U8; + shadowValueMask = + (shadowValueMask << startOffset) & (~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL))); + shadowValue = value & shadowValueMask; + *(char *)shadowStart &= ~shadowValueMask; + *(char *)shadowStart |= shadowValue; + } else { + /* Adjust startAddr to left util it reach the beginning of a u8 */ + if (startOffset > 0) { + shadowValueMask = LMS_SHADOW_MASK_U8; + shadowValueMask = shadowValueMask << startOffset; + shadowValue = value & shadowValueMask; + *(char *)shadowStart &= ~shadowValueMask; + *(char *)shadowStart |= shadowValue; + shadowStart += 1; + } + + /* Adjust endAddr to right util it reach the end of a u8 */ + if (endOffset < (LMS_SHADOW_U8_CELL_NUM - 1) * LMS_SHADOW_BITS_PER_CELL) { + shadowValueMask = LMS_SHADOW_MASK_U8; + shadowValueMask &= ~(shadowValueMask << (endOffset + LMS_SHADOW_BITS_PER_CELL)); + shadowValue = value & shadowValueMask; + *(char *)shadowEnd &= ~shadowValueMask; + *(char *)shadowEnd |= shadowValue; + shadowEnd -= 1; + } + + if (shadowEnd + 1 > shadowStart) { + (void)__real_memset((void *)shadowStart, value & LMS_SHADOW_MASK_U8, shadowEnd + 1 - shadowStart); + } + } +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsGetShadowValue(uintptr_t addr, uint32_t *shadowValue) +{ + uintptr_t shadowAddr; + uint32_t shadowOffset; + LmsMem2Shadow(addr, &shadowAddr, &shadowOffset); + /* If the shadow addr is not mapped then regarded as legal access */ + if (LmsIsShadowAddrMapped(shadowAddr, shadowAddr) != LMS_OK) { + *shadowValue = LMS_SHADOW_ACCESSABLE_U8; + return; + } + + *shadowValue = ((*(char *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsMallocMark(uintptr_t preRzStart, uintptr_t accessMemStart, uintptr_t nextRzStart, + uintptr_t RzEndAddr) +{ + LmsSetShadowValue(preRzStart, accessMemStart, LMS_SHADOW_REDZONE_U8); + LmsSetShadowValue(accessMemStart, nextRzStart, LMS_SHADOW_ACCESSABLE_U8); + LmsSetShadowValue(nextRzStart, RzEndAddr, LMS_SHADOW_REDZONE_U8); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsTagMem(void *ptr, size_t origSize) +{ + g_shadowStartAddr = SHADOW_BASE; + size_t mSize = malloc_usable_size(ptr); + uint32_t memOffset = (uintptr_t)ptr + mSize + OVERHEAD - USPACE_MAP_BASE; + uintptr_t shadowEndAddr = g_shadowStartAddr + memOffset / LMS_SHADOW_U8_REFER_BYTES; + LMS_OUTPUT_INFO("SHADOW_BASE:%x g_shadowStartAddr:%x memOffset: %x\n", SHADOW_BASE, g_shadowStartAddr, memOffset); + memOffset = (uintptr_t)ptr - OVERHEAD - USPACE_MAP_BASE; + uintptr_t shadowStartAddr = g_shadowStartAddr + memOffset / LMS_SHADOW_U8_REFER_BYTES; + + LmsLock(&g_lmsMutex); + if (LmsIsShadowAddrMapped(shadowStartAddr, shadowEndAddr) != LMS_OK) { + LmsAddMapNode(shadowStartAddr, shadowEndAddr); + } + + LmsMallocMark((uintptr_t)ptr - OVERHEAD, (uintptr_t)ptr, (uintptr_t)ptr + LMS_MEM_ALIGN_UP(origSize, LMS_RZ_SIZE), + (uintptr_t)((uintptr_t)ptr + mSize + OVERHEAD)); + LmsUnlock(&g_lmsMutex); + + return ptr; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS uint32_t LmsCheckAddr(uintptr_t addr) +{ + LmsLock(&g_lmsMutex); + uint32_t shadowValue = -1; + LmsGetShadowValue(addr, &shadowValue); + LmsUnlock(&g_lmsMutex); + return shadowValue; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS uint32_t LmsCheckAddrRegion(uintptr_t addr, size_t size) +{ + if (LmsCheckAddr(addr) || LmsCheckAddr(addr + size - 1)) { + return LMS_NOK; + } else { + return LMS_OK; + } +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsPrintMemInfo(uintptr_t addr) +{ +#define LMS_DUMP_OFFSET 4 +#define LMS_DUMP_RANGE_DOUBLE 2 + + LMS_OUTPUT_INFO("\nDump info around address [0x%8x]:\n", addr); + uint32_t printY = LMS_DUMP_OFFSET * LMS_DUMP_RANGE_DOUBLE + 1; + uint32_t printX = LMS_MEM_BYTES_PER_SHADOW_CELL * LMS_DUMP_RANGE_DOUBLE; + uintptr_t dumpAddr = addr - addr % printX - LMS_DUMP_OFFSET * printX; + uint32_t shadowValue = 0; + uintptr_t shadowAddr = 0; + uint32_t shadowOffset = 0; + int isCheckAddr; + + for (int y = 0; y < printY; y++, dumpAddr += printX) { + LmsMem2Shadow(dumpAddr, &shadowAddr, &shadowOffset); + /* find util dumpAddr in pool region */ + if (LmsIsShadowAddrMapped(shadowAddr, shadowAddr) != LMS_OK) { + continue; + } + uintptr_t maxShadowAddr; + uint32_t maxShadowOffset; + LmsMem2Shadow(dumpAddr + printX, &maxShadowAddr, &maxShadowOffset); + /* finish if dumpAddr exceeds pool's upper region */ + if (LmsIsShadowAddrMapped(maxShadowAddr, maxShadowAddr) != LMS_OK) { + goto END; + } + + LMS_OUTPUT_INFO("\n\t[0x%x]: ", dumpAddr); + for (int x = 0; x < printX; x++) { + if (dumpAddr + x == addr) { + LMS_OUTPUT_INFO("[%02x]", *(uint8_t *)(dumpAddr + x)); + } else { + LMS_OUTPUT_INFO(" %02x ", *(uint8_t *)(dumpAddr + x)); + } + } + + LMS_OUTPUT_INFO("|\t[0x%x | %2d]: ", shadowAddr, shadowOffset); + + for (int x = 0; x < printX; x += LMS_MEM_BYTES_PER_SHADOW_CELL) { + LmsGetShadowValue(dumpAddr + x, &shadowValue); + isCheckAddr = dumpAddr + x - (uintptr_t)addr + LMS_MEM_BYTES_PER_SHADOW_CELL; + if (isCheckAddr > 0 && isCheckAddr <= LMS_MEM_BYTES_PER_SHADOW_CELL) { + LMS_OUTPUT_INFO("[%1x]", shadowValue); + } else { + LMS_OUTPUT_INFO(" %1x ", shadowValue); + } + } + } +END: + LMS_OUTPUT_INFO("\n"); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsGetShadowInfo(uintptr_t memAddr, LmsAddrInfo *info) +{ + uintptr_t shadowAddr; + uint32_t shadowOffset; + uint32_t shadowValue; + + LmsMem2Shadow(memAddr, &shadowAddr, &shadowOffset); + + shadowValue = ((*(char *)shadowAddr) >> shadowOffset) & LMS_SHADOW_MASK; + info->memAddr = memAddr; + info->shadowAddr = shadowAddr; + info->shadowOffset = shadowOffset; + info->shadowValue = shadowValue; +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static void LmsGetErrorInfo(uintptr_t addr, size_t size, LmsAddrInfo *info) +{ + LmsGetShadowInfo(addr, info); + if (info->shadowValue != LMS_SHADOW_ACCESSABLE_U8) { + return; + } else { + LmsGetShadowInfo(addr + size - 1, info); + } +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static void LmsPrintErrInfo(LmsAddrInfo *info, uint32_t errMod) +{ + switch (info->shadowValue) { + case LMS_SHADOW_AFTERFREE: + LMS_OUTPUT_ERROR("Use after free error detected!\n"); + break; + case LMS_SHADOW_REDZONE: + LMS_OUTPUT_ERROR("Heap buffer overflow error detected!\n"); + break; + case LMS_SHADOW_ACCESSABLE: + LMS_OUTPUT_ERROR("No error!\n"); + break; + default: + LMS_OUTPUT_ERROR("UnKnown Error detected!\n"); + break; + } + + switch (errMod) { + case FREE_ERRORMODE: + LMS_OUTPUT_ERROR("Illegal Double free address at: [0x%x]\n", info->memAddr); + break; + case LOAD_ERRMODE: + LMS_OUTPUT_ERROR("Illegal READ address at: [0x%x]\n", info->memAddr); + break; + case STORE_ERRMODE: + LMS_OUTPUT_ERROR("Illegal WRITE address at: [0x%x]\n", info->memAddr); + break; + default: + LMS_OUTPUT_ERROR("UnKnown Error mode at: [0x%x]\n", info->memAddr); + break; + } + + LMS_OUTPUT_INFO("Shadow memory address: [0x%x : %d] Shadow memory value: [%d] \n", info->shadowAddr, + info->shadowOffset, info->shadowValue); + + LMS_OUTPUT_INFO("\n"); + LMS_OUTPUT_INFO("%-25s%d\n", "Accessable heap addr", LMS_SHADOW_ACCESSABLE); + LMS_OUTPUT_INFO("%-25s%d\n", "Heap red zone", LMS_SHADOW_REDZONE); + LMS_OUTPUT_INFO("%-25s%d\n", "Heap freed buffer", LMS_SHADOW_AFTERFREE); + LMS_OUTPUT_INFO("\n"); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsReportError(uintptr_t p, size_t size, uint32_t errMod) +{ + LmsAddrInfo info; + (void)__real_memset(&info, 0, sizeof(LmsAddrInfo)); + + int locked = LmsTrylock(&g_lmsMutex); + LMS_OUTPUT_ERROR("\n***** Lite Memory Sanitizer Error Detected *****\n"); + LmsGetErrorInfo(p, size, &info); + LmsPrintErrInfo(&info, errMod); + LmsPrintMemInfo(info.memAddr); + LMS_OUTPUT_ERROR("***** Lite Memory Sanitizer Error Detected End *****\n"); + if (!locked) { + LmsUnlock(&g_lmsMutex); + } + + if (LMS_CRASH_MODE > 0) { + LmsCrash(); + } else { + print_trace(); + } +} + +void LmsCheckValid(const char *dest, const char *src) +{ + if (LmsCheckAddr((uintptr_t)dest) != LMS_SHADOW_ACCESSABLE_U8) { + LmsReportError((uintptr_t)dest, MEM_REGION_SIZE_1, STORE_ERRMODE); + return; + } + + if (LmsCheckAddr((uintptr_t)src) != LMS_SHADOW_ACCESSABLE_U8) { + LmsReportError((uintptr_t)src, MEM_REGION_SIZE_1, LOAD_ERRMODE); + return; + } + + for (uint32_t i = 0; *(src + i) != '\0'; i++) { + if (LmsCheckAddr((uintptr_t)dest + i + 1) != LMS_SHADOW_ACCESSABLE_U8) { + LmsReportError((uintptr_t)dest + i + 1, MEM_REGION_SIZE_1, STORE_ERRMODE); + return; + } + + if (LmsCheckAddr((uintptr_t)src + i + 1) != LMS_SHADOW_ACCESSABLE_U8) { + LmsReportError((uintptr_t)src + i + 1, MEM_REGION_SIZE_1, LOAD_ERRMODE); + return; + } + } +} + +void __asan_store1_noabort(uintptr_t p) +{ + if (LmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) { + LmsReportError(p, MEM_REGION_SIZE_1, STORE_ERRMODE); + } +} + +void __asan_store2_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_2, STORE_ERRMODE); + } +} + +void __asan_store4_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_4, STORE_ERRMODE); + } +} + +void __asan_store8_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_8, STORE_ERRMODE); + } +} + +void __asan_store16_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LMS_OK) { /* 16 byte memory for check */ + LmsReportError(p, MEM_REGION_SIZE_16, STORE_ERRMODE); + } +} + +void __asan_storeN_noabort(uintptr_t p, size_t size) +{ + if (LmsCheckAddrRegion(p, size) != LMS_OK) { + LmsReportError(p, size, STORE_ERRMODE); + } +} + +void __asan_load1_noabort(uintptr_t p) +{ + if (LmsCheckAddr(p) != LMS_SHADOW_ACCESSABLE_U8) { + LmsReportError(p, MEM_REGION_SIZE_1, LOAD_ERRMODE); + } +} + +void __asan_load2_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_2) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_2, LOAD_ERRMODE); + } +} + +void __asan_load4_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_4) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_4, LOAD_ERRMODE); + } +} + +void __asan_load8_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_8) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_8, LOAD_ERRMODE); + } +} + +void __asan_load16_noabort(uintptr_t p) +{ + if (LmsCheckAddrRegion(p, MEM_REGION_SIZE_16) != LMS_OK) { + LmsReportError(p, MEM_REGION_SIZE_16, LOAD_ERRMODE); + } +} + +void __asan_loadN_noabort(uintptr_t p, size_t size) +{ + if (LmsCheckAddrRegion(p, size) != LMS_OK) { + LmsReportError(p, size, LOAD_ERRMODE); + } +} + +void __asan_handle_no_return(void) +{ + return; +} \ No newline at end of file diff --git a/kernel/extended/lms/usr/los_lms.h b/kernel/extended/lms/usr/los_lms.h new file mode 100755 index 00000000..bad2ee4d --- /dev/null +++ b/kernel/extended/lms/usr/los_lms.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOS_LMS_H +#define _LOS_LMS_H + +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/* + * If LMS_CRASH_MODE == 0 + * the program would NOT be crashed once the sanitizer detected an error. + * If LMS_CRASM_MODE > 0 + * the program would be crashed once the sanitizer detected an error. + */ +#define LMS_CRASH_MODE 0 + +/* + * USPACE_MAP_BASE + * is the start address of user space. + */ +#define USPACE_MAP_BASE 0x00000000 + +/* + * USPACE_MAP_SIZE + * is the address size of the user space, and [USPACE_MAP_BASE, USPACE_MAP_BASE + USPACE_MAP_SIZE] + * must cover the HEAP section. + */ +#define USPACE_MAP_SIZE 0x3ef00000 + +/* + * LMS_OUTPUT_ERROR can be redefined to redirect output logs. + */ +#ifndef LMS_OUTPUT_ERROR +#define LMS_OUTPUT_ERROR(fmt, ...) \ + do { \ + (printf("\033[31;1m"), printf(fmt, ##__VA_ARGS__), printf("\033[0m")); \ + } while (0) +#endif + +/* + * LMS_OUTPUT_INFO can be redefined to redirect output logs. + */ +#ifndef LMS_OUTPUT_INFO +#define LMS_OUTPUT_INFO(fmt, ...) \ + do { \ + (printf("\033[33;1m"), printf(fmt, ##__VA_ARGS__), printf("\033[0m")); \ + } while (0) +#endif + + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_LMS_H */ \ No newline at end of file diff --git a/kernel/extended/lms/usr/los_lms_pri.h b/kernel/extended/lms/usr/los_lms_pri.h new file mode 100755 index 00000000..73e52c14 --- /dev/null +++ b/kernel/extended/lms/usr/los_lms_pri.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOS_LMS_PRI_H +#define _LOS_LMS_PRI_H + +#include +#include +#include "los_lms.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define UNKNOWN_ERROR 3 +#define FREE_ERRORMODE 2 +#define STORE_ERRMODE 1 +#define LOAD_ERRMODE 0 + +#define SANITIZER_INTERFACE_ATTRIBUTE +#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) + +#define LMS_SHADOW_ACCESSABLE 0x00 +#define LMS_SHADOW_AFTERFREE 0x03 +#define LMS_SHADOW_REDZONE 0x02 +#define LMS_SHADOW_PAINT 0x01 +#define LMS_SHADOW_MASK 0x03 + +#define LMS_SHADOW_BITS_PER_CELL 2 +#define LMS_MEM_BYTES_PER_SHADOW_CELL 4 +#define LMS_SHADOW_U8_CELL_NUM 4 +#define LMS_SHADOW_U8_REFER_BYTES 16 + +#define LMS_SHADOW_ACCESSABLE_U8 0x00 +#define LMS_SHADOW_AFTERFREE_U8 0xFF +#define LMS_SHADOW_REDZONE_U8 0xAA +#define LMS_SHADOW_MASK_U8 0xFF +#define LMS_SHADOW_PAINT_U8 0x55 + +#define MEM_REGION_SIZE_1 1 +#define MEM_REGION_SIZE_2 2 +#define MEM_REGION_SIZE_4 4 +#define MEM_REGION_SIZE_8 8 +#define MEM_REGION_SIZE_16 16 + +#define LMS_RZ_SIZE 4 +#define LMS_OK 0 +#define LMS_NOK 1 + +#define PAGE_ADDR_MASK 0xFFFFE000 +#define SHADOW_BASE \ + ((USPACE_MAP_BASE + (USPACE_MAP_SIZE / (LMS_SHADOW_U8_REFER_BYTES + 1)) * LMS_SHADOW_U8_REFER_BYTES) & \ + PAGE_ADDR_MASK) +#define OVERHEAD (2 * sizeof(size_t)) + +#define LMS_MEM_ALIGN_DOWN(value, align) (((uint32_t)(value)) & ~((uint32_t)((align) - 1))) +#define LMS_MEM_ALIGN_UP(value, align) (((uint32_t)(value) + ((align) - 1)) & ~((uint32_t)((align) - 1))) + +typedef struct { + uintptr_t memAddr; + uintptr_t shadowAddr; + uint32_t shadowOffset; + uint32_t shadowValue; +} LmsAddrInfo; + +extern pthread_mutex_t g_lmsMutex; + +ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsLock(pthread_mutex_t *lock) +{ + (void)pthread_mutex_lock(lock); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static inline int LmsTrylock(pthread_mutex_t *lock) +{ + return pthread_mutex_trylock(lock); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsUnlock(pthread_mutex_t *lock) +{ + (void)pthread_mutex_unlock(lock); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static inline void LmsCrash(void) +{ + *(volatile char *)(SHADOW_BASE - 1) = 0; +} + +uint32_t LmsIsShadowAddrMapped(uintptr_t sdStartAddr, uintptr_t sdEndAddr); + +void LmsSetShadowValue(uintptr_t startAddr, uintptr_t endAddr, char value); + +void LmsGetShadowValue(uintptr_t addr, uint32_t *shadowValue); + +void LmsReportError(uintptr_t p, size_t size, uint32_t errMod); + +void LmsMem2Shadow(uintptr_t memAddr, uintptr_t *shadowAddr, uint32_t *shadowOffset); + +void LmsCheckValid(const char *dest, const char *src); + +void *__real_malloc(size_t); + +void __real_free(void *); + +void *__real_calloc(size_t, size_t); + +void *__real_realloc(void *, size_t); + +void *__real_valloc(size_t); + +void *__real_aligned_alloc(size_t, size_t); + +void *__real_memcpy(void *__restrict, const void *__restrict, size_t); + +void *__real_memmove(void *, const void *, size_t); + +char *__real_strcat(char *, const char *); + +char *__real_strcpy(char *, const char *); + +void *__real_memset(void *, int, size_t); + +SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uintptr_t p, uint32_t size); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uintptr_t p, uint32_t size); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uintptr_t p); +SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_no_return(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_LMS_PRI_H */ \ No newline at end of file diff --git a/kernel/extended/lms/usr/los_lmslibc.c b/kernel/extended/lms/usr/los_lmslibc.c new file mode 100755 index 00000000..644908cc --- /dev/null +++ b/kernel/extended/lms/usr/los_lmslibc.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_lms_pri.h" + +ATTRIBUTE_NO_SANITIZE_ADDRESS void LmsFree(void *ptr) +{ + if (ptr == NULL) { + return; + } + + size_t allocSize = malloc_usable_size(ptr); + uintptr_t shadowAddr, offset; + LmsMem2Shadow((uintptr_t)ptr, &shadowAddr, &offset); + + LmsLock(&g_lmsMutex); + if (LmsIsShadowAddrMapped(shadowAddr, shadowAddr) == LMS_OK) { + uint32_t acShadowValue; + LmsGetShadowValue((uintptr_t)ptr, &acShadowValue); + if (acShadowValue != LMS_SHADOW_ACCESSABLE) { + char erroMode = (acShadowValue == LMS_SHADOW_AFTERFREE ? FREE_ERRORMODE : UNKNOWN_ERROR); + LmsReportError((uintptr_t)ptr, MEM_REGION_SIZE_1, erroMode); + goto UNLOCK_OUT; + } + } else { + LMS_OUTPUT_ERROR("Error! Free an unallocated memory:%p!\n", ptr); + goto UNLOCK_OUT; + } + + __real_free(ptr); + LmsSetShadowValue((uintptr_t)ptr, (uintptr_t)ptr + allocSize, LMS_SHADOW_AFTERFREE_U8); + +UNLOCK_OUT: + LmsUnlock(&g_lmsMutex); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMalloc(size_t size) +{ + void *ptr = __real_malloc(size); + if (ptr == NULL) { + return ptr; + } + return LmsTagMem(ptr, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsRealloc(void *ptr, size_t size) +{ + void *p = __real_realloc(ptr, size); + if (p == NULL) { + return p; + } + return LmsTagMem(p, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsCalloc(size_t m, size_t n) +{ + void *p = __real_calloc(m, n); + if (p == NULL) { + return p; + } + return LmsTagMem(p, n * m); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsValloc(size_t size) +{ + void *p = __real_valloc(size); + if (p == NULL) { + return p; + } + return LmsTagMem(p, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsAlignedAlloc(size_t align, size_t len) +{ + void *p = __real_aligned_alloc(align, len); + if (p == NULL) { + return p; + } + return LmsTagMem(p, len); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_aligned_alloc(size_t align, size_t len) +{ + return LmsAlignedAlloc(align, len); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_valloc(size_t size) +{ + return LmsValloc(size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_calloc(size_t m, size_t n) +{ + return LmsCalloc(m, n); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_realloc(void *p, size_t n) +{ + return LmsRealloc(p, n); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_malloc(size_t size) +{ + return LmsMalloc(size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void __wrap_free(void *ptr) +{ + return LmsFree(ptr); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMemset(void *p, int n, size_t size) +{ + __asan_storeN_noabort((uintptr_t)p, size); + + return __real_memset(p, n, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_memset(void *p, int n, size_t size) +{ + return LmsMemset(p, n, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMemcpy(void *__restrict dest, const void *__restrict src, size_t size) +{ + __asan_loadN_noabort((uintptr_t)src, size); + __asan_storeN_noabort((uintptr_t)dest, size); + + return __real_memcpy(dest, src, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_memcpy(void *__restrict dest, const void *__restrict src, size_t size) +{ + return LmsMemcpy(dest, src, size); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *LmsMemmove(void *dest, const void *src, size_t len) +{ + __asan_loadN_noabort((uintptr_t)src, len); + __asan_storeN_noabort((uintptr_t)dest, len); + + return __real_memmove(dest, src, len); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS void *__wrap_memmove(void *dest, const void *src, size_t len) +{ + return LmsMemmove(dest, src, len); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS char *LmsStrcat(char *s, const char *append) +{ + if ((s == NULL) || (append == NULL)) { + return NULL; + } + + char *save = s; + for (; *s != '\0'; ++s) { + } + LmsCheckValid(s, append); + + return __real_strcat(save, append); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS char *__wrap_strcat(char *s, const char *append) +{ + return LmsStrcat(s, append); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS char *LmsStrcpy(char *dest, const char *src) +{ + if ((dest == NULL) || (src == NULL)) { + return NULL; + } + + LmsCheckValid(dest, src); + return __real_strcpy(dest, src); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS char *__wrap_strcpy(char *dest, const char *src) +{ + return LmsStrcpy(dest, src); +} \ No newline at end of file diff --git a/kernel/include/los_lms.h b/kernel/include/los_lms.h new file mode 100755 index 00000000..f0a8bcad --- /dev/null +++ b/kernel/include/los_lms.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOS_LMS_H +#define _LOS_LMS_H + +#include "los_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_KERNEL_LMS + +UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size); +VOID LOS_LmsCheckPoolDel(const VOID *pool); +VOID LOS_LmsAddrProtect(UINTPTR addrStart, UINTPTR addrEnd); +VOID LOS_LmsAddrDisableProtect(UINTPTR addrStart, UINTPTR addrEnd); + +#endif /* LOSCFG_KERNEL_LMS */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_LMS_H */ \ No newline at end of file diff --git a/lib/libc/BUILD.gn b/lib/libc/BUILD.gn index 4937e5fe..c5beae17 100644 --- a/lib/libc/BUILD.gn +++ b/lib/libc/BUILD.gn @@ -63,11 +63,20 @@ kernel_module(module_name) { ] asmflags = [ "-D__strlen_armv6t2=strlen", - "-D__strcpy_arm=strcpy", "-D__strcmp_arm=strcmp", - "-D__memcpy_arm=memcpy", "-D__memchr_arm=memchr", ] + if (defined(LOSCFG_KERNEL_LMS)) { + asmflags += [ + "-D__memcpy_arm=__memcpy", + "-D__strcpy_arm=__strcpy", + ] + } else { + asmflags += [ + "-D__memcpy_arm=memcpy", + "-D__strcpy_arm=strcpy", + ] + } sources += [ "src/arch/arm/memcmp.S", "src/arch/arm/memset.S", diff --git a/lib/libc/Makefile b/lib/libc/Makefile index 562d957b..1de4959f 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -37,11 +37,15 @@ LOCAL_SRCS += \ LOCAL_CMACRO = \ -D__strlen_armv6t2=strlen \ - -D__strcpy_arm=strcpy \ -D__strcmp_arm=strcmp \ - -D__memcpy_arm=memcpy \ -D__memchr_arm=memchr +ifeq ($(LOSCFG_KERNEL_LMS), y) +LOCAL_CMACRO += -D__memcpy_arm=__memcpy -D__strcpy_arm=__strcpy +else +LOCAL_CMACRO += -D__memcpy_arm=memcpy -D__strcpy_arm=strcpy +endif + # Replace the general srcs of the same name with specially optimized srcs LOCAL_SRCS += $(LOCAL_OPT_SRCS) LOCAL_SRCS := $(filter-out $(LOCAL_FILTER_SRCS),$(LOCAL_SRCS)) diff --git a/lib/libc/src/arch/arm/memset.S b/lib/libc/src/arch/arm/memset.S index 5d948f12..63700d5c 100644 --- a/lib/libc/src/arch/arm/memset.S +++ b/lib/libc/src/arch/arm/memset.S @@ -31,10 +31,18 @@ .syntax unified .arch armv7-a .fpu neon - .globl memset @ -- Begin function memset - .p2align 2 - .type memset,%function -memset: + +#define FUNCTION(x) \ +.globl x; \ +.p2align 2; \ +.type x,%function; \ +x: + +#if defined(LOSCFG_KERNEL_LMS) +FUNCTION(__memset) +#else +FUNCTION(memset) +#endif @ r0 = address @ r1 = char @ r2 = count diff --git a/lib/libsec/BUILD.gn b/lib/libsec/BUILD.gn index 983f624f..ae17c178 100644 --- a/lib/libsec/BUILD.gn +++ b/lib/libsec/BUILD.gn @@ -35,6 +35,22 @@ module_name = get_path_info(rebase_path("."), "name") kernel_module(module_name) { sources = libsec_sources + if (defined(LOSCFG_KERNEL_LMS)) { + if (ohos_build_compiler == "gcc") { + cflags_c = [ "-fsanitize=kernel-address" ] + } else { + cflags_c = [ + "-fsanitize=kernel-address", + "-mllvm", + "-asan-instrumentation-with-call-threshold=0", + "-mllvm", + "-asan-stack=0", + "-mllvm", + "-asan-globals=0", + ] + } + } + public_configs = [ ":public" ] } diff --git a/tools/build/mk/los_config.mk b/tools/build/mk/los_config.mk index 87d1e721..df1dcf46 100644 --- a/tools/build/mk/los_config.mk +++ b/tools/build/mk/los_config.mk @@ -163,6 +163,12 @@ ifeq ($(LOSCFG_KERNEL_PERF), y) LITEOS_PERF_INCLUDE += -I $(LITEOSTOPDIR)/kernel/extended/perf endif +ifeq ($(LOSCFG_KERNEL_LMS), y) + LITEOS_BASELIB += -llms + LIB_SUBDIRS += kernel/extended/lms + LITEOS_LMS_INCLUDE += -I $(LITEOSTOPDIR)/kernel/extended/lms +endif + ifeq ($(LOSCFG_KERNEL_LITEIPC), y) LITEOS_BASELIB += -lliteipc LIB_SUBDIRS += kernel/extended/liteipc @@ -507,7 +513,7 @@ LITEOS_EXTKERNEL_INCLUDE := $(LITEOS_CPPSUPPORT_INCLUDE) $(LITEOS_DYNLOAD_INCL $(LITEOS_TICKLESS_INCLUDE) $(LITEOS_HOOK_INCLUDE)\ $(LITEOS_VDSO_INCLUDE) $(LITEOS_LITEIPC_INCLUDE) \ $(LITEOS_PIPE_INCLUDE) $(LITEOS_CPUP_INCLUDE) \ - $(LITEOS_PERF_INCLUDE) + $(LITEOS_PERF_INCLUDE) $(LITEOS_LMS_INCLUDE) LITEOS_COMPAT_INCLUDE := $(LITEOS_POSIX_INCLUDE) $(LITEOS_LINUX_INCLUDE) \ $(LITEOS_BSD_INCLUDE) LITEOS_FS_INCLUDE := $(LITEOS_VFS_INCLUDE) $(LITEOS_FAT_CACHE_INCLUDE) \