An insn array records, per entry, the xlated offset, the jitted offset and a jitted target pointer in ips[]. bpf_insn_array_init() runs when the map is bound to a program and resets only xlated_off; the jitted offset and the ips[] pointer are left as the previous owner set them. A program can be verified and JITed and only then fail to load (e.g. bpf_check_tail_call()). By that point bpf_prog_update_insn_ptrs() has already filled ips[] with pointers into that program's JIT image. Thus, the map is handed back for reuse with the stale pointers intact. If the next program reuses the map, the stale pointer survived the now active program's jump table, pointing into the previous, freed image. Fix by resetting the jitted offset and the ips[] pointer alongside the xlated offset. Fixes: b4ce5923e780 ("bpf, x86: add new map type: instructions array") Reported-by: Sandipan Roy Reported-by: James Burton Signed-off-by: Daniel Borkmann Acked-by: Anton Protopopov --- kernel/bpf/bpf_insn_array.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/bpf_insn_array.c b/kernel/bpf/bpf_insn_array.c index a2f84afe6f7c..5874abd1f743 100644 --- a/kernel/bpf/bpf_insn_array.c +++ b/kernel/bpf/bpf_insn_array.c @@ -199,12 +199,16 @@ int bpf_insn_array_init(struct bpf_map *map, const struct bpf_prog *prog) return -EBUSY; /* - * Reset all the map indexes to the original values. This is needed, - * e.g., when a replay of verification with different log level should - * be performed. + * Reset the map to its pre-verification state. The xlated and jitted + * offsets and the jitted target pointers are recomputed by the verifier + * and the JIT for this program, so any values left by a previous owner + * must be cleared here. */ - for (i = 0; i < map->max_entries; i++) + for (i = 0; i < map->max_entries; i++) { values[i].xlated_off = values[i].orig_off; + values[i].jitted_off = 0; + insn_array->ips[i] = 0; + } return 0; } -- 2.43.0