• 用slub_track调试use after free问题


    死机重启问题中,有部分是访问了已释放的内存导致,这就是典型的userafter free问题.

    打开CONFIG_SLUB_DEBUG和CONFIG_SLUB_DEBUG_ON宏开关后,系统就可以监测内存的释放与分配调用栈.

    1. slab 内存布局
    slub的内存管理原理这里就不在详述.直接给出slabobject对象的内存布局,object内存包含下面四个部分:

    object_size +Redzone + Freepointer +2*track+pading

    object_size :待分配内存的大小,alloc时为0x5a,free后为0x6b,但是最后一个Byte为0xa5表示object的结束,之后的数据都为metadata.

    Redzone : 标记区.alloc填充0xcc,free后填充0bb

    Freepointer :指向下一个空闲的object

    2个structtrack结构,用于跟踪内存的分配与释放栈

    pading :填充区,为了内存对齐,填充为0x5a

    典型的object内存布局

    slub info

    2. 相关变量
    kmem_cache->inuse= object_size + Redzone

    kmem_cache->offset= inuse or =0

    kmem_cache->size= object_size +Redzone+Freepointer+2*track+pading

    3. 查找track信息
    当系统出现KE时,用gdb调试打印内存,发现访问的内存全变成了0x6b,则可以怀疑是userafter free。

    分析下述案例:

    crash_arm64> musb_qh 0xffffffc0640ebc80 -x
    struct musb_qh {
      hep = 0x6b6b6b6b6b6b6b6b,
      dev = 0x6b6b6b6b6b6b6b6b,

    这个地址0xffffffc0640ebc80出问题了,下面看是slub分配的,所以可以用slub track分析了。

    crash_arm64> kmem 0xffffffc0640ebc80

    CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
    ffffffc079007980 kmalloc-256              256       5184      5208    248    16k
      SLAB              MEMORY            NODE  TOTAL  ALLOCATED  FREE
      ffffffbdc1903a00  ffffffc0640e8000     0     21         19     2
      FREE / [ALLOCATED]
      [ffffffc0640ebc00]


          PAGE               PHYSICAL      MAPPING       INDEX CNT FLAGS
    ffffffbdc1903ac0         e40eb000                0        1  0 0

    struct kmem_cache {
      cpu_slab = 0xffffff8008e6bc30,
      flags = 0x80010d00,

    crash_arm64> p kmalloc_caches  -x
    kmalloc_caches = $1 =

     {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffc079004380, 0xffffffc079007980, 0xffffffc079004680, 0xffffffc079007680, 0xffffffc079004980, 0xffffffc079007380, 0xffffffc079004c80}

    struct kmem_cache {
      cpu_slab = 0xffffff8008e6bc30,
      flags = 0x80010d00,                //这个flag 表明当前debug等级信息,
      min_partial = 0x5,
      size = 0x300,
      object_size = 0x100,
      offset = 0x108,
      cpu_partial = 0x0,
      oo = {
        x = 0x20015
      },
      max = {
        x = 0x20015
      },
      min = {
        x = 0x5
      },
      allocflags = 0x4000,
      refcount = 0x1,
      ctor = 0x0,
      inuse = 0x108,
      align = 0x80,
      reserved = 0x0,

      name = 0xffffff8008c8ef4f "kmalloc-256",

    /*
     * Flags to pass to kmem_cache_create().
     * The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set.
     */
    #define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */
    #define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
    #define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
    #define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
    #define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
    #define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
    #define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */

    这里slub track 就是需要SLAB_STORE_USER 这个flag,满足条件。  此slub 肯定包含了alloc和free的track。

    分析内存里object的内存布局,找到这个track地址:

    ffffffc0640ebbd0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebbe0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebbf0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebc00:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc10:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc20:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc30:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc40:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc50:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc60:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc70:  bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb   ................
    ffffffc0640ebc80:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebc90:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebca0:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebcb0:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebcc0:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebcd0:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebce0:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebcf0:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd00:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd10:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd20:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd30:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd40:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd50:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd60:  6b6b6b6b6b6b6b6b 6b6b6b6b6b6b6b6b   kkkkkkkkkkkkkkkk
    ffffffc0640ebd70:  6b6b6b6b6b6b6b6b a56b6b6b6b6b6b6b   kkkkkkkkkkkkkkk.
    ffffffc0640ebd80:  bbbbbbbbbbbbbbbb ffffffc0640eb680   ...........d....                 //used  after free的slub好像一般都有这些信息。
    ffffffc0640ebd90:  ffffff80085e3724 ffffff80081cb79c   $7^.............
    ffffffc0640ebda0:  ffffff80081cbe6c ffffff80081cbf58   l.......X.......
    ffffffc0640ebdb0:  ffffff80081cc27c ffffff80085e3724   |.......$7^.....
    ffffffc0640ebdc0:  ffffff800859d374 ffffff800859e7c4   t.Y.......Y.....
    ffffffc0640ebdd0:  ffffff80087a37f8 ffffff80087ac584   .7z.......z.....
    ffffffc0640ebde0:  ffffff80087ae554 ffffff80087932cc   T.z......2y.....
    ffffffc0640ebdf0:  ffffff8008792d3c ffffff8008795bd8   <-y......[y.....
    ffffffc0640ebe00:  ffffff8008796778 ffffff8008797200   xgy......ry.....
    ffffffc0640ebe10:  ffffff800822ee1c 000003a200000003   ..".............
    ffffffc0640ebe20:  000000010028dde4 ffffff80085e3250   ..(.....P2^.....
    ffffffc0640ebe30:  ffffff80081cd008 ffffff80081cd18c   ................
    ffffffc0640ebe40:  ffffff80081cdec0 ffffff80085e3250   ........P2^.....
    ffffffc0640ebe50:  ffffff800859d530 ffffff800859e27c   0.Y.....|.Y.....
    ffffffc0640ebe60:  ffffff80087a29e4 ffffff80087a39f8   .)z......9z.....
    ffffffc0640ebe70:  ffffff80087ad5d0 ffffff80087ad730   ..z.....0.z.....
    ffffffc0640ebe80:  ffffff8008792fb8 ffffff8008792d3c   ./y.....<-y.....
    ffffffc0640ebe90:  ffffff8008792dc8 ffffff8008792ec4   .-y.......y.....
    ffffffc0640ebea0:  ffffff8008794d70 ffffff8008794dbc   pMy......My.....
    ffffffc0640ebeb0:  00000dfc00000003 000000010028df1a   ..........(.....            //大致一看cpu和pid就是他了
    ffffffc0640ebec0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebed0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebee0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebef0:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf00:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf10:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf20:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf30:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf40:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf50:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf60:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf70:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ
    ffffffc0640ebf80:  5a5a5a5a5a5a5a5a 5a5a5a5a5a5a5a5a   ZZZZZZZZZZZZZZZZ

    从内存中查找关键字0xa5,0xbb,再参考slabobject的内存布局,很容易找到alloctrack和freetrack的地址,再用gdb打印出内存

    crash_arm64> track -ox
    struct track {
       [0x0] unsigned long addr;
       [0x8] unsigned long addrs[16];
      [0x88] int cpu;
      [0x8c] int pid;
      [0x90] unsigned long when;
    }
    SIZE: 0x98

    crash_arm64> track ffffffc0640ebe28  -x
    struct track {
      addr = 0xffffff80085e3250,
      addrs = {0xffffff80081cd008, 0xffffff80081cd18c, 0xffffff80081cdec0, 0xffffff80085e3250, 0xffffff800859d530, 0xffffff800859e27c, 0xffffff80087a29e4, 0xffffff80087a39f8, 0xffffff80087ad5d0, 0xffffff80087ad730, 0xffffff8008792fb8, 0xffffff8008792d3c, 0xffffff8008792dc8, 0xffffff8008792ec4, 0xffffff8008794d70, 0xffffff8008794dbc},
      cpu = 0x3,
      pid = 0xdfc,
      when = 0x10028df1a
    }

    dis这些地址就知道是谁释放的了。也可以看alloc的调用栈。
    ————————————————
    版权声明:本文为CSDN博主「chenpuo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/chenpuo/article/details/80885789

  • 相关阅读:
    递归函数及Java范例
    笔记本的硬盘坏了
    “References to generic type List should be parameterized”
    配置管理软件(configuration management software)介绍
    WinCE文件目录定制及内存调整
    使用Silverlight for Embedded开发绚丽的界面(3)
    wince国际化语言支持
    Eclipse IDE for Java EE Developers 与Eclipse Classic 区别
    WinCE Heartbeat Message的实现
    使用Silverlight for Embedded开发绚丽的界面(2)
  • 原文地址:https://www.cnblogs.com/smilingsusu/p/14479938.html
Copyright © 2020-2023  润新知