Skip to content

Commit 12af2b8

Browse files
rpptmcgrof
authored andcommitted
mm: introduce execmem_alloc() and execmem_free()
module_alloc() is used everywhere as a mean to allocate memory for code. Beside being semantically wrong, this unnecessarily ties all subsystems that need to allocate code, such as ftrace, kprobes and BPF to modules and puts the burden of code allocation to the modules code. Several architectures override module_alloc() because of various constraints where the executable memory can be located and this causes additional obstacles for improvements of code allocation. Start splitting code allocation from modules by introducing execmem_alloc() and execmem_free() APIs. Initially, execmem_alloc() is a wrapper for module_alloc() and execmem_free() is a replacement of module_memfree() to allow updating all call sites to use the new APIs. Since architectures define different restrictions on placement, permissions, alignment and other parameters for memory that can be used by different subsystems that allocate executable memory, execmem_alloc() takes a type argument, that will be used to identify the calling subsystem and to allow architectures define parameters for ranges suitable for that subsystem. No functional changes. Signed-off-by: Mike Rapoport (IBM) <[email protected]> Acked-by: Masami Hiramatsu (Google) <[email protected]> Acked-by: Song Liu <[email protected]> Acked-by: Steven Rostedt (Google) <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]>
1 parent bc6b94d commit 12af2b8

File tree

16 files changed

+128
-45
lines changed

16 files changed

+128
-45
lines changed

arch/powerpc/kernel/kprobes.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include <linux/extable.h>
2020
#include <linux/kdebug.h>
2121
#include <linux/slab.h>
22-
#include <linux/moduleloader.h>
2322
#include <linux/set_memory.h>
23+
#include <linux/execmem.h>
2424
#include <asm/code-patching.h>
2525
#include <asm/cacheflush.h>
2626
#include <asm/sstep.h>
@@ -130,7 +130,7 @@ void *alloc_insn_page(void)
130130
{
131131
void *page;
132132

133-
page = module_alloc(PAGE_SIZE);
133+
page = execmem_alloc(EXECMEM_KPROBES, PAGE_SIZE);
134134
if (!page)
135135
return NULL;
136136

@@ -142,7 +142,7 @@ void *alloc_insn_page(void)
142142
}
143143
return page;
144144
error:
145-
module_memfree(page);
145+
execmem_free(page);
146146
return NULL;
147147
}
148148

arch/s390/kernel/ftrace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
* Author(s): Martin Schwidefsky <[email protected]>
88
*/
99

