[PATCH bpf-next v2 3/5] bpf: alloc_prog_pack(): skip ROX management for already ROX memory

From: Mike Rapoport (Microsoft)

Date: Sat Jul 11 2026 - 05:45:22 EST


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@xxxxxxxxxx>
---
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 fc75625dc951..1b89c18cf246 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -916,6 +916,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;
@@ -927,16 +932,18 @@ 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);

if (static_branch_unlikely(&bpf_pred_flush_enabled))
pack->arch_flush_needed = true;
- 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;

@@ -965,7 +972,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
pr_warn_once("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n");
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