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

bpf: consider that tail calls invalidate packet pointers

Tail-called programs could execute any of the helpers that invalidate
packet pointers. Hence, conservatively assume that each tail call
invalidates packet pointers.

Making the change in bpf_helper_changes_pkt_data() automatically makes
use of check_cfg() logic that computes 'changes_pkt_data' effect for
global sub-programs, such that the following program could be
rejected:

int tail_call(struct __sk_buff *sk)
{
bpf_tail_call_static(sk, &jmp_table, 0);
return 0;
}

SEC("tc")
int not_safe(struct __sk_buff *sk)
{
int *p = (void *)(long)sk->data;
... make p valid ...
tail_call(sk);
*p = 42; /* this is unsafe */
...
}

The tc_bpf2bpf.c:subprog_tc() needs change: mark it as a function that
can invalidate packet pointers. Otherwise, it can't be freplaced with
tailcall_freplace.c:entry_freplace() that does a tail call.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20241210041100.1898468-8-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
1a4607ff 89ff4089

+4
+2
net/core/filter.c
··· 7924 7924 case BPF_FUNC_xdp_adjust_head: 7925 7925 case BPF_FUNC_xdp_adjust_meta: 7926 7926 case BPF_FUNC_xdp_adjust_tail: 7927 + /* tail-called program could call any of the above */ 7928 + case BPF_FUNC_tail_call: 7927 7929 return true; 7928 7930 default: 7929 7931 return false;
+2
tools/testing/selftests/bpf/progs/tc_bpf2bpf.c
··· 11 11 12 12 __sink(skb); 13 13 __sink(ret); 14 + /* let verifier know that 'subprog_tc' can change pointers to skb->data */ 15 + bpf_skb_change_proto(skb, 0, 0); 14 16 return ret; 15 17 } 16 18