Skip to content

Commit f0e77c5

Browse files
committed
Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Pull bpf fixes from Alexei Starovoitov: - Fix bpf_throw() and global subprog combination (Kumar Kartikeya Dwivedi) - Fix out of bounds access in BPF interpreter (Yazhou Tang) - Fix potential out of bounds access in inner per-cpu array map (Guannan Wang) - Reject NULL data/sig in bpf_verify_pkcs7_signature (KP Singh) * tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: libbpf: fix off-by-one in emit_signature_match jump offset bpf: Reject NULL data/sig in bpf_verify_pkcs7_signature selftests/bpf: Cover global subprog exception leaks bpf: Check global subprog exception paths bpf: make bpf_session_is_return() reference optional bpf: Use array_map_meta_equal for percpu array inner map replacement selftests/bpf: Add test for large offset bpf-to-bpf call bpf: Fix s16 truncation for large bpf-to-bpf call offsets bpf: Fix out-of-bounds read in bpf_patch_call_args()
2 parents 4cbfe45 + 7dd6256 commit f0e77c5

16 files changed

Lines changed: 251 additions & 27 deletions

File tree

include/linux/bpf.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2917,7 +2917,13 @@ int bpf_check_uarg_tail_zero(bpfptr_t uaddr, size_t expected_size,
29172917
int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size);
29182918

29192919
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
2920-
void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
2920+
int bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
2921+
s32 bpf_call_args_imm(s16 idx);
2922+
#else
2923+
static inline s32 bpf_call_args_imm(s16 idx)
2924+
{
2925+
return 0;
2926+
}
29212927
#endif
29222928

29232929
struct btf *bpf_get_btf_vmlinux(void);

include/linux/bpf_verifier.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ struct bpf_subprog_info {
729729
*/
730730
s16 fastcall_stack_off;
731731
bool has_tail_call: 1;
732+
bool might_throw: 1;
732733
bool tail_call_reachable: 1;
733734
bool has_ld_abs: 1;
734735
bool is_cb: 1;
@@ -1308,6 +1309,7 @@ void bpf_fmt_stack_mask(char *buf, ssize_t buf_sz, u64 stack_mask);
13081309
bool bpf_subprog_is_global(const struct bpf_verifier_env *env, int subprog);
13091310

13101311
int bpf_find_subprog(struct bpf_verifier_env *env, int off);
1312+
bool bpf_is_throw_kfunc(struct bpf_insn *insn);
13111313
int bpf_compute_const_regs(struct bpf_verifier_env *env);
13121314
int bpf_prune_dead_branches(struct bpf_verifier_env *env);
13131315
int bpf_check_cfg(struct bpf_verifier_env *env);

include/linux/filter.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,9 +1151,6 @@ bool sk_filter_charge(struct sock *sk, struct sk_filter *fp);
11511151
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
11521152

11531153
u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
1154-
#define __bpf_call_base_args \
1155-
((u64 (*)(u64, u64, u64, u64, u64, const struct bpf_insn *)) \
1156-
(void *)__bpf_call_base)
11571154

11581155
struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog);
11591156
void bpf_jit_compile(struct bpf_prog *prog);

kernel/bpf/arraymap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ const struct bpf_map_ops array_map_ops = {
827827
};
828828

829829
const struct bpf_map_ops percpu_array_map_ops = {
830-
.map_meta_equal = bpf_map_meta_equal,
830+
.map_meta_equal = array_map_meta_equal,
831831
.map_alloc_check = array_map_alloc_check,
832832
.map_alloc = array_map_alloc,
833833
.map_free = array_map_free,

kernel/bpf/cfg.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,19 @@ static void mark_subprog_might_sleep(struct bpf_verifier_env *env, int off)
6464
subprog->might_sleep = true;
6565
}
6666

