C语言 如何在Linux中分配可执行内存

bvjveswy  于 2022-12-11  发布在  Linux
关注(0)|答案(1)|浏览(138)

自Linux 5.8内核发布以来,*__vmalloc()的签名已从:

void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)

到这

void *__vmalloc(unsigned long size, gfp_t gfp_mask)

这意味着你不能通过这个函数来分配可执行内存。所以这就是你的代码在更新后的样子:

#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
return __vmalloc(len, GFP_KERNEL, PAGE_KERNEL_EXEC);
#else
return __vmalloc(len, GFP_KERNEL);
#endif

但这意味着,如果不使用内核的noexec参数,就不可能为内核〉= 5.8分配可执行内存。
这里有什么替代方案,或者换句话说,在内核5.8之后,我如何仍然分配可执行内存?

92dk7w1h

92dk7w1h1#

看看vmalloc.c,我们可以看到

  • __vmalloc调用__vmalloc_node__vmalloc_node调用__vmalloc_node_range(请参阅下文)
  • __vmalloc_node_range保留了prot参数。

因此,我们可以想象从__vmalloc_node_range重新创建__vmalloc(..., PAGE_KERNEL_EXEC);

#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
return __vmalloc(len, GFP_KERNEL, PAGE_KERNEL_EXEC);
#else
return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END, gfp_mask,
             PAGE_KERNEL_EXEC, 0, node, caller);
#endif

vmalloc.c中提取的代码:

void *__vmalloc_node(unsigned long size, unsigned long align,
                gfp_t gfp_mask, int node, const void *caller)
{
    return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
                gfp_mask, PAGE_KERNEL, 0, node, caller);
}
void *__vmalloc(unsigned long size, gfp_t gfp_mask)
{
    return __vmalloc_node(size, 1, gfp_mask, NUMA_NO_NODE,
                __builtin_return_address(0));
}

相关问题