Reputation: 428
Since the release of the Linux 5.8 kernel the signature of *__vmalloc()
has changed from:
void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
To this
void *__vmalloc(unsigned long size, gfp_t gfp_mask)
Which means you cannot allocate executable memory via this function. So this is what your code will look like after that update:
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
return __vmalloc(len, GFP_KERNEL, PAGE_KERNEL_EXEC);
#else
return __vmalloc(len, GFP_KERNEL);
#endif
But this means, that without using the noexec
parameter for the kernel, it is not possible to vmalloc executable memory for Kernels >= 5.8.
What is the alternative here, or in other words, how can I still allocate executable memory after kernel 5.8?
Upvotes: 3
Views: 551
Reputation: 9709
Looking at vmalloc.c, we can see that
__vmalloc
calls __vmalloc_node
which calls __vmalloc_node_range
(see below)__vmalloc_node_range
has kept the prot
parameter.So, we can imagine recreate __vmalloc(..., PAGE_KERNEL_EXEC);
from __vmalloc_node_range
:
#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
The extracted code from 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));
}
Upvotes: 2