IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux mem 2.8 Kfence 详解 -> 正文阅读

[系统运维]Linux mem 2.8 Kfence 详解

1. 原理介绍

Kfence (Kernel Electric Fence) 是 Linux 内核引入的一种低开销的内存错误检测机制,因为是低开销的所以它可以在运行的生产环境中开启,同样由于是低开销所以它的功能相比较 KASAN 会偏弱。

Kfence 的基本原理非常简单,它创建了自己的专有检测内存池 kfence_pool。在 data page 的两边加上了 fence page 电子栅栏,利用 MMU 的特性把 fence page 设置成不可访问。如果对 data page 的访问越过了 page 边界, 就会立刻触发异常。
在这里插入图片描述

Kfence 的主要特点如下:

itemKfenceKASAN
检测密度抽样法,默认每 100ms 提供一个可检测的内存对所有内存访问进行检测
检测粒度核心的检测粒度为 page检测粒度为字节

1.1 slub/slab hook

Kfence 把自己 hook 到 slub/slabmalloc()/free() 流程当中去。但并不是所有的 slub/slab 内存都会从 kfence_pool 内存池中分配。它规定了两个条件:

  • 1、默认每隔 100 ms,开放从 kfence_pool 内存池中分配一次数据。分配成功后会把 kfence_allocation_gate 加 1,阻止继续从 kfence_pool 的分配。kfence_timer 定时到期以后,又会重新开放一次分配。这相当于一种 抽样法
  • 2、每次分配都会占用 kfence_pool 中的一个 data page,所以可分配的内存长度最大为 1 page。
    在这里插入图片描述

1.2 out-of-bounds (over data page)

kfence_pool 中成功分配一个内存对象 obj,不管 obj 的实际大小有多大,都会占据一个 data page
在这里插入图片描述

当原本访问 obj 的操作溢出到相邻的 fence page 时,会立即触发 CPU 异常,通过堆栈回溯揪出异常访问的元凶。

1.3 out-of-bounds (in data page)

大部分情况下 obj 是小于一个 page 的,对于 data page 剩余空间系统使用 canary pattern 进行填充。这种操作是为了检测超出了 obj 但还在 data page 范围内的溢出访问。
在这里插入图片描述

这种类型的溢出是不能在溢出发生时立刻触发的,它只能在 obj free 时,通过检测 canary pattern 被破坏来检测到有 canary 区域的溢出访问。但是异常访问的元凶却不能直接抓出来。

1.4 use-after-free

obj 被 free 以后,对应 data page 也会被设置成不可访问状态。
在这里插入图片描述

这种状态下,如果有操作继续访问 obj 会立即触发 CPU 异常,通过堆栈回溯揪出异常访问的元凶。

1.5 invalid-free

obj free 时会判断记录的 malloc 信息,判断是不是一次异常的 free。

2. 代码解析

分析以下关键的代码流程:

2.1 kfence_protect()

fence page 设置成不可访问的核心就是通过 MMU 清除掉 PTE 中的 present 标志位:

kfence_init_pool() → kfence_protect() → kfence_protect_page():
kfence_free() → __kfence_free() → kfence_guarded_free() → kfence_protect() → kfence_protect_page():

linux-5.16.14\arch\riscv\include\asm\kfence.h:

static inline bool kfence_protect_page(unsigned long addr, bool protect)
{
	pte_t *pte = virt_to_kpte(addr);

	if (protect)
		set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
	else
		set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));

	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);

	return true;
}

2.2 kfence_alloc_pool()

在系统启动时保留 Kfence 需要用到的内存 Page,默认保留 255 个 data page

start_kernel() → mm_init() → kfence_alloc_pool():

void __init kfence_alloc_pool(void)
{
	if (!kfence_sample_interval)
		return;

	__kfence_pool = memblock_alloc(KFENCE_POOL_SIZE, PAGE_SIZE);

	if (!__kfence_pool)
		pr_err("failed to allocate pool\n");
}

#define KFENCE_POOL_SIZE ((CONFIG_KFENCE_NUM_OBJECTS + 1) * 2 * PAGE_SIZE)

config KFENCE_NUM_OBJECTS
	int "Number of guarded objects available"
	range 1 65535
	default 255

2.3 kfence_init()

void __init kfence_init(void)
{
	/* Setting kfence_sample_interval to 0 on boot disables KFENCE. */
	if (!kfence_sample_interval)
		return;

	stack_hash_seed = (u32)random_get_entropy();
    /* (1) 初始化 kfence pool 内存池 */
	if (!kfence_init_pool()) {
		pr_err("%s failed\n", __func__);
		return;
	}

	if (!IS_ENABLED(CONFIG_KFENCE_STATIC_KEYS))
		static_branch_enable(&kfence_allocation_key);
	WRITE_ONCE(kfence_enabled, true);
    /* (2) 初始化定时释放 guard 的 timer */
	queue_delayed_work(system_unbound_wq, &kfence_timer, 0);
	pr_info("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n", KFENCE_POOL_SIZE,
		CONFIG_KFENCE_NUM_OBJECTS, (void *)__kfence_pool,
		(void *)(__kfence_pool + KFENCE_POOL_SIZE));
}

2.4 kfence_alloc()

内存分配流程:

kmem_cache_alloc() → slab_alloc() → kfence_alloc() → __kfence_alloc() → kfence_guarded_alloc():

2.5 kfence_free()

内存释放流程:

kfence_free() → __kfence_free() → kfence_guarded_free():

参考文档

1.Linux内存异常检测工具—kfence
2.Kernel Electric-Fence (KFENCE)
3.Linux Kernel Sanitizers
4.Linux开源动态之一种新的内存非法访问检查工具KFence

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-03 09:29:08  更:2022-05-03 09:29:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:37:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码