67+
static void mark_subprog_might_throw(struct bpf_verifier_env *env, int off)
68+
{
69+
struct bpf_subprog_info *subprog;
70+
71+
subprog = bpf_find_containing_subprog(env, off);
72+
subprog->might_throw = true;
73+
}
74+
6775
/* 't' is an index of a call-site.
6876
* 'w' is a callee entry point.
6977
* Eventually this function would be called when env->cfg.insn_state[w] == EXPLORED.
7078
* Rely on DFS traversal order and absence of recursive calls to guarantee that
71-
* callee's change_pkt_data marks would be correct at that moment.
79+
* callee's effect marks would be correct at that moment.
7280
*/
7381
static void merge_callee_effects(struct bpf_verifier_env *env, int t, int w)
7482
{
@@ -78,6 +86,7 @@ static void merge_callee_effects(struct bpf_verifier_env *env, int t, int w)
7886
callee = bpf_find_containing_subprog(env, w);
7987
caller->changes_pkt_data |= callee->changes_pkt_data;
8088
caller->might_sleep |= callee->might_sleep;
89+
caller->might_throw |= callee->might_throw;
8190
}
8291

8392
enum {
@@ -509,6 +518,8 @@ static int visit_insn(int t, struct bpf_verifier_env *env)
509518
mark_subprog_might_sleep(env, t);
510519
if (ret == 0 && bpf_is_kfunc_pkt_changing(&meta))
511520
mark_subprog_changes_pkt_data(env, t);
521+
if (ret == 0 && bpf_is_throw_kfunc(insn))
522+
mark_subprog_might_throw(env, t);
512523
}
513524
return visit_func_call_insn(t, insns, env, insn->src_reg == BPF_PSEUDO_CALL);
514525

kernel/bpf/core.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,9 @@ static u32 abs_s32(s32 x)
17711771
return x >= 0 ? (u32)x : -(u32)x;
17721772
}
17731773

1774+
static u64 (*interpreters_args[])(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5,
1775+
const struct bpf_insn *insn);
1776+
17741777
/**
17751778
* ___bpf_prog_run - run eBPF program on a given context
17761779
* @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
@@ -2077,10 +2080,9 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
20772080
CONT;
20782081

20792082
JMP_CALL_ARGS:
2080-
BPF_R0 = (__bpf_call_base_args + insn->imm)(BPF_R1, BPF_R2,
2081-
BPF_R3, BPF_R4,
2082-
BPF_R5,
2083-
insn + insn->off + 1);
2083+
BPF_R0 = interpreters_args[insn->off](BPF_R1, BPF_R2, BPF_R3,
2084+
BPF_R4, BPF_R5,
2085+
insn + insn->imm + 1);
20842086
CONT;
20852087

20862088
JMP_TAIL_CALL: {
@@ -2394,13 +2396,22 @@ EVAL4(PROG_NAME_LIST, 416, 448, 480, 512)
23942396
#undef PROG_NAME_LIST
23952397

23962398
#ifdef CONFIG_BPF_SYSCALL
2397-
void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth)
2399+
int bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth)
23982400
{
23992401
stack_depth = max_t(u32, stack_depth, 1);
2400-
insn->off = (s16) insn->imm;
2401-
insn->imm = interpreters_args[(round_up(stack_depth, 32) / 32) - 1] -
2402-
__bpf_call_base_args;
2402+
/* Prevent out-of-bounds read to interpreters_args */
2403+
if (stack_depth > MAX_BPF_STACK)
2404+
return -EINVAL;
2405+
insn->off = (round_up(stack_depth, 32) / 32) - 1;
24032406
insn->code = BPF_JMP | BPF_CALL_ARGS;
2407+
return 0;
2408+
}
2409+
2410+
s32 bpf_call_args_imm(s16 idx)
2411+
{
2412+
if (WARN_ON_ONCE(idx < 0 || idx >= ARRAY_SIZE(interpreters_args)))
2413+
return 0;
2414+
return BPF_CALL_IMM(interpreters_args[idx]);
24042415
}
24052416
#endif
24062417
#endif

