* [PATCH bpf-next 1/5] bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc()
2026-06-26 18:42 [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
@ 2026-06-26 18:42 ` Mike Rapoport (Microsoft)
2026-06-26 18:59 ` sashiko-bot
2026-06-26 18:42 ` [PATCH bpf-next 2/5] bpf: drop __weak from bpf_jit_alloc_exec() and bpf_jit_free_exec() Mike Rapoport (Microsoft)
` (4 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-06-26 18:42 UTC (permalink / raw)
To: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Daniel Borkmann, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
Mike Rapoport, H. Peter Anvin, Yonghong Song, bpf, linux-kernel,
x86
bpf_dispatcher->rw_image is a temporary writable buffer that
arch_prepare_bpf_dispatcher() fills and then copies into
bpf_dispatcher->image using bpf_arch_text_copy().
The rel32 offsets emitted by emit_bpf_dispatcher() are calculated against
->image, so ->rw_image does not need to live in the module address range.
Allocate ->rw_image with vmalloc() to avoid permissions dance when
EXECMEM_BPF will be backed by ROX caches.
Also saves a bit of space in the more scarce module address space.
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
kernel/bpf/dispatcher.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/dispatcher.c b/kernel/bpf/dispatcher.c
index b77db7413f8c..a7a6a375cdd3 100644
--- a/kernel/bpf/dispatcher.c
+++ b/kernel/bpf/dispatcher.c
@@ -148,7 +148,10 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from,
d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero);
if (!d->image)
goto out;
- d->rw_image = bpf_jit_alloc_exec(PAGE_SIZE);
+ /* d->rw_image doesn't need to be in module memory range, so we
+ * can use vmalloc.
+ */
+ d->rw_image = vmalloc(PAGE_SIZE);
if (!d->rw_image) {
bpf_prog_pack_free(d->image, PAGE_SIZE);
d->image = NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH bpf-next 1/5] bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc()
2026-06-26 18:42 ` [PATCH bpf-next 1/5] bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc() Mike Rapoport (Microsoft)
@ 2026-06-26 18:59 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-06-26 18:59 UTC (permalink / raw)
Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Uninitialized vmalloc memory is copied into the executable BPF dispatcher image, creating an information leak and potential W^X bypass.
--
commit a818beebb25a7db7c07963818946c91a734b9050
Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc()
This patch changes the allocation of the temporary bpf_dispatcher->rw_image
from bpf_jit_alloc_exec() to vmalloc(). This saves space in the module address
range since the temporary buffer doesn't require executable permissions.
> diff --git a/kernel/bpf/dispatcher.c b/kernel/bpf/dispatcher.c
> index b77db7413f8c7..a7a6a375cdd31 100644
> --- a/kernel/bpf/dispatcher.c
> +++ b/kernel/bpf/dispatcher.c
[ ... ]
> @@ -148,7 +148,10 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from,
> d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero);
> if (!d->image)
> goto out;
> - d->rw_image = bpf_jit_alloc_exec(PAGE_SIZE);
> + /* d->rw_image doesn't need to be in module memory range, so we
> + * can use vmalloc.
> + */
> + d->rw_image = vmalloc(PAGE_SIZE);
[Severity: High]
This is a pre-existing issue, but does allocating this temporary buffer without
zeroing it leak uninitialized memory into the executable dispatcher image?
When bpf_dispatcher_update() updates the dispatcher, it unconditionally copies
PAGE_SIZE / 2 bytes (2048 bytes) from this buffer into the executable RO+X
image:
kernel/bpf/dispatcher.c:bpf_dispatcher_update() {
...
arch_prepare_bpf_dispatcher(d->rw_image, ...);
...
if (IS_ERR(bpf_arch_text_copy(new, tmp, PAGE_SIZE / 2)))
...
}
Since arch_prepare_bpf_dispatcher() only writes a small number of
instructions into the buffer, the rest of the 2048 bytes copied by
bpf_arch_text_copy() comes from whatever was previously in this allocation.
Could this allow malicious gadgets to be sprayed into vmalloc space from
userspace and then copied into executable memory, potentially bypassing W^X
protections?
Would it be safer to use vzalloc() here to ensure the unused portions of the
buffer are padded with zeroes?
> if (!d->rw_image) {
> bpf_prog_pack_free(d->image, PAGE_SIZE);
> d->image = NULL;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260626-execmem-x86-rox-bpf-v0-v1-0-45a0b0ed4fe9@kernel.org?part=1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH bpf-next 2/5] bpf: drop __weak from bpf_jit_alloc_exec() and bpf_jit_free_exec()
2026-06-26 18:42 [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
2026-06-26 18:42 ` [PATCH bpf-next 1/5] bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc() Mike Rapoport (Microsoft)
@ 2026-06-26 18:42 ` Mike Rapoport (Microsoft)
2026-06-26 18:42 ` [PATCH bpf-next 3/5] bpf: alloc_prog_pack(): skip ROX management for already ROX memory Mike Rapoport (Microsoft)
` (3 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-06-26 18:42 UTC (permalink / raw)
To: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Daniel Borkmann, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
Mike Rapoport, H. Peter Anvin, Yonghong Song, bpf, linux-kernel,
x86
bpf_jit_alloc_exec() and bpf_jit_free_exec() are wrappers for the
corresponding execmem APIs.
Architectures define the properties of the memory range needed by BPF in
their initialization of execmem and don't need to override neither of
them.
Drop the __weak qualifier from bpf_jit_alloc_exec() and
bpf_jit_free_exec().
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
kernel/bpf/core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 649cce41e13f..2188f6b5a9e2 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1060,12 +1060,12 @@ void bpf_jit_uncharge_modmem(u32 size)
atomic_long_sub(size, &bpf_jit_current);
}
-void *__weak bpf_jit_alloc_exec(unsigned long size)
+void *bpf_jit_alloc_exec(unsigned long size)
{
return execmem_alloc(EXECMEM_BPF, size);
}
-void __weak bpf_jit_free_exec(void *addr)
+void bpf_jit_free_exec(void *addr)
{
execmem_free(addr);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH bpf-next 3/5] bpf: alloc_prog_pack(): skip ROX management for already ROX memory
2026-06-26 18:42 [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
2026-06-26 18:42 ` [PATCH bpf-next 1/5] bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc() Mike Rapoport (Microsoft)
2026-06-26 18:42 ` [PATCH bpf-next 2/5] bpf: drop __weak from bpf_jit_alloc_exec() and bpf_jit_free_exec() Mike Rapoport (Microsoft)
@ 2026-06-26 18:42 ` Mike Rapoport (Microsoft)
2026-06-26 18:42 ` [PATCH bpf-next 4/5] bpf, x86: make sure allocation in arch_bpf_trampoline_size() is writable Mike Rapoport (Microsoft)
` (2 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-06-26 18:42 UTC (permalink / raw)
To: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Daniel Borkmann, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
Mike Rapoport, H. Peter Anvin, Yonghong Song, bpf, linux-kernel,
x86
execmem_alloc() can return ROX memory that is already filled with
architecture defined trapping instructions.
In preparation for enabling this mode for BPF on x86, make sure that there
is no redundant management of the ROX memory.
There is no need to fill allocated memory with trapping instructions, to
request permissions reset on free and to set ROX permissions as this all
is handled by execmem_alloc().
Add bpf_jit_mem_is_rox() wrapper for execmem_is_rox(), use it to check if
execmem_alloc() returns ROX memory and skip the redundant steps in that
case.
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
kernel/bpf/core.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 2188f6b5a9e2..9666b6cca797 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -904,6 +904,11 @@ static LIST_HEAD(pack_list);
#define BPF_PROG_CHUNK_COUNT (BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE)
+static bool bpf_jit_mem_is_rox(void)
+{
+ return execmem_is_rox(EXECMEM_BPF);
+}
+
static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insns)
{
struct bpf_prog_pack *pack;
@@ -915,14 +920,16 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
pack->ptr = bpf_jit_alloc_exec(BPF_PROG_PACK_SIZE);
if (!pack->ptr)
goto out;
- bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE);
bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE);
- set_vm_flush_reset_perms(pack->ptr);
- err = set_memory_rox((unsigned long)pack->ptr,
- BPF_PROG_PACK_SIZE / PAGE_SIZE);
- if (err)
- goto out;
+ if (!bpf_jit_mem_is_rox()) {
+ bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE);
+ set_vm_flush_reset_perms(pack->ptr);
+ err = set_memory_rox((unsigned long)pack->ptr,
+ BPF_PROG_PACK_SIZE / PAGE_SIZE);
+ if (err)
+ goto out;
+ }
list_add_tail(&pack->list, &pack_list);
return pack;
@@ -943,7 +950,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
if (size > BPF_PROG_PACK_SIZE) {
size = round_up(size, PAGE_SIZE);
ptr = bpf_jit_alloc_exec(size);
- if (ptr) {
+ if (ptr && !bpf_jit_mem_is_rox()) {
int err;
bpf_fill_ill_insns(ptr, size);
--
2.53.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH bpf-next 4/5] bpf, x86: make sure allocation in arch_bpf_trampoline_size() is writable
2026-06-26 18:42 [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
` (2 preceding siblings ...)
2026-06-26 18:42 ` [PATCH bpf-next 3/5] bpf: alloc_prog_pack(): skip ROX management for already ROX memory Mike Rapoport (Microsoft)
@ 2026-06-26 18:42 ` Mike Rapoport (Microsoft)
2026-06-26 18:42 ` [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
2026-07-09 8:03 ` [PATCH bpf-next 0/5] bpf, x86: " Mike Rapoport
5 siblings, 0 replies; 15+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-06-26 18:42 UTC (permalink / raw)
To: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Daniel Borkmann, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
Mike Rapoport, H. Peter Anvin, Yonghong Song, bpf, linux-kernel,
x86
arch_bpf_trampoline_size() allocates a buffer to get actual size required
for a trampoline.
This buffer must be in the module address space because
__arch_prepare_bpf_trampoline() calculates rel32 offsets relatively to
that buffer.
In preparation for enabling ROX mode for EXECMEM_BPF make sure that the
allocated memory is writable.
Add bpf_jit_alloc_exec_rw() wrapper for execmem_alloc_rw() and use it for
buffer allocation in arch_bpf_trampoline_size().
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
arch/x86/net/bpf_jit_comp.c | 5 ++---
include/linux/filter.h | 1 +
kernel/bpf/core.c | 5 +++++
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 054e043ffcd2..ba562d3bf031 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3703,13 +3703,12 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
int ret;
/* Allocate a temporary buffer for __arch_prepare_bpf_trampoline().
- * This will NOT cause fragmentation in direct map, as we do not
- * call set_memory_*() on this buffer.
*
* We cannot use kvmalloc here, because we need image to be in
* module memory range.
+ * Since it must be writable use bpf_jit_alloc_exec_rw().
*/
- image = bpf_jit_alloc_exec(PAGE_SIZE);
+ image = bpf_jit_alloc_exec_rw(PAGE_SIZE);
if (!image)
return -ENOMEM;
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 67d337ede91b..773b16f06572 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1323,6 +1323,7 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
void bpf_jit_binary_free(struct bpf_binary_header *hdr);
u64 bpf_jit_alloc_exec_limit(void);
void *bpf_jit_alloc_exec(unsigned long size);
+void *bpf_jit_alloc_exec_rw(unsigned long size);
void bpf_jit_free_exec(void *addr);
void bpf_jit_free(struct bpf_prog *fp);
struct bpf_binary_header *
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 9666b6cca797..55284b5d0292 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1072,6 +1072,11 @@ void *bpf_jit_alloc_exec(unsigned long size)
return execmem_alloc(EXECMEM_BPF, size);
}
+void *bpf_jit_alloc_exec_rw(unsigned long size)
+{
+ return execmem_alloc_rw(EXECMEM_BPF, size);
+}
+
void bpf_jit_free_exec(void *addr)
{
execmem_free(addr);
--
2.53.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
2026-06-26 18:42 [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
` (3 preceding siblings ...)
2026-06-26 18:42 ` [PATCH bpf-next 4/5] bpf, x86: make sure allocation in arch_bpf_trampoline_size() is writable Mike Rapoport (Microsoft)
@ 2026-06-26 18:42 ` Mike Rapoport (Microsoft)
2026-06-26 18:59 ` sashiko-bot
2026-07-09 8:03 ` [PATCH bpf-next 0/5] bpf, x86: " Mike Rapoport
5 siblings, 1 reply; 15+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-06-26 18:42 UTC (permalink / raw)
To: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Daniel Borkmann, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
Mike Rapoport, H. Peter Anvin, Yonghong Song, bpf, linux-kernel,
x86
BPF core and x86 JIT use text poking and temporary writable buffers and
thus can handle ROX memory.
Enable ROX cache for EXECMEM_BPF when configuration and CPU features allow
that.
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
arch/x86/mm/init.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index fb67217fddcd..079f8c7e9e3c 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -1107,10 +1107,10 @@ struct execmem_info __init *execmem_arch_setup(void)
.alignment = MODULE_ALIGN,
},
[EXECMEM_BPF] = {
- .flags = EXECMEM_KASAN_SHADOW,
+ .flags = flags,
.start = start,
.end = MODULES_END,
- .pgprot = PAGE_KERNEL,
+ .pgprot = pgprot,
.alignment = MODULE_ALIGN,
},
[EXECMEM_MODULE_DATA] = {
--
2.53.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
2026-06-26 18:42 ` [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
@ 2026-06-26 18:59 ` sashiko-bot
2026-06-27 14:44 ` Alexei Starovoitov
2026-07-09 12:53 ` Mike Rapoport
0 siblings, 2 replies; 15+ messages in thread
From: sashiko-bot @ 2026-06-26 18:59 UTC (permalink / raw)
Cc: bpf
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Pages freed from the ROX cache via vfree() are returned to the page allocator with Read-Only permissions, causing kernel panics on subsequent allocations.
- [High] The return value of execmem_restore_rox() is ignored in __execmem_cache_free(), potentially leaving cached memory as Non-Executable (NX) and crashing the kernel when BPF programs are executed.
--
commit d59aa3f12b249d60a053835fa723486bb4d4f203
Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
BPF core and x86 JIT use text poking and temporary writable buffers and
thus can handle ROX memory. Enable ROX cache for EXECMEM_BPF when
configuration and CPU features allow that.
> diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
> index fb67217fddcd3..079f8c7e9e3cd 100644
> --- a/arch/x86/mm/init.c
> +++ b/arch/x86/mm/init.c
> @@ -1107,10 +1107,10 @@ struct execmem_info __init *execmem_arch_setup(void)
> .alignment = MODULE_ALIGN,
> },
> [EXECMEM_BPF] = {
> - .flags = EXECMEM_KASAN_SHADOW,
> + .flags = flags,
> .start = start,
> .end = MODULES_END,
> - .pgprot = PAGE_KERNEL,
> + .pgprot = pgprot,
[Severity: Critical]
This is a pre-existing issue, but enabling the ROX cache for BPF
significantly increases the likelihood of triggering it. When memory is freed
back to the page allocator via vfree() from the ROX cache, it appears to
retain Read-Only permissions.
In mm/execmem.c:execmem_cache_populate_alloc(), memory is allocated without
the VM_FLUSH_RESET_PERMS flag:
unsigned long vm_flags = VM_ALLOW_HUGE_VMAP;
...
p = execmem_vmalloc(range, alloc_size, PAGE_KERNEL, vm_flags);
When the block is later cleaned up in mm/execmem.c:execmem_cache_clean(), it
is freed using vfree():
execmem_set_direct_map_valid(vm, true);
mas_store_gfp(&mas, NULL, GFP_KERNEL);
vfree(area);
Since VM_FLUSH_RESET_PERMS was omitted, vfree() skips resetting the direct map
permissions. If a subsequent kernel subsystem allocates these same pages from
the buddy allocator and attempts to write to them, will this result in a Write
Protection fault and kernel panic?
[Severity: High]
This is also a pre-existing issue exposed by enabling the ROX cache. In the
error handling path, the return value of execmem_restore_rox() is ignored.
Looking at mm/execmem.c:__execmem_cache_free():
execmem_fill_trapping_insns(ptr, size);
execmem_restore_rox(ptr, size);
err = execmem_cache_add_locked(ptr, size, gfp_mask);
If execmem_restore_rox() fails (for example, if set_memory_rox() returns
ENOMEM when allocating page tables for direct map splitting), the memory is
left as Non-Executable (NX).
Since this error is ignored and the memory is still added to the free list,
could BPF subsequently allocate this NX memory from the cache, assuming it is
executable, and crash the system when attempting to execute JIT code?
> .alignment = MODULE_ALIGN,
> },
> [EXECMEM_MODULE_DATA] = {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260626-execmem-x86-rox-bpf-v0-v1-0-45a0b0ed4fe9@kernel.org?part=5
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
2026-06-26 18:59 ` sashiko-bot
@ 2026-06-27 14:44 ` Alexei Starovoitov
2026-07-09 12:53 ` Mike Rapoport
2026-07-09 12:53 ` Mike Rapoport
1 sibling, 1 reply; 15+ messages in thread
From: Alexei Starovoitov @ 2026-06-27 14:44 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
On Fri Jun 26, 2026 at 11:59 AM PDT, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] Pages freed from the ROX cache via vfree() are returned to the page allocator with Read-Only permissions, causing kernel panics on subsequent allocations.
> - [High] The return value of execmem_restore_rox() is ignored in __execmem_cache_free(), potentially leaving cached memory as Non-Executable (NX) and crashing the kernel when BPF programs are executed.
The pre-existing issues sounds real and probably should be addressed
before cleanups in this series? Or altogether?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
2026-06-27 14:44 ` Alexei Starovoitov
@ 2026-07-09 12:53 ` Mike Rapoport
0 siblings, 0 replies; 15+ messages in thread
From: Mike Rapoport @ 2026-07-09 12:53 UTC (permalink / raw)
To: Alexei Starovoitov; +Cc: sashiko-reviews, bpf
On Sat, Jun 27, 2026 at 07:44:44AM -0700, Alexei Starovoitov wrote:
> On Fri Jun 26, 2026 at 11:59 AM PDT, sashiko-bot wrote:
> > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> >
> > Pre-existing issues:
> > - [Critical] Pages freed from the ROX cache via vfree() are returned to the page allocator with Read-Only permissions, causing kernel panics on subsequent allocations.
> > - [High] The return value of execmem_restore_rox() is ignored in __execmem_cache_free(), potentially leaving cached memory as Non-Executable (NX) and crashing the kernel when BPF programs are executed.
>
> The pre-existing issues sounds real and probably should be addressed
> before cleanups in this series? Or altogether?
Both are false positives.
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
2026-06-26 18:59 ` sashiko-bot
2026-06-27 14:44 ` Alexei Starovoitov
@ 2026-07-09 12:53 ` Mike Rapoport
1 sibling, 0 replies; 15+ messages in thread
From: Mike Rapoport @ 2026-07-09 12:53 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf, Alexei Starovoitov, Daniel Borkmann
On Fri, Jun 26, 2026 at 06:59:44PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] Pages freed from the ROX cache via vfree() are returned to the page allocator with Read-Only permissions, causing kernel panics on subsequent allocations.
> - [High] The return value of execmem_restore_rox() is ignored in __execmem_cache_free(), potentially leaving cached memory as Non-Executable (NX) and crashing the kernel when BPF programs are executed.
> --
>
> commit d59aa3f12b249d60a053835fa723486bb4d4f203
> Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
>
> x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
>
> BPF core and x86 JIT use text poking and temporary writable buffers and
> thus can handle ROX memory. Enable ROX cache for EXECMEM_BPF when
> configuration and CPU features allow that.
>
> > diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
> > index fb67217fddcd3..079f8c7e9e3cd 100644
> > --- a/arch/x86/mm/init.c
> > +++ b/arch/x86/mm/init.c
> > @@ -1107,10 +1107,10 @@ struct execmem_info __init *execmem_arch_setup(void)
> > .alignment = MODULE_ALIGN,
> > },
> > [EXECMEM_BPF] = {
> > - .flags = EXECMEM_KASAN_SHADOW,
> > + .flags = flags,
> > .start = start,
> > .end = MODULES_END,
> > - .pgprot = PAGE_KERNEL,
> > + .pgprot = pgprot,
>
> [Severity: Critical]
> This is a pre-existing issue, but enabling the ROX cache for BPF
> significantly increases the likelihood of triggering it. When memory is freed
> back to the page allocator via vfree() from the ROX cache, it appears to
> retain Read-Only permissions.
>
> In mm/execmem.c:execmem_cache_populate_alloc(), memory is allocated without
> the VM_FLUSH_RESET_PERMS flag:
>
> unsigned long vm_flags = VM_ALLOW_HUGE_VMAP;
> ...
> p = execmem_vmalloc(range, alloc_size, PAGE_KERNEL, vm_flags);
>
> When the block is later cleaned up in mm/execmem.c:execmem_cache_clean(), it
> is freed using vfree():
>
> execmem_set_direct_map_valid(vm, true);
> mas_store_gfp(&mas, NULL, GFP_KERNEL);
> vfree(area);
>
> Since VM_FLUSH_RESET_PERMS was omitted, vfree() skips resetting the direct map
> permissions. If a subsequent kernel subsystem allocates these same pages from
> the buddy allocator and attempts to write to them, will this result in a Write
> Protection fault and kernel panic?
The call to execmem_set_direct_map_valid() resets the direct map
permissions so there's no need to reset them in vfree().
> [Severity: High]
> This is also a pre-existing issue exposed by enabling the ROX cache. In the
> error handling path, the return value of execmem_restore_rox() is ignored.
>
> Looking at mm/execmem.c:__execmem_cache_free():
>
> execmem_fill_trapping_insns(ptr, size);
> execmem_restore_rox(ptr, size);
> err = execmem_cache_add_locked(ptr, size, gfp_mask);
>
> If execmem_restore_rox() fails (for example, if set_memory_rox() returns
> ENOMEM when allocating page tables for direct map splitting), the memory is
> left as Non-Executable (NX).
set_memory_rox() cannot fail here.
The only failure path in set_memory is an allocation failure when there is
a splitting of large pages. At this point a 2M page would be already split
by execmem_alloc_rw() so execmem_restore_rox() updates permissions on 4k
pages and collapses them into 2M page once the entire 2M page is ROX.
> Since this error is ignored and the memory is still added to the free list,
> could BPF subsequently allocate this NX memory from the cache, assuming it is
> executable, and crash the system when attempting to execute JIT code?
>
> > .alignment = MODULE_ALIGN,
> > },
> > [EXECMEM_MODULE_DATA] = {
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260626-execmem-x86-rox-bpf-v0-v1-0-45a0b0ed4fe9@kernel.org?part=5
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations
2026-06-26 18:42 [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
` (4 preceding siblings ...)
2026-06-26 18:42 ` [PATCH bpf-next 5/5] x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations Mike Rapoport (Microsoft)
@ 2026-07-09 8:03 ` Mike Rapoport
2026-07-09 12:12 ` Daniel Borkmann
5 siblings, 1 reply; 15+ messages in thread
From: Mike Rapoport @ 2026-07-09 8:03 UTC (permalink / raw)
To: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Daniel Borkmann, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
H. Peter Anvin, Yonghong Song, bpf, linux-kernel, x86
Gentle ping
On Fri, Jun 26, 2026 at 09:42:27PM +0300, Mike Rapoport (Microsoft) wrote:
> Hi,
>
> BPF allocations of executable memory on x86 are essentially read-only. Most
> paths that call bpf_jit_alloc_exec() immediately make it ROX with
> set_memory_rox().
>
> The code generation, at least on x86, uses separately allocated writable
> buffers and then updates the actual text memory with text_poke().
>
> These patches do several small adjustments to how BPF allocates executable
> memory and enable EXECMEM_ROX_CACHE for BPF allocations on x86.
>
> ---
> Mike Rapoport (Microsoft) (5):
> bpf: dispatcher: allocate bpf_dispatcher->rw_image with vmalloc()
> bpf: drop __weak from bpf_jit_alloc_exec() and bpf_jit_free_exec()
> bpf: alloc_prog_pack(): skip ROX management for already ROX memory
> bpf, x86: make sure allocation in arch_bpf_trampoline_size() is writable
> x86/bpf: enable EXECMEM_ROX_CACHE for BPF allocations
>
> arch/x86/mm/init.c | 4 ++--
> arch/x86/net/bpf_jit_comp.c | 5 ++---
> include/linux/filter.h | 1 +
> kernel/bpf/core.c | 30 +++++++++++++++++++++---------
> kernel/bpf/dispatcher.c | 5 ++++-
> 5 files changed, 30 insertions(+), 15 deletions(-)
> ---
> base-commit: 53435562a725962e4de0c29653223129ba11643a
> change-id: 20260626-execmem-x86-rox-bpf-v0-b4241ade80df
>
> Best regards,
> --
> Sincerely yours,
> Mike.
>
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations
2026-07-09 8:03 ` [PATCH bpf-next 0/5] bpf, x86: " Mike Rapoport
@ 2026-07-09 12:12 ` Daniel Borkmann
2026-07-09 12:55 ` Mike Rapoport
0 siblings, 1 reply; 15+ messages in thread
From: Daniel Borkmann @ 2026-07-09 12:12 UTC (permalink / raw)
To: Mike Rapoport, Alexei Starovoitov, Andrii Nakryiko,
Andy Lutomirski, Borislav Petkov, Dave Hansen, Eduard Zingerman,
Ingo Molnar, Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner
Cc: Emil Tsalapatis, Jiri Olsa, John Fastabend, Martin KaFai Lau,
H. Peter Anvin, Yonghong Song, bpf, linux-kernel, x86
Hi Mike,
On 7/9/26 10:03 AM, Mike Rapoport wrote:
> Gentle ping
>
> On Fri, Jun 26, 2026 at 09:42:27PM +0300, Mike Rapoport (Microsoft) wrote:
>> Hi,
>>
>> BPF allocations of executable memory on x86 are essentially read-only. Most
>> paths that call bpf_jit_alloc_exec() immediately make it ROX with
>> set_memory_rox().
>>
>> The code generation, at least on x86, uses separately allocated writable
>> buffers and then updates the actual text memory with text_poke().
>>
>> These patches do several small adjustments to how BPF allocates executable
>> memory and enable EXECMEM_ROX_CACHE for BPF allocations on x86.
I think there was an open Q from Alexei wrt the sashiko reports [0] and
whether you could address them. Once done, please resend to bpf list.
Thanks,
Daniel
[0] https://lore.kernel.org/bpf/20260626-execmem-x86-rox-bpf-v0-v1-0-45a0b0ed4fe9@kernel.org/#r
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations
2026-07-09 12:12 ` Daniel Borkmann
@ 2026-07-09 12:55 ` Mike Rapoport
2026-07-10 12:30 ` Daniel Borkmann
0 siblings, 1 reply; 15+ messages in thread
From: Mike Rapoport @ 2026-07-09 12:55 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Dave Hansen, Eduard Zingerman, Ingo Molnar,
Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner, Emil Tsalapatis, Jiri Olsa, John Fastabend,
Martin KaFai Lau, H. Peter Anvin, Yonghong Song, bpf,
linux-kernel, x86
Hi Daniel,
On Thu, Jul 09, 2026 at 02:12:04PM +0200, Daniel Borkmann wrote:
> Hi Mike,
>
> On 7/9/26 10:03 AM, Mike Rapoport wrote:
> > Gentle ping
> >
> > On Fri, Jun 26, 2026 at 09:42:27PM +0300, Mike Rapoport (Microsoft) wrote:
> > > Hi,
> > >
> > > BPF allocations of executable memory on x86 are essentially read-only. Most
> > > paths that call bpf_jit_alloc_exec() immediately make it ROX with
> > > set_memory_rox().
> > >
> > > The code generation, at least on x86, uses separately allocated writable
> > > buffers and then updates the actual text memory with text_poke().
> > >
> > > These patches do several small adjustments to how BPF allocates executable
> > > memory and enable EXECMEM_ROX_CACHE for BPF allocations on x86.
>
> I think there was an open Q from Alexei wrt the sashiko reports [0] and
> whether you could address them. Once done, please resend to bpf list.
Thanks for the link!
I'm not subscribed to bpf@ and it took me a few minutes to realize why I
don't see this in my inbox.
> Thanks,
> Daniel
>
> [0] https://lore.kernel.org/bpf/20260626-execmem-x86-rox-bpf-v0-v1-0-45a0b0ed4fe9@kernel.org/#r
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH bpf-next 0/5] bpf, x86: enable EXECMEM_ROX_CACHE for BPF allocations
2026-07-09 12:55 ` Mike Rapoport
@ 2026-07-10 12:30 ` Daniel Borkmann
0 siblings, 0 replies; 15+ messages in thread
From: Daniel Borkmann @ 2026-07-10 12:30 UTC (permalink / raw)
To: Mike Rapoport
Cc: Alexei Starovoitov, Andrii Nakryiko, Andy Lutomirski,
Borislav Petkov, Dave Hansen, Eduard Zingerman, Ingo Molnar,
Kumar Kartikeya Dwivedi, Peter Zijlstra, Song Liu,
Thomas Gleixner, Emil Tsalapatis, Jiri Olsa, John Fastabend,
Martin KaFai Lau, H. Peter Anvin, Yonghong Song, bpf,
linux-kernel, x86
Hi Mike,
On 7/9/26 2:55 PM, Mike Rapoport wrote:
> On Thu, Jul 09, 2026 at 02:12:04PM +0200, Daniel Borkmann wrote:
>> On 7/9/26 10:03 AM, Mike Rapoport wrote:
>>> Gentle ping
>>>
>>> On Fri, Jun 26, 2026 at 09:42:27PM +0300, Mike Rapoport (Microsoft) wrote:
>>>> Hi,
>>>>
>>>> BPF allocations of executable memory on x86 are essentially read-only. Most
>>>> paths that call bpf_jit_alloc_exec() immediately make it ROX with
>>>> set_memory_rox().
>>>>
>>>> The code generation, at least on x86, uses separately allocated writable
>>>> buffers and then updates the actual text memory with text_poke().
>>>>
>>>> These patches do several small adjustments to how BPF allocates executable
>>>> memory and enable EXECMEM_ROX_CACHE for BPF allocations on x86.
>>
>> I think there was an open Q from Alexei wrt the sashiko reports [0] and
>> whether you could address them. Once done, please resend to bpf list.
>
> Thanks for the link!
> I'm not subscribed to bpf@ and it took me a few minutes to realize why I
> don't see this in my inbox.
Ok, np. Despite the sashiko false positives, could you pls resend against
latest bpf-next, so your set can run through the upstream BPF CI?
Thanks,
Daniel
^ permalink raw reply [flat|nested] 15+ messages in thread