尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

init execmem_arch_setup

init execmem_arch_setup execmem_arch_setup()是 Linux 内核中用于为可执行内存分配如内核模块、BPF JIT、ftrace、kprobes定义架构相关地址范围和权限的初始化钩子。核心作用定义“可执行内存”的分配规则它属于execmem子系统可执行内存分配器的一部分。该子系统的目标是将可执行内存的分配从模块加载器中解耦让 BPF、kprobes、ftrace 等子系统不再依赖CONFIG_MODULES同时允许不同架构定义各自的内存范围、权限和约束。execmem_arch_setup()由架构实现返回一个填充好的struct execmem_info告诉通用的execmem核心哪些地址范围可以用于分配可执行代码以及用什么页保护属性pgprot和地址对齐要求。x86 架构下的典型实现在 x86 上该函数的核心逻辑是地址范围根据kaslr_enabled()决定起始地址。如果启用了 KASLR会在MODULES_VADDR基础上加一个随机偏移get_random_u32_inclusive(1, 1024) * PAGE_SIZE以增加安全性。填充execmem_info将计算好的start和固定的endMODULES_END填入EXECMEM_DEFAULT范围并设置pgprot PAGE_KERNEL、alignment MODULE_ALIGN同时标记EXECMEM_KASAN_SHADOW标志。调用时机execmem_arch_setup()不是直接被 x86 的初始化代码调用的。它是由通用的execmem核心在execmem_init()中调用的void __init execmem_init(void) { struct execmem_info *info execmem_arch_setup(); // ... 验证并保存 info }而execmem_init()通常是一个core_initcall在启动流程中较早执行。对于 x86 这类可能需要极早分配可执行内存的架构它还会被特殊处理以确保在 ftrace 等子系统需要分配代码内存之前就完成初始化。与内存管理有关系execmem_arch_setup()与内存管理有非常紧密的关系。它本身就是内存管理子系统的一部分专门负责可执行内存Executable Memory这一特殊领域的地址空间规划。关系体现在三个层面1. 它管理的是虚拟地址空间的一部分execmem_arch_setup()返回的struct execmem_info中最核心的字段就是start和end——它们定义了可执行内存可以使用的虚拟地址范围。在 x86 上这个范围就是MODULES_VADDR到MODULES_END之间的模块区域。这本质上是在内核虚拟地址空间布局中为“可执行代码”划出一块专属的“地盘”。2. 它依赖内存管理的页表机制它返回的pgprot字段通常是PAGE_KERNEL会直接用于建立页表映射。execmem分配器在拿到这块内存后需要通过vmap等机制将其映射到内核虚拟地址空间并设置正确的页表权限可读、可写、可执行。这完全依赖于内存管理的页表操作。3. 它与 KASAN 影子内存有交互x86 的实现中标记了EXECMEM_KASAN_SHADOW标志。这意味着execmem分配器在分配内存时需要额外考虑 KASAN 影子内存的映射。当可执行内存被分配后KASAN 的影子内存也需要同步更新以确保对这块内存的访问不会误报。这直接涉及内存管理中的影子内存机制。为什么单独设计传统上可执行内存的分配如内核模块加载是耦合在模块加载器中的。但 BPF JIT、ftrace、kprobes 等子系统也需要分配可执行内存却不一定依赖CONFIG_MODULES。execmem子系统的设计目标就是将可执行内存的分配从模块加载器中解耦让所有需要可执行内存的子系统都能使用统一的分配器。而execmem_arch_setup()就是架构层面对这个分配器的“配置入口”——它告诉内存管理子系统这块地址空间可以用来放可执行代码请按这个权限和对齐要求来管理它。所以是内存管理在可执行代码领域的专门延伸。
返回列表