10-
#include <linux/moduleloader.h>
1110
#include <linux/hardirq.h>
1211
#include <linux/uaccess.h>
1312
#include <linux/ftrace.h>
1413
#include <linux/kernel.h>
1514
#include <linux/types.h>
1615
#include <linux/kprobes.h>
16+
#include <linux/execmem.h>
1717
#include <trace/syscall.h>
1818
#include <asm/asm-offsets.h>
1919
#include <asm/text-patching.h>
@@ -220,7 +220,7 @@ static int __init ftrace_plt_init(void)
220220
{
221221
const char *start, *end;
222222

223-
ftrace_plt = module_alloc(PAGE_SIZE);
223+
ftrace_plt = execmem_alloc(EXECMEM_FTRACE, PAGE_SIZE);
224224
if (!ftrace_plt)
225225
panic("cannot allocate ftrace plt\n");
226226

arch/s390/kernel/kprobes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#define pr_fmt(fmt) "kprobes: " fmt
1111

12-
#include <linux/moduleloader.h>
1312
#include <linux/kprobes.h>
1413
#include <linux/ptrace.h>
1514
#include <linux/preempt.h>
@@ -21,6 +20,7 @@
2120
#include <linux/slab.h>
2221
#include <linux/hardirq.h>
2322
#include <linux/ftrace.h>
23+
#include <linux/execmem.h>
2424
#include <asm/set_memory.h>
2525
#include <asm/sections.h>
2626
#include <asm/dis.h>
@@ -38,7 +38,7 @@ void *alloc_insn_page(void)
3838
{
3939
void *page;
4040

41-
page = module_alloc(PAGE_SIZE);
41+
page = execmem_alloc(EXECMEM_KPROBES, PAGE_SIZE);
4242
if (!page)
4343
return NULL;
4444
set_memory_rox((unsigned long)page, 1);

arch/s390/kernel/module.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/moduleloader.h>
2222
#include <linux/bug.h>
2323
#include <linux/memory.h>
24+
#include <linux/execmem.h>
2425
#include <asm/alternative.h>
2526
#include <asm/nospec-branch.h>
2627
#include <asm/facility.h>
@@ -76,7 +77,7 @@ void *module_alloc(unsigned long size)
7677
#ifdef CONFIG_FUNCTION_TRACER
7778
void module_arch_cleanup(struct module *mod)
7879
{
79-
module_memfree(mod->arch.trampolines_start);
80+
execmem_free(mod->arch.trampolines_start);
8081
}
8182
#endif
8283

@@ -510,7 +511,7 @@ static int module_alloc_ftrace_hotpatch_trampolines(struct module *me,
510511

511512
size = FTRACE_HOTPATCH_TRAMPOLINES_SIZE(s->sh_size);
512513
numpages = DIV_ROUND_UP(size, PAGE_SIZE);
513-
start = module_alloc(numpages * PAGE_SIZE);
514+
start = execmem_alloc(EXECMEM_FTRACE, numpages * PAGE_SIZE);
514515
if (!start)
515516
return -ENOMEM;
516517
set_memory_rox((unsigned long)start, numpages);

arch/sparc/net/bpf_jit_comp_32.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// SPDX-License-Identifier: GPL-2.0
2-
#include <linux/moduleloader.h>
32
#include <linux/workqueue.h>
43
#include <linux/netdevice.h>
54
#include <linux/filter.h>
65
#include <linux/cache.h>
76
#include <linux/if_vlan.h>
7+
#include <linux/execmem.h>
88

99
#include <asm/cacheflush.h>
1010
#include <asm/ptrace.h>
@@ -713,7 +713,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
713713
if (unlikely(proglen + ilen > oldproglen)) {
714714
pr_err("bpb_jit_compile fatal error\n");
715715
kfree(addrs);
716-
module_memfree(image);
716+
execmem_free(image);
717717
return;
718718
}
719719
memcpy(image + proglen, temp, ilen);
@@ -736,7 +736,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
736736
break;
737737
}
738738
if (proglen == oldproglen) {
739-
image = module_alloc(proglen);
739+
image = execmem_alloc(EXECMEM_BPF, proglen);
740740
if (!image)
741741
goto out;
742742
}
@@ -758,7 +758,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
758758
void bpf_jit_free(struct bpf_prog *fp)
759759
{
760760
if (fp->jited)
761-
module_memfree(fp->bpf_func);
761+
execmem_free(fp->bpf_func);
762762

763763
bpf_prog_unlock_free(fp);
764764
}

arch/x86/kernel/ftrace.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/memory.h>
2626
#include <linux/vmalloc.h>
2727
#include <linux/set_memory.h>
28+
#include <linux/execmem.h>
2829

2930
#include <trace/syscall.h>
3031

@@ -261,15 +262,14 @@ void arch_ftrace_update_code(int command)
261262
#ifdef CONFIG_X86_64
262263

263264
#ifdef CONFIG_MODULES
264-
#include <linux/moduleloader.h>
265265
/* Module allocation simplifies allocating memory for code */
266266
static inline void *alloc_tramp(unsigned long size)
267267
{
268-
return module_alloc(size);
268+
return execmem_alloc(EXECMEM_FTRACE, size);
269269
}
270270
static inline void tramp_free(void *tramp)
271271
{
272-
module_memfree(tramp);
272+
execmem_free(tramp);
273273
}
274274
#else
275275
/* Trampolines can only be created if modules are supported */

arch/x86/kernel/kprobes/core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@
4040
#include <linux/kgdb.h>
4141
#include <linux/ftrace.h>
4242
#include <linux/kasan.h>
43-
#include <linux/moduleloader.h>
4443
#include <linux/objtool.h>
4544
#include <linux/vmalloc.h>
4645
#include <linux/pgtable.h>
4746
#include <linux/set_memory.h>
4847
#include <linux/cfi.h>
48+
#include <linux/execmem.h>
4949

5050
#include <asm/text-patching.h>
5151
#include <asm/cacheflush.h>
@@ -495,7 +495,7 @@ void *alloc_insn_page(void)
495495
{
496496
void *page;
497497

498-
page = module_alloc(PAGE_SIZE);
498+
page = execmem_alloc(EXECMEM_KPROBES, PAGE_SIZE);
499499
if (!page)
500500
return NULL;
501501

include/linux/execmem.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _LINUX_EXECMEM_ALLOC_H
3+
#define _LINUX_EXECMEM_ALLOC_H
4+
5+
#include <linux/types.h>
6+
#include <linux/moduleloader.h>
7+
8+
/**
9+
* enum execmem_type - types of executable memory ranges
10+
*
11+
* There are several subsystems that allocate executable memory.
12+
* Architectures define different restrictions on placement,
13+
* permissions, alignment and other parameters for memory that can be used
14+
* by these subsystems.
15+
* Types in this enum identify subsystems that allocate executable memory
16+
* and let architectures define parameters for ranges suitable for
17+
* allocations by each subsystem.
18+
*
19+
* @EXECMEM_DEFAULT: default parameters that would be used for types that
20+
* are not explicitly defined.
21+
* @EXECMEM_MODULE_TEXT: parameters for module text sections
22+
* @EXECMEM_KPROBES: parameters for kprobes
23+
* @EXECMEM_FTRACE: parameters for ftrace
24+
* @EXECMEM_BPF: parameters for BPF
25+
* @EXECMEM_TYPE_MAX:
26+
*/
27+
enum execmem_type {
28+
EXECMEM_DEFAULT,
29+
EXECMEM_MODULE_TEXT = EXECMEM_DEFAULT,
30+
EXECMEM_KPROBES,
31+
EXECMEM_FTRACE,
32+
EXECMEM_BPF,
33+
EXECMEM_TYPE_MAX,
34+
};
35+
36+
/**
37+
* execmem_alloc - allocate executable memory
38+
* @type: type of the allocation
39+
* @size: how many bytes of memory are required
40+
*
41+
* Allocates memory that will contain executable code, either generated or
42+
* loaded from kernel modules.
43+
*
44+
* The memory will have protections defined by architecture for executable
45+
* region of the @type.
46+
*
47+
* Return: a pointer to the allocated memory or %NULL
48+
*/
49+
void *execmem_alloc(enum execmem_type type, size_t size);
50+
51+
/**
52+
* execmem_free - free executable memory
53+
* @ptr: pointer to the memory that should be freed
54+
*/
55+
void execmem_free(void *ptr);
56+
57+
#endif /* _LINUX_EXECMEM_ALLOC_H */

include/linux/moduleloader.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section);
2929
sections. Returns NULL on failure. */
3030
void *module_alloc(unsigned long size);
3131

32-
/* Free memory returned from module_alloc. */
33-
void module_memfree(void *module_region);
34-
3532
/* Determines if the section name is an init section (that is only used during
3633
* module loading).
3734
*/

kernel/bpf/core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <linux/skbuff.h>
2323
#include <linux/vmalloc.h>
2424
#include <linux/random.h>
25-
#include <linux/moduleloader.h>
2625
#include <linux/bpf.h>
2726
#include <linux/btf.h>
2827
#include <linux/objtool.h>
@@ -37,6 +36,7 @@
3736
#include <linux/nospec.h>
3837
#include <linux/bpf_mem_alloc.h>
3938
#include <linux/memcontrol.h>
39+
#include <linux/execmem.h>
4040

4141
#include <asm/barrier.h>
4242
#include <asm/unaligned.h>
@@ -1050,12 +1050,12 @@ void bpf_jit_uncharge_modmem(u32 size)
10501050

10511051
void *__weak bpf_jit_alloc_exec(unsigned long size)
10521052
{
1053-
return module_alloc(size);
1053+
return execmem_alloc(EXECMEM_BPF, size);
10541054
}
10551055

10561056
void __weak bpf_jit_free_exec(void *addr)
10571057
{
1058-
module_memfree(addr);
1058+
execmem_free(addr);
10591059
}
10601060

10611061
struct bpf_binary_header *

0 commit comments

Comments
 (0)