• 在kernel中使用内存检测


    目录

    一、slub内存检测

    1、越界访问

    2、释放后再访问

    3、无效的释放

    4、实验输出

    二、KASAN 内存检测

    1、数组越界

    2、栈的越界访问

    3、实验输出


    一般的内存访问错误如下:

    • 越界访问
    • 访问已经释放的内存
    • 重复释放
    • 内存泄露
    • 栈溢出

    在内核中提供了内存检测的工具slub与kasan,在开发时可以将检测的功能打开。

    一、slub内存检测

    linux内核中,对于小块内存分配,大量使用slab/slub分配器,在内存访问中比较容易出错的地方如下:

    • 访问已经释放的内存
    • 越界访问
    • 重复释放

    内核配置

    CONFIG_SLUB=y

    CONFIG_SLUB_DEBUG_ON=y

    CONFIG_SLUB_STATS=y

    使用的工具tools/vm/slabinfo    

    1、越界访问

    1. static noinline void __init kmalloc_pagealloc_oob_right(void)
    2. {
    3. char *ptr;
    4. size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
    5. /* Allocate a chunk that does not fit into a SLUB cache to trigger
    6. * the page allocator fallback.
    7. */
    8. pr_info("kmalloc pagealloc allocation: out-of-bounds to right\n");
    9. ptr = kmalloc(size, GFP_KERNEL);
    10. if (!ptr) {
    11. pr_err("Allocation failed\n");
    12. return;
    13. }
    14. ptr[size] = 0;
    15. kfree(ptr);
    16. }

    2、释放后再访问

    1. static noinline void __init kmalloc_pagealloc_uaf(void)
    2. {
    3. char *ptr;
    4. size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
    5. pr_info("kmalloc pagealloc allocation: use-after-free\n");
    6. ptr = kmalloc(size, GFP_KERNEL);
    7. if (!ptr) {
    8. pr_err("Allocation failed\n");
    9. return;
    10. }
    11. kfree(ptr);
    12. ptr[0] = 0;
    13. }

    3、无效的释放

    1. static noinline void __init kmalloc_pagealloc_invalid_free(void)
    2. {
    3. char *ptr;
    4. size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
    5. pr_info("kmalloc pagealloc allocation: invalid-free\n");
    6. ptr = kmalloc(size, GFP_KERNEL);
    7. if (!ptr) {
    8. pr_err("Allocation failed\n");
    9. return;
    10. }
    11. kfree(ptr + 1);
    12. }

    4、实验输出

    • 内存越界访问Redzone overwritten、Object padding overwritten
    • 重复释放Object already free
    • 访问已释放内存为Posion overwritten
    1. # insmod slub3.ko
    2. [ 997.342740] :access free memory
    3. benshushu:slub_test_3# [ 997.436270] =============================================================================
    4. [ 997.437705] BUG kmalloc-128 (Tainted: G B OE ): Redzone overwritten
    5. [ 997.438153] -----------------------------------------------------------------------------
    6. [ 997.438153]
    7. [ 997.440009] INFO: 0x000000001c0937b9-0x0000000065391b57. First byte 0x55 instead of 0xcc
    8. [ 997.442519] INFO: Allocated in create_slub_error+0x30/0x94 [slub3] age=63120 cpu=1 pid=1602

    有的时候需要使用slabinfo -v才能输出错误

    1. slub_test# ./slabinfo -v
    2. [ 1112.602383] =============================================================================
    3. [ 1112.602945] BUG kmalloc-128 (Tainted: G B OE ): Redzone overwritten
    4. [ 1112.603254] -----------------------------------------------------------------------------
    5. [ 1112.603254]
    6. [ 1112.603773] INFO: 0x00000000583020f8-0x00000000583020f8. First byte 0x55 instead of 0xcc
    7. [ 1112.604214] INFO: Allocated in create_slub_error+0x34/0xdc [slub4] age=4071 cpu=0 pid=1687
    8. [ 1112.604661] __slab_alloc+0x64/0xb0
    9. [ 1112.604822] __kmalloc+0x558/0xee4
    10. [ 1112.605002] create_slub_error+0x34/0xdc [slub4]

    二、KASAN 内存检测

    KASAN(Kernal Address SANtizer)在Linux4.0版本中合并到官方的内核。是动态检测内存错误的工具。可以检查内存越界和使用已经释放的内存等问题。KASAN比kmemcheck工具检测速度快。

    内核配置

    CONFIG_HAVE_ARCH_KASAN=y

    CONFIG_KASAN=y

    CONFIG_KASAN_OUTLINE=y

    CONFIG_KASAN_INLINE=y

    CONFIG_TEST_KASAN=m //编译test_kasan.ko测试模块

    内核源码中的测试程序/lib/test_ksacn.c 

    1. static int __init kmalloc_tests_init(void)
    2. {
    3. /*
    4. * Temporarily enable multi-shot mode. Otherwise, we'd only get a
    5. * report for the first case.
    6. */
    7. bool multishot = kasan_save_enable_multi_shot();
    8. kmalloc_oob_right();
    9. kmalloc_oob_left();
    10. kmalloc_node_oob_right();
    11. #ifdef CONFIG_SLUB
    12. kmalloc_pagealloc_oob_right();
    13. kmalloc_pagealloc_uaf();
    14. kmalloc_pagealloc_invalid_free();
    15. #endif
    16. kmalloc_large_oob_right();
    17. kmalloc_oob_krealloc_more();
    18. kmalloc_oob_krealloc_less();
    19. kmalloc_oob_16();
    20. kmalloc_oob_in_memset();
    21. kmalloc_oob_memset_2();
    22. kmalloc_oob_memset_4();
    23. kmalloc_oob_memset_8();
    24. kmalloc_oob_memset_16();
    25. kmalloc_uaf();
    26. kmalloc_uaf_memset();
    27. kmalloc_uaf2();
    28. kmem_cache_oob();
    29. memcg_accounted_kmem_cache();
    30. kasan_stack_oob();
    31. kasan_global_oob();
    32. kasan_alloca_oob_left();
    33. kasan_alloca_oob_right();
    34. ksize_unpoisons_memory();
    35. copy_user_test();
    36. use_after_scope_test();
    37. kmem_cache_double_free();
    38. kmem_cache_invalid_free();
    39. kasan_memchr();
    40. kasan_memcmp();
    41. kasan_strings();
    42. kasan_restore_multi_shot(multishot);
    43. return -EAGAIN;
    44. }

    从上选择其中两个解析

    1、数组越界

    1. static noinline void __init kmalloc_oob_right(void)
    2. {
    3. char *ptr;
    4. size_t size = 123;
    5. pr_info("out-of-bounds to right\n");
    6. ptr = kmalloc(size, GFP_KERNEL);
    7. if (!ptr) {
    8. pr_err("Allocation failed\n");
    9. return;
    10. }
    11. ptr[size] = 'x';
    12. kfree(ptr);
    13. }

    2、栈的越界访问

    1. static noinline void __init kasan_stack_oob(void)
    2. {
    3. char stack_array[10];
    4. volatile int i = 0;
    5. char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
    6. pr_info("out-of-bounds on stack\n");
    7. *(volatile char *)p;
    8. }

    3、实验输出

    1)在内核中同时开启ksasn与slub的检测的检测,内存错误优先被kasan检测到,如下所示:

    1. slub_test_1# insmod slub1.ko
    2. [ 744.870946] slub1: loading out-of-tree module taints kernel.
    3. [ 744.886482] slub1: module verification failed: signature and/or required key missing - tainting kernel
    4. [ 744.958499] module init
    5. [ 744.959688] ==================================================================
    6. [ 744.962726] BUG: KASAN: slab-out-of-bounds in create_slub_error+0x6c/0x78 [slub1]
    7. [ 744.963528] Write of size 130 at addr ffff800019ea1200 by task insmod/1602
    8. [ 744.964141]
    1. slub_test_2# insmod slub2.ko
    2. [ 874.303487] my module init
    3. [ 874.304834] ben:double free test
    4. [ 874.305266] ==================================================================
    5. [ 874.306672] BUG: KASAN: double-free or invalid-free in create_slub_error+0x98/0xa4 [slub2]
    6. [ 874.307269]

    2)将test_kasan.ko加载后,所有的打印输出有所缩减,把检测到的提示错误保留

    slab-out-of-bounds, use-after-free,double-free or invalid-free,alloca-out-of-bounds

    1. insmod test_kasan.ko
    2. [ 96.717377] test_kasan: module verification failed: signature and/or required key missing - tainting kernel
    3. [ 96.788908] kasan test: kmalloc_oob_right out-of-bounds to right
    4. [ 96.790675] ==================================================================
    5. [ 96.794556] BUG: KASAN: slab-out-of-bounds in kmalloc_oob_right+0xc8/0xe4 [test_kasan]
    6. [ 96.796122] Write of size 1 at addr ffff80001cebcffb by task insmod/569
    7. [ 96.796619]
    8. [ 96.797727] CPU: 0 PID: 569 Comm: insmod Kdump: loaded Tainted: G E 5.0.0+ #2
    9. [ 96.798290] Hardware name: linux,dummy-virt (DT)
    10. [ 96.799205] Call trace:
    11. [ 96.800667] dump_backtrace+0x0/0x97c
    12. [ 96.801030] show_stack+0x24/0x30
    13. [ 96.801283] __dump_stack+0x20/0x2c
    14. [ 96.801673] dump_stack+0x318/0x690
    15. [ 96.802003] print_address_description+0x38/0x42c
    16. [ 96.802371] kasan_report+0x194/0x1e8
    17. [ 96.802727] __asan_report_store1_noabort+0x30/0x3c
    18. [ 96.803462] kmalloc_oob_right+0xc8/0xe4 [test_kasan]
    19. [ 96.805821] kmalloc_tests_init+0x14/0x640 [test_kasan]
    20. [ 96.806516] do_one_initcall+0xc8c/0x1ca4
    21. [ 96.806802] do_init_module+0x1d8/0x784
    22. [ 96.807130] load_module+0x1210/0x1920
    23. [ 96.808033] __se_sys_finit_module+0x1c8/0x224
    24. [ 96.808527] __arm64_sys_finit_module+0xbc/0xc8
    25. [ 96.809137] __invoke_syscall+0x24/0x2c
    26. [ 96.809389] invoke_syscall+0xcc/0x128
    27. [ 96.809557] el0_svc_common+0x1c4/0x2d0
    28. [ 96.809746] el0_svc_handler+0x91c/0x960
    29. [ 96.809946] el0_svc+0x8/0xc
    30. [ 96.810422]
    31. [ 96.810770] Allocated by task 569:
    32. [ 96.811245] __kasan_kmalloc+0x148/0x290
    33. [ 96.811886] kasan_kmalloc+0x30/0x38
    34. [ 96.812672] __kmalloc+0xea4/0xee4
    35. [ 96.813049] kmalloc_oob_right+0x48/0xe4 [test_kasan]
    36. [ 96.813561] kmalloc_tests_init+0x14/0x640 [test_kasan]
    37. [ 96.814003] do_one_initcall+0xc8c/0x1ca4
    38. [ 96.814363] do_init_module+0x1d8/0x784
    39. [ 96.814589] load_module+0x1210/0x1920
    40. [ 96.814829] __se_sys_finit_module+0x1c8/0x224
    41. [ 96.815093] __arm64_sys_finit_module+0xbc/0xc8
    42. [ 96.816164] __invoke_syscall+0x24/0x2c
    43. [ 96.816581] invoke_syscall+0xcc/0x128
    44. [ 96.817567] el0_svc_common+0x1c4/0x2d0
    45. [ 96.817836] el0_svc_handler+0x91c/0x960
    46. [ 96.818363] el0_svc+0x8/0xc
    47. [ 96.818832]
    48. [ 96.819123] Freed by task 0:
    49. [ 96.820128] (stack is not available)
    50. [ 96.820582]
    51. [ 96.820839] The buggy address belongs to the object at ffff80001cebcf80
    52. [ 96.820839] which belongs to the cache kmalloc-128 of size 128
    53. [ 96.821736] The buggy address is located 123 bytes inside of
    54. [ 96.821736] 128-byte region [ffff80001cebcf80, ffff80001cebd000)
    55. [ 96.823027] The buggy address belongs to the page:
    56. [ 96.827418] page:ffff7e000073af00 count:1 mapcount:0 mapping:ffff800021c0c400 index:0xffff80001cebed80 compound_mapcount: 0
    57. [ 96.830608] flags: 0xffff00000010200(slab|head)
    58. [ 96.831566] raw: 0ffff00000010200 ffff7e0000752f08 ffff800021c03c90 ffff800021c0c400
    59. [ 96.833056] raw: ffff80001cebed80 0000000000190012 00000001ffffffff 0000000000000000
    60. [ 96.833864] page dumped because: kasan: bad access detected
    61. [ 96.834505]
    62. [ 96.834866] Memory state around the buggy address:
    63. [ 96.836134] ffff80001cebce80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    64. [ 96.837813] ffff80001cebcf00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    65. [ 96.839023] >ffff80001cebcf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
    66. [ 96.840070] ^
    67. [ 96.840943] ffff80001cebd000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    68. [ 96.841405] ffff80001cebd080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    69. [ 96.841988] ==================================================================
    70. [ 96.842481] Disabling lock debugging due to kernel taint
    71. [ 96.844009] kasan test: kmalloc_oob_left out-of-bounds to left
    72. [ 96.845114] ==================================================================
    73. [ 96.849223] BUG: KASAN: slab-out-of-bounds in kmalloc_oob_left+0xc0/0x134 [test_kasan]
    74. [ 96.850317] Read of size 1 at addr ffff80001cebed7f by task insmod/569
    75. [ 96.895962] ==================================================================
    76. [ 96.898866] kasan test: kmalloc_node_oob_right kmalloc_node(): out-of-bounds to right
    77. [ 96.902638] ==================================================================
    78. [ 96.905146] BUG: KASAN: slab-out-of-bounds in kmalloc_node_oob_right+0xd0/0xe8 [test_kasan]
    79. [ 96.906247] Write of size 1 at addr ffff800015826a80 by task insmod/569
    80. [ 96.907658]
    81. [ 96.967853] ==================================================================
    82. [ 96.970577] kasan test: kmalloc_pagealloc_oob_right kmalloc pagealloc allocation: out-of-bounds to right
    83. [ 96.973391] ==================================================================
    84. [ 96.974297] BUG: KASAN: slab-out-of-bounds in kmalloc_pagealloc_oob_right+0xc8/0xe0 [test_kasan]
    85. [ 96.976085] Write of size 1 at addr ffff80001c0be00a by task insmod/569
    86. [ 97.009774] ==================================================================
    87. [ 97.013784] kasan test: kmalloc_pagealloc_uaf kmalloc pagealloc allocation: use-after-free
    88. [ 97.015457] ==================================================================
    89. [ 97.016937] BUG: KASAN: use-after-free in kmalloc_pagealloc_uaf+0xc0/0xd0 [test_kasan]
    90. [ 97.018264] Write of size 1 at addr ffff80001c0bc000 by task insmod/569
    91. [ 97.021236]
    92. [ 97.058048] ==================================================================
    93. [ 97.062012] kasan test: kmalloc_pagealloc_invalid_free kmalloc pagealloc allocation: invalid-free
    94. [ 97.063042] ==================================================================
    95. [ 97.064403] BUG: KASAN: double-free or invalid-free in kmalloc_pagealloc_invalid_free+0x78/0x80 [test_kasan]
    96. [ 97.563543] ==================================================================
    97. [ 97.565871] kasan test: kmalloc_oob_memset_16 out-of-bounds in memset16
    98. [ 97.566822] ==================================================================
    99. [ 97.567581] BUG: KASAN: slab-out-of-bounds in kmalloc_oob_memset_16+0x80/0x90 [test_kasan]
    100. [ 97.568841] Write of size 16 at addr ffff80001d4bc081 by task insmod/569
    101. [ 97.618222] ==================================================================
    102. [ 97.620924] kasan test: kmalloc_uaf use-after-free
    103. [ 97.622887] ==================================================================
    104. [ 97.624507] BUG: KASAN: use-after-free in kmalloc_uaf+0xcc/0xe0 [test_kasan]
    105. [ 97.626212] Write of size 1 at addr ffff80001d4bc588 by task insmod/569
    106. [ 97.627438]
    107. [ 97.672285] ==================================================================
    108. [ 97.673872] kasan test: kmalloc_uaf_memset use-after-free in memset
    109. [ 97.674501] ==================================================================
    110. [ 97.675046] BUG: KASAN: use-after-free in kmalloc_uaf_memset+0x84/0x8c [test_kasan]
    111. [ 97.675620] Write of size 33 at addr ffff80001d4bf500 by task insmod/569
    112. [ 97.676672] ==================================================================
    113. [ 98.023758] kasan test: memcg_accounted_kmem_cache allocate memcg accounted object
    114. [ 98.674484] kasan test: kasan_stack_oob out-of-bounds on stack
    115. [ 98.675223] ==================================================================
    116. [ 98.678286] BUG: KASAN: stack-out-of-bounds in kasan_stack_oob+0xf8/0x144 [test_kasan]
    117. [ 98.679094] Read of size 1 at addr ffff8000197df39a by task insmod/569
    118. [ 98.679522] [ 98.735804]
    119. [ 98.867912] ==================================================================
    120. [ 98.870386] kasan test: copy_user_test out-of-bounds in copy_from_user()
    121. [ 98.871485] ==================================================================
    122. [ 98.872960] BUG: KASAN: slab-out-of-bounds in copy_user_test+0x28c/0x8d8 [test_kasan]
    123. [ 98.874518] Write of size 11 at addr ffff80001c007000 by task insmod/569
    124. [ 98.875381][ 98.932274] ==================================================================
    125. [ 98.934343] kasan test: copy_user_test out-of-bounds in copy_to_user()
    126. [ 98.935494] ==================================================================
    127. [ 98.936524] BUG: KASAN: slab-out-of-bounds in copy_user_test+0x500/0x8d8 [test_kasan]
    128. [ 98.937066] Read of size 11 at addr ffff80001c007000 by task insmod/569
    129. [ 98.938636][ 98.993046]
    130. [ 99.049702] ==================================================================
    131. [ 99.051988] kasan test: copy_user_test out-of-bounds in __copy_to_user()
    132. [ 99.052711] ==================================================================
    133. [ 99.054365] BUG: KASAN: slab-out-of-bounds in copy_user_test+0x67c/0x8d8 [test_kasan]
    134. [ 99.056035] Read of size 11 at addr ffff80001c007000 by task insmod/569
    135. [ 99.057768]
    136. [ 99.297345] ==================================================================
    137. [ 99.303983] kasan test: use_after_scope_test use-after-scope on int
    138. [ 99.305426] kasan test: use_after_scope_test use-after-scope on array
    139. [ 99.319414] kasan test: kmem_cache_double_free double-free on heap object
    140. [ 99.321611] ==================================================================
    141. [ 99.322758] BUG: KASAN: double-free or invalid-free in kmem_cache_double_free+0xc4/0xd4 [test_kasan]
    142. [ 99.324030]
    143. [ 99.718299] ==================================================================
    144. [ 99.719678] kasan test: kasan_memcmp out-of-bounds in memcmp
    145. [ 99.721512] ==================================================================
    146. [ 99.722675] BUG: KASAN: slab-out-of-bounds in memcmp+0x7c/0x138
    147. [ 99.723387] Read of size 1 at addr ffff80001d62b798 by task insmod/569
    148. [ 99.723956]
    149. [ 99.808130] ==================================================================
    150. [ 99.810907] kasan test: kasan_strings use-after-free in strchr
    151. [ 99.812133] ==================================================================
    152. [ 99.812909] BUG: KASAN: use-after-free in strchr+0xd0/0xf4
    153. [ 99.813602] Read of size 1 at addr ffff80001d629c10 by task insmod/569
    154. [ 99.814186]
    155. [ 100.231048] ==================================================================
    156. [ 100.232472] kasan test: kasan_strings use-after-free in strncmp
    157. [ 100.235615] ==================================================================
    158. [ 100.241922] BUG: KASAN: use-after-free in strncmp+0x74/0x148
    159. [ 100.243947] Read of size 1 at addr ffff80001d629c10 by task insmod/569
    160. [ 100.244851]
    161. [ 100.293083] ffff80001d629c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    162. [ 100.293951] ffff80001d629d00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc

  • 相关阅读:
    “深入理解机器学习性能评估指标:TP、TN、FP、FN、精确率、召回率、准确率、F1-score和mAP”
    AGV小车、机械臂协同作业实战06-任务分配算法(图解蚁群算法)代码示例java
    C#、C++、Java、Python 选择哪个好?
    494. 目标和
    集合转json json转集合
    磷酸铁锂电池回收浸出液除铝
    elastic-job源码分析
    使用gitpull项目的时候第一次输错密码之后报错Authentication failed for “http://xxxxxx“
    算法学习(一)—— 如何看待数据结构与算法
    Java - Object#finalize在JDK9中被标记废弃了!
  • 原文地址:https://blog.csdn.net/WANGYONGZIXUE/article/details/126922861