• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# LMS
2
3
4## Basic Concepts
5
6Lite Memory Sanitizer (LMS) is a tool used to detect memory errors on a real-time basis. It can detect buffer overflow, Use-After-Free (UAF), and double free errors in real time, and notify the operating system immediately. Together with Backtrace, the LMS can locate the code line that causes the memory error. It greatly improves the efficiency of locating memory errors.
7
8The LMS module of the OpenHarmony LiteOS-M kernel provides the following functions:
9
10- Supports check of multiple memory pools.
11
12- Checks the memory allocated by **LOS_MemAlloc**, **LOS_MemAllocAlign**, and **LOS_MemRealloc**.
13
14- Checks the memory when bounds-checking functions are called (enabled by default).
15
16- Checks the memory when libc frequently accessed functions, including **memset**, **memcpy**, **memmove**, **strcat**, **strcpy**, **strncat** and **strncpy**, are called.
17
18
19## Working Principles
20
21The LMS uses shadow memory mapping to mark the system memory state. There are three states: **Accessible**, **RedZone**, and **Freed**. The shadow memory is located in the tail of the memory pool.
22
23- After memory is allocated from the heap, the shadow memory in the data area is set to the **Accessible** state, and the shadow memory in the head node area is set to the **RedZone** state.
24
25- When memory is released from the heap, the shadow memory of the released memory is set to the **Freed** state.
26
27- During code compilation, a function is inserted before the read/write instructions in the code to check the address validity. The tool checks the state value of the shadow memory that accesses the memory. If the shadow memory is in the **RedZone** statue, an overflow error will be reported. If the shadow memory is in the **Freed** state, a UAF error will be reported.
28
29- When memory is released, the tool checks the state value of the shadow memory at the released address. If the shadow memory is in the **RedZone** state, a double free error will be reported.
30
31
32## Available APIs
33
34The LMS module of the OpenHarmony LiteOS-A kernel provides the following APIs. For more details, see [API reference](https://gitee.com/openharmony/kernel_liteos_m/blob/master/components/lms/los_lms.h).
35
36**Table 1** APIs of the LMS module
37
38| Category| API | Description|
39| -------- | -------- | -------- |
40| Adding a memory pool to be checked| LOS_LmsCheckPoolAdd | Adds the address range of a memory pool to the LMS check linked list. LMS performs a validity check when the accessed address is within the linked list. In addition, **LOS_MemInit** calls this API to add the initialized memory pool to the LMS check linked list by default.|
41| Deleting a memory pool from the LMS check linked list| LOS_LmsCheckPoolDel | Cancels the validity check on the specified memory pool.|
42| Protecting a specified memory chunk| LOS_LmsAddrProtect | Locks a memory chunk to prevent it from being read or written. Once the locked memory chunk is accessed, an error will be reported.|
43| Disabling protection of a specified memory chunk| LOS_LmsAddrDisableProtect | Unlocks a memory chunk to make it readable and writable.|
44
45
46## Development Guidelines
47
48
49### How to Develop
50
51The typical process for enabling LMS is as follows:
52
531. Configure the macros related to the LMS module.
54   Configure the LMS macro **LOSCFG_KERNEL_LMS**, which is disabled by default.
55
56   Run the **make menuconfig** command in the **kernel/liteos_m** directory, and set **Kernel->Enable Lite Memory Sanitizer** to **YES**. If this option is unavailable, select **Enable Backtrace**.
57
58   | Macro| menuconfig Option| Description| Value|
59   | -------- | -------- | -------- | -------- |
60   | LOSCFG_KERNEL_LMS | Enable Lms Feature | Whether to enable LMS.| YES/NO |
61   | LOSCFG_LMS_MAX_RECORD_POOL_NUM | Lms check pool max num | Maximum number of memory pools that can be checked by LMS.| INT |
62   | LOSCFG_LMS_LOAD_CHECK | Enable lms read check | Whether to enable LMS read check.| YES/NO |
63   | LOSCFG_LMS_STORE_CHECK | Enable lms write check | Whether to enable LMS write check.| YES/NO |
64   | LOSCFG_LMS_CHECK_STRICT | Enable lms strict check, byte-by-byte | Whether to enable LMS byte-by-byte check.| YES/NO |
65
662. Modify the build script of the target module.
67   Add **-fsanitize=kernel-address** to insert memory access checks, and add **-O0** to disable optimization performed by the compiler.
68
69   The modifications vary depending on the compiler (GCC or Clang) used. The following is an example:
70
71   ```
72   if ("$ohos_build_compiler_specified" == "gcc") {
73       cflags_c = [
74       "-O0",
75       "-fsanitize=kernel-address",
76       ]
77   } else {
78       cflags_c = [
79       "-O0",
80       "-fsanitize=kernel-address",
81       "-mllvm",
82       "-asan-instrumentation-with-call-threshold=0",
83       "-mllvm",
84       "-asan-stack=0",
85       "-mllvm",
86       "-asan-globals=0",
87       ]
88   }
89   ```
90
913. Recompile the code and check the serial port output.
92
93   The memory problem detected will be displayed.
94
95
96### Development Example
97
98This example implements the following:
99
1001. Create a task for LMS.
101
1022. Construct a buffer overflow error and a UAF error.
103
1043. Add "-fsanitize=kernel-address", execute the compilation, and check the output.
105
106
107### Sample Code
108
109The code is as follows:
110
111The sample code can be compiled and verified in **./kernel/liteos_m/testsuites/src/osTest.c**. The **Example_Lms_test** function is called in **TestTaskEntry**.
112
113Modify **./kernel/liteos_m/testsuites/BUILD.gn** corresponding to **osTest.c**.
114
115```
116#define PAGE_SIZE       (0x1000U)
117#define INDEX_MAX       20
118UINT32 g_lmsTestTaskId;
119char g_testLmsPool[2 * PAGE_SIZE];
120STATIC VOID testPoolInit(void)
121{
122    UINT32 ret = LOS_MemInit(g_testLmsPool, 2 * PAGE_SIZE);
123    if (ret != 0) {
124        PRINT_ERR("%s failed, ret = 0x%x\n", __FUNCTION__, ret);
125        return;
126    }
127}
128static VOID LmsTestOsmallocOverflow(VOID)
129{
130    PRINTK("\n######%s start ######\n", __FUNCTION__);
131    UINT32 i;
132    CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX);
133    PRINTK("str[%2d]=0x%2x ", INDEX_MAX, str[INDEX_MAX]); /* trigger heap overflow at str[INDEX_MAX] */
134    PRINTK("\n######%s stop ######\n", __FUNCTION__);
135}
136static VOID LmsTestUseAfterFree(VOID)
137{
138    PRINTK("\n######%s start ######\n", __FUNCTION__);
139    UINT32 i;
140    CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX);
141    LOS_MemFree(g_testLmsPool, str);
142    PRINTK("str[%2d]=0x%2x ", 0, str[0]); /* trigger use after free at str[0] */
143    PRINTK("\n######%s stop ######\n", __FUNCTION__);
144}
145VOID LmsTestCaseTask(VOID)
146{
147    testPoolInit();
148    LmsTestOsmallocOverflow();
149    LmsTestUseAfterFree();
150}
151UINT32 Example_Lms_test(VOID){
152    UINT32 ret;
153    TSK_INIT_PARAM_S lmsTestTask;
154    /* Create a task for LMS. */
155    memset(&lmsTestTask, 0, sizeof(TSK_INIT_PARAM_S));
156    lmsTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)LmsTestCaseTask;
157    lmsTestTask.pcName       = "TestLmsTsk";  /* Test task name. */
158    lmsTestTask.uwStackSize  = 0x800;
159    lmsTestTask.usTaskPrio   = 5;
160    lmsTestTask.uwResved   = LOS_TASK_STATUS_DETACHED;
161    ret = LOS_TaskCreate(&g_lmsTestTaskId, &lmsTestTask);
162    if(ret != LOS_OK){
163        PRINT_ERR("LmsTestTask create failed .\n");
164        return LOS_NOK;
165    }
166    return LOS_OK;
167}
168```
169
170
171### Verification
172
173  The following is an example of the command output. The data may vary depending on the running environment.
174
175```
176######LmsTestOsmallocOverflow start ######
177[ERR][TestLmsTsk]*****  Kernel Address Sanitizer Error Detected Start *****
178[ERR][TestLmsTsk]Heap buffer overflow error detected
179[ERR][TestLmsTsk]Illegal READ address at: [0x21040414]
180[ERR][TestLmsTsk]Shadow memory address: [0x21041e84 : 6]  Shadow memory value: [2]
181psp, start = 21057d88, end = 21057e80
182taskName = TestLmsTsk
183taskID   = 5
184----- traceback start -----
185traceback 0 -- lr = 0x210099f4
186traceback 1 -- lr = 0x2101da6e
187traceback 2 -- lr = 0x2101db38
188traceback 3 -- lr = 0x2101c494
189----- traceback end -----
190
191[LMS] Dump info around address [0x21040414]:
192
193        [0x21040390]:  00  00  00  00  00  00  00  00 | [0x21041e7c |  4]:  1  1
194        [0x21040398]:  00  00  00  00  00  00  00  00 | [0x21041e7d |  0]:  1  1
195        [0x210403a0]:  00  00  00  00  00  00  00  00 | [0x21041e7d |  4]:  1  1
196        [0x210403a8]:  00  00  00  00  00  00  00  00 | [0x21041e7e |  0]:  1  1
197        [0x210403b0]:  00  00  00  00  00  00  00  00 | [0x21041e7e |  4]:  1  1
198        [0x210403b8]:  00  00  00  00  00  00  00  00 | [0x21041e7f |  0]:  1  1
199        [0x210403c0]:  00  00  00  00  00  00  00  00 | [0x21041e7f |  4]:  1  1
200        [0x210403c8]:  00  00  00  00  00  00  00  00 | [0x21041e80 |  0]:  1  1
201        [0x210403d0]:  00  00  00  00  00  00  00  00 | [0x21041e80 |  4]:  1  1
202        [0x210403d8]:  00  00  00  00  00  00  00  00 | [0x21041e81 |  0]:  1  1
203        [0x210403e0]:  00  00  00  00  00  00  00  00 | [0x21041e81 |  4]:  1  1
204        [0x210403e8]:  00  00  00  00  00  00  00  00 | [0x21041e82 |  0]:  1  1
205        [0x210403f0]:  00  00  00  00  00  00  00  00 | [0x21041e82 |  4]:  1  1
206        [0x210403f8]:  40  1e  04  21  05  07  00  80 | [0x21041e83 |  0]:  2  2
207        [0x21040400]:  00  00  00  00  00  00  00  00 | [0x21041e83 |  4]:  0  0
208        [0x21040408]:  00  00  00  00  00  00  00  00 | [0x21041e84 |  0]:  0  0
209        [0x21040410]:  00  00  00  00 [f8] 03  04  21 | [0x21041e84 |  4]:  0 [2]
210        [0x21040418]:  00  8b  06  00  00  00  00  00 | [0x21041e85 |  0]:  2  3
211        [0x21040420]:  00  00  00  00  00  00  00  00 | [0x21041e85 |  4]:  3  3
212        [0x21040428]:  00  00  00  00  00  00  00  00 | [0x21041e86 |  0]:  3  3
213        [0x21040430]:  00  00  00  00  00  00  00  00 | [0x21041e86 |  4]:  3  3
214        [0x21040438]:  00  00  00  00  00  00  00  00 | [0x21041e87 |  0]:  3  3
215        [0x21040440]:  00  00  00  00  00  00  00  00 | [0x21041e87 |  4]:  3  3
216        [0x21040448]:  00  00  00  00  00  00  00  00 | [0x21041e88 |  0]:  3  3
217        [0x21040450]:  00  00  00  00  00  00  00  00 | [0x21041e88 |  4]:  3  3
218        [0x21040458]:  00  00  00  00  00  00  00  00 | [0x21041e89 |  0]:  3  3
219        [0x21040460]:  00  00  00  00  00  00  00  00 | [0x21041e89 |  4]:  3  3
220        [0x21040468]:  00  00  00  00  00  00  00  00 | [0x21041e8a |  0]:  3  3
221        [0x21040470]:  00  00  00  00  00  00  00  00 | [0x21041e8a |  4]:  3  3
222        [0x21040478]:  00  00  00  00  00  00  00  00 | [0x21041e8b |  0]:  3  3
223        [0x21040480]:  00  00  00  00  00  00  00  00 | [0x21041e8b |  4]:  3  3
224        [0x21040488]:  00  00  00  00  00  00  00  00 | [0x21041e8c |  0]:  3  3
225        [0x21040490]:  00  00  00  00  00  00  00  00 | [0x21041e8c |  4]:  3  3
226[ERR][TestLmsTsk]*****  Kernel Address Sanitizer Error Detected End *****
227str[20]=0xfffffff8
228######LmsTestOsmallocOverflow stop ######
229
230######LmsTestUseAfterFree start ######
231[ERR][TestLmsTsk]*****  Kernel Address Sanitizer Error Detected Start *****
232[ERR][TestLmsTsk]Use after free error detected
233[ERR][TestLmsTsk]Illegal READ address at: [0x2104041c]
234[ERR][TestLmsTsk]Shadow memory address: [0x21041e85 : 2]  Shadow memory value: [3]
235psp, start = 21057d90, end = 21057e80
236taskName = TestLmsTsk
237taskID   = 5
238----- traceback start -----
239traceback 0 -- lr = 0x210099f4
240traceback 1 -- lr = 0x2101daec
241traceback 2 -- lr = 0x2101db3c
242traceback 3 -- lr = 0x2101c494
243----- traceback end -----
244
245[LMS] Dump info around address [0x2104041c]:
246
247        [0x21040398]:  00  00  00  00  00  00  00  00 | [0x21041e7d |  0]:  1  1
248        [0x210403a0]:  00  00  00  00  00  00  00  00 | [0x21041e7d |  4]:  1  1
249        [0x210403a8]:  00  00  00  00  00  00  00  00 | [0x21041e7e |  0]:  1  1
250        [0x210403b0]:  00  00  00  00  00  00  00  00 | [0x21041e7e |  4]:  1  1
251        [0x210403b8]:  00  00  00  00  00  00  00  00 | [0x21041e7f |  0]:  1  1
252        [0x210403c0]:  00  00  00  00  00  00  00  00 | [0x21041e7f |  4]:  1  1
253        [0x210403c8]:  00  00  00  00  00  00  00  00 | [0x21041e80 |  0]:  1  1
254        [0x210403d0]:  00  00  00  00  00  00  00  00 | [0x21041e80 |  4]:  1  1
255        [0x210403d8]:  00  00  00  00  00  00  00  00 | [0x21041e81 |  0]:  1  1
256        [0x210403e0]:  00  00  00  00  00  00  00  00 | [0x21041e81 |  4]:  1  1
257        [0x210403e8]:  00  00  00  00  00  00  00  00 | [0x21041e82 |  0]:  1  1
258        [0x210403f0]:  00  00  00  00  00  00  00  00 | [0x21041e82 |  4]:  1  1
259        [0x210403f8]:  40  1e  04  21  05  07  00  80 | [0x21041e83 |  0]:  2  2
260        [0x21040400]:  00  00  00  00  00  00  00  00 | [0x21041e83 |  4]:  0  0
261        [0x21040408]:  00  00  00  00  00  00  00  00 | [0x21041e84 |  0]:  0  0
262        [0x21040410]:  00  00  00  00  f8  03  04  21 | [0x21041e84 |  4]:  0  2
263        [0x21040418]:  05  8b  06  00 [00] 00  00  00 | [0x21041e85 |  0]:  2 [3]
264        [0x21040420]:  00  00  00  00  00  00  00  00 | [0x21041e85 |  4]:  3  3
265        [0x21040428]:  00  00  00  00  00  00  00  00 | [0x21041e86 |  0]:  3  3
266        [0x21040430]:  14  04  04  21  00  84  06  00 | [0x21041e86 |  4]:  2  2
267        [0x21040438]:  00  00  00  00  00  00  00  00 | [0x21041e87 |  0]:  3  3
268        [0x21040440]:  00  00  00  00  00  00  00  00 | [0x21041e87 |  4]:  3  3
269        [0x21040448]:  00  00  00  00  00  00  00  00 | [0x21041e88 |  0]:  3  3
270        [0x21040450]:  00  00  00  00  00  00  00  00 | [0x21041e88 |  4]:  3  3
271        [0x21040458]:  00  00  00  00  00  00  00  00 | [0x21041e89 |  0]:  3  3
272        [0x21040460]:  00  00  00  00  00  00  00  00 | [0x21041e89 |  4]:  3  3
273        [0x21040468]:  00  00  00  00  00  00  00  00 | [0x21041e8a |  0]:  3  3
274        [0x21040470]:  00  00  00  00  00  00  00  00 | [0x21041e8a |  4]:  3  3
275        [0x21040478]:  00  00  00  00  00  00  00  00 | [0x21041e8b |  0]:  3  3
276        [0x21040480]:  00  00  00  00  00  00  00  00 | [0x21041e8b |  4]:  3  3
277        [0x21040488]:  00  00  00  00  00  00  00  00 | [0x21041e8c |  0]:  3  3
278        [0x21040490]:  00  00  00  00  00  00  00  00 | [0x21041e8c |  4]:  3  3
279        [0x21040498]:  00  00  00  00  00  00  00  00 | [0x21041e8d |  0]:  3  3
280[ERR][TestLmsTsk]*****  Kernel Address Sanitizer Error Detected End *****
281str[ 0]=0x 0
282######LmsTestUseAfterFree stop ######
283```
284
285The key output information is as follows:
286
287- Error type:
288  - Heap buffer overflow
289  - UAF
290
291- Incorrect operations:
292  - Illegal read
293  - Illegal write
294  - Illegal double free
295
296- Context:
297  - Task information (**taskName** and **taskId**)
298  - Backtrace
299
300- Memory information of the error addresses:
301  - Memory value and the value of the corresponding shadow memory
302  - Memory address: memory value|[shadow memory address|shadow memory byte offset]: shadow memory value
303  - Shadow memory value. **0** (Accessible), **3** (Freed), **2** (RedZone), and **1** (filled value)
304