kernel/bpf/fixups.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,9 +1250,9 @@ static int jit_subprogs(struct bpf_verifier_env *env)
12501250
}
12511251
if (!bpf_pseudo_call(insn))
12521252
continue;
1253-
insn->off = env->insn_aux_data[i].call_imm;
1254-
subprog = bpf_find_subprog(env, i + insn->off + 1);
1255-
insn->imm = subprog;
1253+
insn->imm = env->insn_aux_data[i].call_imm;
1254+
subprog = bpf_find_subprog(env, i + insn->imm + 1);
1255+
insn->off = subprog;
12561256
}
12571257

12581258
prog->jited = 1;
@@ -1416,7 +1416,12 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
14161416
depth = get_callee_stack_depth(env, insn, i);
14171417
if (depth < 0)
14181418
return depth;
1419-
bpf_patch_call_args(insn, depth);
1419+
err = bpf_patch_call_args(insn, depth);
1420+
if (err) {
1421+
verbose(env, "stack depth %d exceeds interpreter stack depth limit\n",
1422+
depth);
1423+
return err;
1424+
}
14201425
}
14211426
err = 0;
14221427
#endif

kernel/bpf/helpers.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4241,8 +4241,13 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
42414241

42424242
data_len = __bpf_dynptr_size(data_ptr);
42434243
data = __bpf_dynptr_data(data_ptr, data_len);
4244+
if (!data)
4245+
return -EINVAL;
4246+
42444247
sig_len = __bpf_dynptr_size(sig_ptr);
42454248
sig = __bpf_dynptr_data(sig_ptr, sig_len);
4249+
if (!sig)
4250+
return -EINVAL;
42464251

42474252
return verify_pkcs7_signature(data, data_len, sig, sig_len,
42484253
trusted_keyring->key,

kernel/bpf/syscall.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4919,6 +4919,29 @@ static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
49194919
return map;
49204920
}
49214921

