Hi, While reviewing the BPF subsystem's recently introduced indirect jump support (BPF_MAP_TYPE_INSN_ARRAY / `gotox`), I found a verifier soundness bug: a program that passes verification can, at run time, execute a jump through a NULL (or stale) code pointer, causing a kernel oops/panic. I believe this affects all kernels since the feature was added. The core problem is the interaction between post-verification instruction removal and the insn_array jump table: - `bpf_opt_remove_nops()` removes instructions byte-equal to `JA +0` even when they are targets of a verified `gotox`, because it does not check `insn_aux_data[].indirect_target`. - When such a target is removed, `bpf_insn_array_adjust_after_remove()` marks the map entries `INSN_DELETED`, the JIT skips them and leaves `ips[]` NULL (or stale), and `bpf_insn_array_ready()` skips validation of `INSN_DELETED` entries. The result is that a verified `gotox rX` can execute `jmp *rX` with `rX == NULL`. I reproduced this on the current mainline (v7.3-rc1, commit bc35965f6940) with a minimal BPF program: the load succeeds and running it produces "BUG: kernel NULL pointer dereference" with "#PF: supervisor instruction fetch" at RIP 0x0. A map previously bound to another program can instead leave a stale pointer into a freed JIT image (latent use-after-free). While validating the fix I also noticed a related lifecycle bug: `bpf_insn_array_release()` is only invoked from verifier error paths, so after a successful load the map remains permanently "used" (the map can never be bound to another program, failing with -EBUSY) and `ips[]` keeps pointing into the freed jitted image of the unloaded program. The attached patch fixes all of these: 1. Never remove indirect jump targets in `bpf_opt_remove_nops()`, and hard-guarantee it in `verifier_remove_insns()` by rejecting any removal of an instruction flagged as an indirect jump target. 2. Turn the final safety gate in `bpf_insn_array_ready()` into a hard rejection of `INSN_DELETED` entries instead of silently skipping them. 3. Call `bpf_insn_array_release()` from `__bpf_free_used_maps()` when the bound program is freed, and clear the stale per-entry state (`xlated_off`, `ips[]`) there so a subsequent bind cannot inherit dangling pointers. Thanks, Sandipan Roy Senior Product Security Engineer, Red Hat