本文研究了内核编译选项 CONFIG_SLAB_MERGE_DEFAULTkmem_cache 分配的影响.

以及开启该配置的时候, slab UAF 的一种利用方案 (方案来源, 本文内容基于 Linux-5.10.90).

阅读前, 需要对 slab/slub, buddy system 有基本的了解.

Keywords: slab/slub | CONFIG_SLAB_MERGE_DEFAULT | Linux kernel exploit

Part. 1

创建 struct kmem_cache 的时候,有两种情况:

kmem_cache_create(..)
	kmem_cache_create_usercopy(..)
        if (!usersize) // usersize == 0
            s = __kmem_cache_alias(name, size, align, flags, ctor); // s 为 NULL 才会创建新的 slab
        if (s)
            goto out_unlock;
		create_cache()

// 进入 `__kmem_cache_alias` 看看
__kmem_cache_alias(..)
    // 检查 CONFIG_SLAB_MERGE_DEFAULT 配置;
    // 如果开启了,则通过 sysfs_slab_alias 找到已经创建的相同大小的 slab 作为替代
	s = find_mergeable(..)
		list_for_each_entry_reverse(s, &slab_caches, list) {
			if (slab_unmergeable(s)) // slab_nomerge 为 true 时 return 1;
                continue;
             ...
             return s;
        }
        return NULL; // slab_nomerge 为 true 的时候返回 NULL
    if(s)
       ...
	   sysfs_slab_alias(..)
    return s;

// CONFIG_SLAB_MERGE_DEFAULT=y -> slab_nomerge == false
// CONFIG_SLAB_MERGE_DEFAULT=n -> slab_nomerge == true
static bool slab_nomerge = !IS_ENABLED(CONFIG_SLAB_MERGE_DEFAULT);

// <https://cateee.net/lkddb/web-lkddb/SLAB_MERGE_DEFAULT.html>
// CONFIG_SLAB_MERGE_DEFAULT: Allow slab caches to be merged

// For reduced kernel memory fragmentation, slab caches can be merged
// when they share the same size and other characteristics.
// This carries a risk of kernel heap overflows being able to
// overwrite objects from merged caches (and more easily control cache layout),
// which makes such heap attacks easier to exploit by attackers.

Part. 2

测试 CONFIG_SLAB_MERGE_DEFAULT 的影响

Host 主机(开启了配置):

└─[$] uname -r
5.15.0-52-generic

└─[$] cat /boot/config-$(uname -r) |grep CONFIG_SLAB_MERGE_DEFAULT
CONFIG_SLAB_MERGE_DEFAULT=y

VM (未开启配置):