init mark_rodata_ro

mark_rodata_ro 是 x86-64 架构中用于将内核的只读数据段(.rodata)和代码段(.text)在页表级别设置为只读的初始化函数。它的核心目的是利用硬件的内存保护机制,防止内核启动后意外或恶意的修改。

核心作用:硬件级写保护

在内核启动早期,所有内存页都是可写的,因为内核需要修改页表、初始化数据结构。当初始化基本完成、即将启动第一个用户进程之前,内核会调用 mark_rodata_ro,将那些“本不该被修改”的内存区域(内核代码和只读数据)在页表项中清除写权限。

这个函数由 mark_readonly() 在 CONFIG_STRICT_KERNEL_RWX=y 时调用。值得注意的是,CONFIG_STRICT_KERNEL_RWX 在 x86、arm64 和 s390 上是强制启用的,无法通过 make menuconfig关闭。

实现逻辑

该函数在 x86-64 上的典型实现位于 arch/x86/mm/init_64.c,核心步骤如下:

  1. 确定保护范围:通常从 _stext(内核代码段起始)开始,到 __end_rodata(只读数据段结束)为止。在某些实现中,起始地址会跳过第一页(_stext + PAGE_SIZE),因为内核页全局目录(kernel_pg_dir)位于该页中。

  2. 设置页表属性:通过 set_memory_ro() 或类似机制,将指定范围内的页面标记为只读。在早期版本中,使用的是 change_page_attr_addr() 配合 PAGE_KERNEL_RO。

  3. 刷新 TLB:修改页表后,必须刷新 TLB(转换检测缓冲区),以确保 CPU 使用新的权限。通常通过 global_flush_tlb() 或 flush_tlb_all() 完成。

  4. 非可执行标记:对于 .rodata 段之后的数据区域,还会调用 set_memory_nx() 将其标记为不可执行,防止数据被当作代码执行。

与其他机制的关系

mark_rodata_ro 与内核的动态代码修改机制存在交互:

  • ftrace/kprobes:这些机制需要临时修改内核代码。因此,内核引入了 kernel_set_to_readonly 标志和 set_kernel_text_rw() 等函数,允许在需要时临时将代码段恢复为可写,完成修改后再重新保护。

  • CONFIG_DEBUG_RODATA:在较新的内核中,这个配置选项已被 CONFIG_STRICT_KERNEL_RWX 取代。旧版的 mark_rodata_ro 就是由 CONFIG_DEBUG_RODATA 控制的。

安全意义

这个函数是内核自我加固(Self-Hardening) 的关键一步。通过将代码和只读数据标记为只读,它显著增加了利用内核漏洞的难度——攻击者无法直接覆写内核代码或关键数据结构来执行恶意代码。这也是现代内核安全基线的核心组成部分。

调用时机与调用者

mark_rodata_ro() 的调用关系非常清晰,它位于 free_initmem() 之后、启动第一个用户进程之前,是内核从“初始化阶段”切换到“运行阶段”的标志性步骤之一。

这个函数由 kernel_init()(PID 1,即 init 进程的内核线程部分)在启动流程中调用。

典型的调用顺序可以简化为:

rest_init() 创建 kernel_init (PID 1)
    ↓
kernel_init() 等待 kthreadd (PID 2) 完成
    ↓
kernel_init_freeable() 执行 do_basic_setup() 等初始化
    ↓
free_initmem() 释放 __init 代码和数据段
    ↓
mark_rodata_ro() 将 .text 和 .rodata 设为只读
    ↓
run_init_process() 启动第一个用户态进程 (/sbin/init)

内核文档注释明确写道:“Linux calls mark_rodata_ro() after freeing .init code and prior to calling the first init userspace process”。这句话精炼地概括了它的位置。

为什么必须在这个时机调用?

这个时机是精心选择的,有三个关键原因:

  1. __init 代码已释放:在 free_initmem() 之后,所有标记为 __init 的函数(仅在初始化期间运行一次)所占用的内存已经被归还给伙伴系统。mark_rodata_ro() 此时再将 .text 和 .rodata 设为只读,不会影响任何还在运行的初始化代码。

  2. __ro_after_init 数据已定型:内核中有一类特殊数据(如 phys_base),它们在初始化期间需要被写入,但初始化完成后就永不改变。这些数据被放在专门的段中,在 mark_rodata_ro() 执行时一并被设为只读,从而在运行期间受到硬件写保护。

  3. 第一个用户进程尚未启动:此时系统仍处于纯粹的内核态,没有用户态代码运行。在用户态程序开始执行前完成只读保护,可以确保内核的攻击面在最早的时刻就被最小化。

架构相关的实现

mark_rodata_ro() 是一个架构相关的函数,每个支持严格内核内存保护(CONFIG_STRICT_KERNEL_RWX)的架构都需要实现它。在 x86 上,它的实现位于 arch/x86/mm/init_64.c,通过 set_memory_ro() 和 set_memory_nx() 修改页表项,然后刷新 TLB 使新的权限生效。

数据集介绍:宫颈细胞异常检测目标检测数据集一、基础信息数据集名称:宫颈细胞异常检测目标检测数据集图片数量:- 训练集:2,639张医学显微图像- 验证集:706张医学显微图像分类类别:- Dyskeratotic(角化不良细胞):异常角化特征,常见于癌前病变- Koilocytotic(挖空细胞):典型HPV感染标志,提示潜在癌变风险- Metaplastic(化生细胞):正常修复过程中的细胞类型,需与恶性病变鉴别- Parabasal(旁基底细胞):反映上皮细胞成熟度的重要指标- Superficial_Intermediate(表层/中间层细胞):正常宫颈上皮脱落细胞标注格式:YOLO格式边界框标注,可直接用于目标检测模型训练数据特性:医学显微图像数据,包含细胞形态学特征细节,适用于病理分析场景二、适用场景宫颈癌筛查系统开发:训练AI模型自动识别涂片中的异常细胞类型,辅助病理科医生提升宫颈癌筛查效率细胞病理学教学系统:构建数字化教学工具,帮助医学生快速掌握不同宫颈细胞类型的形态学特征医学影像AI研究:支持计算机视觉与临床医学交叉研究,适用于细胞分类算法创新和论文产出远程医疗诊断工具:集成至云端病理分析平台,为基层医疗机构提供智能细胞学诊断支持三、数据集优势临床相关性突出:覆盖WHO宫颈细胞学分类标准中的关键异常类型,直接对应临床诊断需求标注专业性强:细胞分类体系经临床病理专家验证,确保标注结果符合医学诊断标准形态特征完整性:包含正常细胞到异常病变的完整谱系,支持模型学习渐进式病理特征多任务适配性:除目标检测任务外,可通过标签扩展支持细胞分类计数等衍生应用场景数据分布合理性:训练集与验证集按3:1比例划分,确保模型训练的有效验证
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值