Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: support instructions arrays with constants blinding

When bpf_jit_harden is enabled, all constants in the BPF code are
blinded to prevent JIT spraying attacks. This happens during JIT
phase. Adjust all the related instruction arrays accordingly.

Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20251105090410.1250500-6-a.s.protopopov@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Anton Protopopov and committed by
Alexei Starovoitov
30ec0ec0 218edd6d

+30 -1
+20
kernel/bpf/core.c
··· 1450 1450 bpf_prog_clone_free(fp_other); 1451 1451 } 1452 1452 1453 + static void adjust_insn_arrays(struct bpf_prog *prog, u32 off, u32 len) 1454 + { 1455 + #ifdef CONFIG_BPF_SYSCALL 1456 + struct bpf_map *map; 1457 + int i; 1458 + 1459 + if (len <= 1) 1460 + return; 1461 + 1462 + for (i = 0; i < prog->aux->used_map_cnt; i++) { 1463 + map = prog->aux->used_maps[i]; 1464 + if (map->map_type == BPF_MAP_TYPE_INSN_ARRAY) 1465 + bpf_insn_array_adjust(map, off, len); 1466 + } 1467 + #endif 1468 + } 1469 + 1453 1470 struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog) 1454 1471 { 1455 1472 struct bpf_insn insn_buff[16], aux[2]; ··· 1521 1504 1522 1505 clone = tmp; 1523 1506 insn_delta = rewritten - 1; 1507 + 1508 + /* Instructions arrays must be updated using absolute xlated offsets */ 1509 + adjust_insn_arrays(clone, prog->aux->subprog_start + i, rewritten); 1524 1510 1525 1511 /* Walk new program and skip insns we just inserted. */ 1526 1512 insn = clone->insnsi + i + insn_delta;
+10 -1
kernel/bpf/verifier.c
··· 21632 21632 struct bpf_insn *insn; 21633 21633 void *old_bpf_func; 21634 21634 int err, num_exentries; 21635 + int old_len, subprog_start_adjustment = 0; 21635 21636 21636 21637 if (env->subprog_cnt <= 1) 21637 21638 return 0; ··· 21707 21706 func[i]->aux->func_idx = i; 21708 21707 /* Below members will be freed only at prog->aux */ 21709 21708 func[i]->aux->btf = prog->aux->btf; 21710 - func[i]->aux->subprog_start = subprog_start; 21709 + func[i]->aux->subprog_start = subprog_start + subprog_start_adjustment; 21711 21710 func[i]->aux->func_info = prog->aux->func_info; 21712 21711 func[i]->aux->func_info_cnt = prog->aux->func_info_cnt; 21713 21712 func[i]->aux->poke_tab = prog->aux->poke_tab; ··· 21763 21762 func[i]->aux->might_sleep = env->subprog_info[i].might_sleep; 21764 21763 if (!i) 21765 21764 func[i]->aux->exception_boundary = env->seen_exception; 21765 + 21766 + /* 21767 + * To properly pass the absolute subprog start to jit 21768 + * all instruction adjustments should be accumulated 21769 + */ 21770 + old_len = func[i]->len; 21766 21771 func[i] = bpf_int_jit_compile(func[i]); 21772 + subprog_start_adjustment += func[i]->len - old_len; 21773 + 21767 21774 if (!func[i]->jited) { 21768 21775 err = -ENOTSUPP; 21769 21776 goto out_free;