Kernel总结
一些好用的结构体以及衍生出来的攻击方法
user_key_payload
限制是只能分配最多200个最长20000字节
分配
分配一: size >= 0x18(GFP_kernel)
__x64_sys_add_key->kmalloc
plen可以控制,同时_payload为用户传进来的变量
但是需要注意的是后面会将其free掉,所以和send_msg类似
|
|
释放
poll_list
msg_msg
pt_regs
setxattr
shm_file_data
pipe_buffer
dirty_pipe
pipe_prime
dirty_cred
skb_buffer (>= 512)
pgv 与页级内存页分配
USMA
Cross cache attack
seq_operations (kmalloc-32 | GFP_KERNEL_ACCOUNT)
SLUB分配器
为什么需要内核分配器
操作系统虚拟内存中用于内存管理的最小数据单位是页面,大多数体系结构的传统大小为 4KB(0x1000)。由于每次进程请求某些东西时分配 4KB 内存是不切实际的,即使小到几十个字节,也需要一种中间机制来微管理页面的内容。
虽然在用户空间中这是由 malloc 系列执行的,但内核需要一个不同的系统,与系统本身更紧密地集成,可以在中断上下文中工作,符合 DMA 限制.
为此,内核实现了一个管理页面分配、碎片和重新分配的分配器。它基本上作为零售供应商工作:它获取大库存(4KB 页),然后在模块需要时将它们分成小块进行交易。这个分配器的基本版本称为 SLAB。
SLAB
当内核子系统请求(或释放)对象的数据时,主要开销在于初始化(或销毁)它,而不是为其分配内存。如果有一组频繁分配和释放的公共内核对象,将它们放在一个快速可达的地方可以使整个过程更有效率。
这就是 SLAB 的原理:分配器会跟踪这些称为缓存的块,以便在收到为某种类型的数据对象分配内存的请求时,它可以立即用已经分配的槽满足请求。在此上下文中,slab 是内存中包含预分配内存块的一个或多个连续页面。
Slab 可能存在于以下状态之一:
- empty:slab 中的所有对象都是空闲的
- partial: slab 由自由对象和被占用对象组成
- full:slab中的所有对象都为占用状态
当然,分配器的目的是尽可能快地处理请求,因此跟踪部分 slab 是至关重要的。这是通过缓存完成的,每个对象类型有一个缓存。
SLUB
SLUB 是我们感兴趣的 SLAB 变体,旨在实现更好的调试、更少的碎片和更好的性能。它继续采用基于 slab 的基本模型,但修复了 SLAB 设计中的几个缺陷,特别是围绕具有大量处理器的系统。自 2008 年 2.6.23 以来,它已在主线 Linux 内核中被默认采用。
让我们看看 SLUB 的实现细节,通过常见用例场景的示例。
首先,slab 中的对象在内存中是连续存储的,但它们通过链表在逻辑上相互连接:这样分配器总能找到下一个空闲对象,而无需关心已经使用的数据。
Fresh slab
Partial slab
在 SLUB 中,与 SLAB 不同,指向下一个空闲对象的指针直接存储在对象本身内部,不需要额外的元数据空间并实现 100% 的 slab 利用率。
其中 objsize 是对象本身的大小,offset 是下一个指针之前的空间量,size 是总大小。
所有这些信息以及更多信息都存储在 off-slab 中,存储在跟踪此类元数据的数据结构中:kmem_cache。
每种对象类型只有一个 kmem_cache,并且该对象的所有 slab 都由同一个 kmem_cache 管理。这些结构通过双链表相互链接,可以通过导出的 slab_caches 变量从内核中的任何地方访问。
在 kmem_cache 内部,存储了两种指针以跟踪 slab:一个 kmem_cache_node 数组和一个指向 kmem_cache_cpu 的指针。后者管理 active slab:它只有一个,并且与当前 cpu 相关(SMD 处理器可以有不同的 active 缓存)。下一次分配的结果将始终从active slab 返回,由 freelist 字段指向。另一方面,kmem_cache_node 跟踪不活动的部分和完整的 slab:它们在free的情况下被访问,或者当partial slab 被填满并且另一个部分需要取代它的位置时。
例子
Standard allocation
分配器从 kmem_cache 导航到 kmem_cache_cpu 并访问空闲列表以找到第一个空闲对象,该对象被返回(红色)。相应地更新指针以将其从链接列表中删除,并且空闲列表指向下一个空闲对象。
Allocation that fills up the active slab, with an available partial
返回活动 slab 中的最后一个对象后,已填满的页面将在完整列表中移动,而部分列表中的另一个 slab 将成为活动 slab。
Allocation that fills up the active slab, with no available partial
返回active slab中的最后一个对象后,填满的页面在full list中移动,然后系统分配一个新的slab成为active slab。
Standard free
当内核释放属于部分 slab(或活动的 slab)的对象时,SLUB 只是将其标记为空闲并更新指针。
Free from empty
当内核释放属于部分 slab 的最后一个对象时,该 slab 被释放并交给内存管理单元。
Free from full
当内核释放一个属于完整 slab 的对象时,该 slab 不再是完整的并被移动到部分列表。