4922+
static void prepare_dump_pseudo_call(struct bpf_insn *insn)
4923+
{
4924+
s32 call_off = insn->imm;
4925+
4926+
/*
4927+
* BPF_CALL_ARGS only exists for interpreter fallback.
4928+
* 1. For interpreter (BPF_CALL_ARGS): insn->off is the index of
4929+
* interpreters_args array, so here using bpf_call_args_imm()
4930+
* to get the real address offset.
4931+
* 2. For JIT (BPF_CALL): insn->off is the subprog id.
4932+
*/
4933+
if (insn->code == (BPF_JMP | BPF_CALL_ARGS))
4934+
insn->imm = bpf_call_args_imm(insn->off);
4935+
else
4936+
insn->imm = insn->off;
4937+
4938+
/* Avoid dumping a truncated and misleading pc-relative offset. */
4939+
if (call_off > S16_MAX || call_off < S16_MIN)
4940+
insn->off = 0;
4941+
else
4942+
insn->off = call_off;
4943+
}
4944+
49224945
static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog,
49234946
const struct cred *f_cred)
49244947
{
@@ -4944,6 +4967,9 @@ static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog,
49444967
}
49454968
if (code == (BPF_JMP | BPF_CALL) ||
49464969
code == (BPF_JMP | BPF_CALL_ARGS)) {
4970+
/* Restore the legacy xlated dump layout. */
4971+
if (insns[i].src_reg == BPF_PSEUDO_CALL)
4972+
prepare_dump_pseudo_call(&insns[i]);
49474973
if (code == (BPF_JMP | BPF_CALL_ARGS))
49484974
insns[i].code = BPF_JMP | BPF_CALL;
49494975
if (!bpf_dump_raw_ok(f_cred))

kernel/bpf/verifier.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,6 @@ static bool is_dynptr_ref_function(enum bpf_func_id func_id)
442442
static bool is_sync_callback_calling_kfunc(u32 btf_id);
443443
static bool is_async_callback_calling_kfunc(u32 btf_id);
444444
static bool is_callback_calling_kfunc(u32 btf_id);
445-
static bool is_bpf_throw_kfunc(struct bpf_insn *insn);
446445

447446
static bool is_bpf_wq_set_callback_kfunc(u32 btf_id);
448447
static bool is_task_work_add_kfunc(u32 func_id);
@@ -5405,7 +5404,7 @@ static int check_max_stack_depth_subprog(struct bpf_verifier_env *env, int idx,
54055404
if (bpf_pseudo_kfunc_call(insn + i) && !insn[i].off) {
54065405
bool err = false;
54075406

5408-
if (!is_bpf_throw_kfunc(insn + i))
5407+
if (!bpf_is_throw_kfunc(insn + i))
54095408
continue;
54105409
for (tmp = idx; tmp >= 0 && !err; tmp = dinfo[tmp].caller) {
54115410
if (subprog[tmp].is_cb) {
@@ -9499,6 +9498,9 @@ static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *ins
94999498
return 0;
95009499
}
95019500

9501+
static int process_bpf_exit_full(struct bpf_verifier_env *env,
9502+
bool *do_print_state, bool exception_exit);
9503+
95029504
static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
95039505
int *insn_idx)
95049506
{
@@ -9552,6 +9554,17 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
95529554
caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
95539555
}
95549556

9557+
if (env->subprog_info[subprog].might_throw) {
9558+
struct bpf_verifier_state *branch;
9559+
9560+
branch = push_stack(env, *insn_idx + 1, *insn_idx, false);
9561+
if (IS_ERR(branch)) {
9562+
verbose(env, "failed to push state for global subprog exception path\n");
9563+
return PTR_ERR(branch);
9564+
}
9565+
return process_bpf_exit_full(env, NULL, true);
9566+
}
9567+
95559568
/* continue with next insn after call */
95569569
return 0;
95579570
}
@@ -11263,7 +11276,11 @@ BTF_ID(func, bpf_task_work_schedule_resume)
1126311276
BTF_ID(func, bpf_arena_alloc_pages)
1126411277
BTF_ID(func, bpf_arena_free_pages)
1126511278
BTF_ID(func, bpf_arena_reserve_pages)
11279+
#ifdef CONFIG_BPF_EVENTS
1126611280
BTF_ID(func, bpf_session_is_return)
11281+
#else
11282+
BTF_ID_UNUSED
11283+
#endif
1126711284
BTF_ID(func, bpf_stream_vprintk)
1126811285
BTF_ID(func, bpf_stream_print_stack)
1126911286

@@ -11778,7 +11795,7 @@ static bool is_async_callback_calling_kfunc(u32 btf_id)
1177811795
is_task_work_add_kfunc(btf_id);
1177911796
}
1178011797

11781-
static bool is_bpf_throw_kfunc(struct bpf_insn *insn)
11798+
bool bpf_is_throw_kfunc(struct bpf_insn *insn)
1178211799
{
1178311800
return bpf_pseudo_kfunc_call(insn) && insn->off == 0 &&
1178411801
insn->imm == special_kfunc_list[KF_bpf_throw];
@@ -12968,8 +12985,6 @@ static int check_special_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_ca
1296812985
}
1296912986

1297012987
static int check_return_code(struct bpf_verifier_env *env, int regno, const char *reg_name);
12971-
static int process_bpf_exit_full(struct bpf_verifier_env *env,
12972-
bool *do_print_state, bool exception_exit);
1297312988

1297412989
static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1297512990
int *insn_idx_p)
@@ -13350,7 +13365,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1335013365
if (meta.func_id == special_kfunc_list[KF_bpf_session_cookie])
1335113366
env->prog->call_session_cookie = true;
1335213367

13353-
if (is_bpf_throw_kfunc(insn))
13368+
if (bpf_is_throw_kfunc(insn))
1335413369
return process_bpf_exit_full(env, NULL, true);
1335513370

1335613371
return 0;

0 commit comments

Comments
 (0)