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

bpf: Fix potential array overflow in bpf_trampoline_get_progs()

The cnt value in the 'cnt >= BPF_MAX_TRAMP_PROGS' check does not
include BPF_TRAMP_MODIFY_RETURN bpf programs, so the number of
the attached BPF_TRAMP_MODIFY_RETURN bpf programs in a trampoline
can exceed BPF_MAX_TRAMP_PROGS.

When this happens, the assignment '*progs++ = aux->prog' in
bpf_trampoline_get_progs() will cause progs array overflow as the
progs field in the bpf_tramp_progs struct can only hold at most
BPF_MAX_TRAMP_PROGS bpf programs.

Fixes: 88fd9e5352fe ("bpf: Refactor trampoline update code")
Signed-off-by: Yuntao Wang <ytcoode@gmail.com>
Link: https://lore.kernel.org/r/20220430130803.210624-1-ytcoode@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yuntao Wang and committed by
Alexei Starovoitov
a2aa95b7 5790a2fe

+12 -6
+12 -6
kernel/bpf/trampoline.c
··· 415 415 enum bpf_tramp_prog_type kind; 416 416 struct bpf_tramp_link *link_exiting; 417 417 int err = 0; 418 - int cnt; 418 + int cnt = 0, i; 419 419 420 420 kind = bpf_attach_type_to_tramp(link->link.prog); 421 421 mutex_lock(&tr->mutex); ··· 426 426 err = -EBUSY; 427 427 goto out; 428 428 } 429 - cnt = tr->progs_cnt[BPF_TRAMP_FENTRY] + tr->progs_cnt[BPF_TRAMP_FEXIT]; 429 + 430 + for (i = 0; i < BPF_TRAMP_MAX; i++) 431 + cnt += tr->progs_cnt[i]; 432 + 430 433 if (kind == BPF_TRAMP_REPLACE) { 431 434 /* Cannot attach extension if fentry/fexit are in use. */ 432 435 if (cnt) { ··· 515 512 516 513 void bpf_trampoline_put(struct bpf_trampoline *tr) 517 514 { 515 + int i; 516 + 518 517 if (!tr) 519 518 return; 520 519 mutex_lock(&trampoline_mutex); 521 520 if (!refcount_dec_and_test(&tr->refcnt)) 522 521 goto out; 523 522 WARN_ON_ONCE(mutex_is_locked(&tr->mutex)); 524 - if (WARN_ON_ONCE(!hlist_empty(&tr->progs_hlist[BPF_TRAMP_FENTRY]))) 525 - goto out; 526 - if (WARN_ON_ONCE(!hlist_empty(&tr->progs_hlist[BPF_TRAMP_FEXIT]))) 527 - goto out; 523 + 524 + for (i = 0; i < BPF_TRAMP_MAX; i++) 525 + if (WARN_ON_ONCE(!hlist_empty(&tr->progs_hlist[i]))) 526 + goto out; 527 + 528 528 /* This code will be executed even when the last bpf_tramp_image 529 529 * is alive. All progs are detached from the trampoline and the 530 530 * trampoline image is patched with jmp into epilogue to skip