首页
社区
课程
招聘
[求助][已解决] linux kernel CONFIG_SLAB_FREELIST_HARDENED 加固后 cookie 泄漏问题
2024-5-9 10:34 884

[求助][已解决] linux kernel CONFIG_SLAB_FREELIST_HARDENED 加固后 cookie 泄漏问题

2024-5-9 10:34
884

环境配置:

  • 内核版本 v5.14.16
  • 设置 CONFIG_SLAB_FREELIST_HARDENEDCONFIG_SLAB_FREELIST_RANDOM 编译选项

问题描述:
目前存在 kmalloc-128 空闲链表:

  • freelist -> A -> B -> C -> D -> ......
  • next 指针存放在 object + 0x40 处,即 offset = 0x40

A 的地址和部分内容如下:

1
2
3
4
5
0xffff888005ede200:     0x0000000000000000      0x0000000000000000
0xffff888005ede210:     0x0000000000000000      0x0000000000000000
0xffff888005ede220:     0x0000000000000000      0x0000000000000000
0xffff888005ede230:     0x0000000000000000      0x0000000000000000
0xffff888005ede240:     0x1d947f537ffab314      0x0000000000000000

B 的地址和部分内容如下:

1
2
3
4
5
0xffff888005edee00:     0x0000000000000000      0x0000000000000000
0xffff888005edee10:     0x0000000000000000      0x0000000000000000
0xffff888005edee20:     0x0000000000000000      0x0000000000000000
0xffff888005edee30:     0x0000000000000000      0x0000000000000000
0xffff888005edee40:     0x1d987f537ffaba14      0x0000000000000000

C 的地址和部分内容如下:

1
2
3
4
5
0xffff888005ede700:     0x0000000000000000      0x0000000000000000
0xffff888005ede710:     0x0000000000000000      0x0000000000000000
0xffff888005ede720:     0x0000000000000000      0x0000000000000000
0xffff888005ede730:     0x0000000000000000      0x0000000000000000
0xffff888005ede740:     0x1d917f537ffabb14      0x0000000000000000

D 的地址和部分内容如下:

1
2
3
4
5
0xffff888005ede600:     0x0000000000000000      0x0000000000000000
0xffff888005ede610:     0x0000000000000000      0x0000000000000000
0xffff888005ede620:     0x0000000000000000      0x0000000000000000
0xffff888005ede630:     0x0000000000000000      0x0000000000000000
0xffff888005ede640:     0x1d907f537ffab294      0x0000000000000000

next 指针的加密方式为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,
                 unsigned long ptr_addr)
{
#ifdef CONFIG_SLAB_FREELIST_HARDENED
    /*
     * When CONFIG_KASAN_SW/HW_TAGS is enabled, ptr_addr might be tagged.
     * Normally, this doesn't cause any issues, as both set_freepointer()
     * and get_freepointer() are called with a pointer with the same tag.
     * However, there are some issues with CONFIG_SLUB_DEBUG code. For
     * example, when __free_slub() iterates over objects in a cache, it
     * passes untagged pointers to check_object(). check_object() in turns
     * calls get_freepointer() with an untagged pointer, which causes the
     * freepointer to be restored incorrectly.
     */
    return (void *)((unsigned long)ptr ^ s->random ^
            swab((unsigned long)kasan_reset_tag((void *)ptr_addr)));
#else
    return ptr;
#endif
}

但是这里调试发现一个问题:ptrptr_addr 的高两字节都是 0xffff,所以最后异或出来 ptr ^ ptr_addr ^ cookie 的高两字节应该就是 cookie 的高两字节,也就是说每个 next 指针的高两字节都是相同的,但是这里 Anext = 0x1d947f537ffab314 高两字节为 0x1d94Bnext = 0x1d987f537ffaba14 高两字节为 0x1d98,这两者并不相同

不仅如此,对于 kmalloc-128,在我的环境下,其同一个 slab cache 中高 52 bit 是相同的,所以加密后的指针高 52 bit 应该也是相同的,其就是 cookie 的高 52 bit,但是这里异或出来发现高 52 bit 并非完全相同(大部分是相同的)

自己的探索:
我按照 ptr ^ ptr_addr ^ cookie 的方式去恢复 cookie,发现同一个 slab cache 利用不同堆块恢复出来的居然不同?按照源码来看,这个 random(cookie) 是针对 slab cache 的,所以这里选择不同堆块恢复出来的应该是一样的才对

笔者的问题:
请问在设置了 CONFIG_SLAB_FREELIST_HARDENED 编译选项下 next 指针的加密方式到底是什么?为什么按照源码中的加密逻辑去推理调试却得到不同的 cookie 并且高两字节居然不相同
========================= 后续 ===========================
自己解决了

又审计了一下源码,发现源码中对 ptr_addr 进行了一个 swab 操作很奇怪(之前眼睛瞎了,自动忽视了),跟进去发现其定义如下:主要看 64位的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * __swab64 - return a byteswapped 64-bit value
 * @x: value to byteswap
 */
#ifdef __HAVE_BUILTIN_BSWAP64__
#define __swab64(x) (__u64)__builtin_bswap64((__u64)(x))
#else
#define __swab64(x)             \
    (__builtin_constant_p((__u64)(x)) ? \
    ___constant_swab64(x) :         \
    __fswab64(x))
#endif
 
static __always_inline unsigned long __swab(const unsigned long y)
{
#if __BITS_PER_LONG == 64
    return __swab64(y);
#else /* __BITS_PER_LONG == 32 */
    return __swab32(y);
#endif
}

可以看到会进行字节上的交换....感觉这里应该就是防止堆块地址大量字节相同导致泄漏 cookie 而加的保护,也就是上面说的异或出来的值高 52 bit 就是 cookie


[培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

最后于 2024-5-9 13:08 被XiaozaYa编辑 ,原因:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回