page-spray


paper : https://arxiv.org/pdf/2406.02624

paper

摘要

问题描述:在以往的页面喷射环境中,一共就只有几百MB的内存,LinuxOS会在用户态进程出现内存压力时分配内核释放的物理页给该用户态进程;但是到了现代操作系统中,内核会kill掉一个具有内存压力的用户态进程。

本文贡献:

  1. 不再使用用户态进程申请物理页,而是使用触发相关内核函数的方式申请物理页;
  2. 分析这些方法的根本原因,设计了一个基于LLVM的方法简化识别内核中页面喷射调用点;
  3. 提出了轻量化的缓解措施;

威胁模型:

  1. Linux低用户权限,利用漏洞进行提权;
  2. 基本保护措施都开了;
  3. 非主流保护措施(如AUTOSLUB、SLAB VIRTUAL)不被包括在内;
  4. 排除了硬件、侧信道漏洞的存在;
  5. 没有考虑体系结构代码中的变化;

页面喷射

example

之后利用喷射内核页面,如果此时的vic-obj是pipe_buffer,我们就有机会利用喷射出来的物理页(应该是有写功能的接口)来篡改pipe_buffer的ops成员,从而实现提权。

root-cause

copy-write 和 remapping

copy-write:

remapping:在用户态和内核态之间copy数据会使开销显著提升,因此通过页表映射的方式使得两者共享,从而提高效率。

copy-write

Raw Page-Level Buffer许多内核子系统会有一个函数初始地创建一个缓冲区,然后后续触发写操作,比如pipe;页面不在初始化的时候分配,仅当第一次写的时候才真正分配。

Non-linear Page-Frags Buffer sk_buff;有线性buffer和非线性buffer,线性buffer使一开始就分配的,其中包含meta data和真正的数据区,这里不进行页面分配;只有当线性buffer不够用的时候才分配非线性buffer,也用copy-write。

remapping

Mmap & Zero Copy Calls. pg_vec

静态分析模型

静态分析方法

Copy-Write Callsites. 寻找根接口,主要分为两类:分配接口复制接口;为了系统地识别调用点,我们在内核中构建了一个全局的调用图,去获取函数间的控制流关系,每一个函数调用被表示为该图中的一个节点,我们通过回溯两个根调用节点来初始化我们的搜索:一个分配一个复制数据。当我们从根接口回溯路径时,我们会识别出这些路径相交的节点。这些节点在控制流级别上被标记为潜在的调用站点。

然后,为了提高精度,我们采用了细粒度的数据流分析。这需要在单个节点内进行数据流分析。确保分配操作发生在复制操作之前,然后从分配点到复制点之间进行搜索,确认是否存在数据的传输,如果有则认为是一个可能的调用点。

Remapping Callsites.这类调用会走函数表,然后涉及很多协议族。所以我们在早期遍历函数表获取函数指针相关的信息,特别关注和mmap相关的函数指针。

根节点还是作为一个控制流层面的节点。回溯到一个调用是我们前面搜集的函数表中的mmap指针的别名,就先认为这是一个调用点。然后再数据流层面采用向后+向前分析,从分配接口回溯,确认分配和remap是否用了相同的结构;

Optimization. 🕊🕊🕊🕊

动态测试与分析

使用Syzkaller:为了使Syzkaller能够报告相应的调用站点的可达性,我们在每个调用点插入WARN_ON(1)导致panic,


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录