Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -17827,7 +17827,8 @@ static int visit_insn(int t, struct bpf_verifier_env *env)
*/
if (ret == 0 && fp->might_sleep)
mark_subprog_might_sleep(env, t);
if (bpf_helper_changes_pkt_data(insn->imm))
if (bpf_helper_changes_pkt_data(insn->imm)
|| insn->imm == BPF_FUNC_tail_call)
mark_subprog_changes_pkt_data(env, t);
} else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
struct bpf_kfunc_call_arg_meta meta;
Expand Down
2 changes: 0 additions & 2 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -8032,8 +8032,6 @@ bool bpf_helper_changes_pkt_data(enum bpf_func_id func_id)
case BPF_FUNC_xdp_adjust_head:
case BPF_FUNC_xdp_adjust_meta:
case BPF_FUNC_xdp_adjust_tail:
/* tail-called program could call any of the above */
case BPF_FUNC_tail_call:
return true;
default:
return false;
Expand Down
18 changes: 16 additions & 2 deletions tools/testing/selftests/bpf/progs/verifier_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,10 +1117,10 @@ int tail_call(struct __sk_buff *sk)
return 0;
}

/* Tail calls invalidate packet pointers. */
/* Tail calls in sub-programs invalidate packet pointers. */
SEC("tc")
__failure __msg("invalid mem access")
int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
int invalidate_pkt_pointers_by_indirect_tail_call(struct __sk_buff *sk)
{
int *p = (void *)(long)sk->data;

Expand All @@ -1131,4 +1131,18 @@ int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
return TCX_PASS;
}

/* Direct tail calls do not invalidate packet pointers. */
SEC("tc")
__success
int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
{
int *p = (void *)(long)sk->data;

if ((void *)(p + 1) > (void *)(long)sk->data_end)
return TCX_DROP;
bpf_tail_call_static(sk, &jmp_table, 0);
*p = 42; /* this is NOT unsafe: tail calls don't return */
return TCX_PASS;
}

char _license[] SEC("license") = "GPL";
Loading