Skip to content

Commit 2e47575

Browse files
teckiKernel Patches Daemon
authored andcommitted
bpf: tail calls do not modify packet data
The bpf verifier checks whether packet data is modified within a helper function, and if so invalidates the pointer to that data. Currently the verifier always invalidates if the helper function called is a tail call, as it cannot tell whether the called function does or does not modify the packet data. However, in this case, the fact that the packet might be modified is irrelevant in the code following the helper call, as the tail call only returns if there is nothing to execute, otherwise the calling (sub)program will return directly after the tail call finished. So it is this (sub)program for which the pointer to packet data needs to be invalidated. Fortunately, there are already two distinct points in the code for invalidating packet pointers directly after a helper call, and for entire (sub)programs. This commit assures that the pointer is only invalidated in the relevant case. Note that this is a regression bug: taking care of tail calls only became necessary when subprograms were introduced, before commit 1a4607f using a packet pointer after a tail call was working fine, as it should. Fixes: 1a4607f ("bpf: consider that tail calls invalidate packet pointers") Signed-off-by: Martin Teichmann <martin.teichmann@xfel.eu>
1 parent 3a9d54a commit 2e47575

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

kernel/bpf/verifier.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17827,7 +17827,8 @@ static int visit_insn(int t, struct bpf_verifier_env *env)
1782717827
*/
1782817828
if (ret == 0 && fp->might_sleep)
1782917829
mark_subprog_might_sleep(env, t);
17830-
if (bpf_helper_changes_pkt_data(insn->imm))
17830+
if (bpf_helper_changes_pkt_data(insn->imm)
17831+
|| insn->imm == BPF_FUNC_tail_call)
1783117832
mark_subprog_changes_pkt_data(env, t);
1783217833
} else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
1783317834
struct bpf_kfunc_call_arg_meta meta;

net/core/filter.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8032,8 +8032,6 @@ bool bpf_helper_changes_pkt_data(enum bpf_func_id func_id)
80328032
case BPF_FUNC_xdp_adjust_head:
80338033
case BPF_FUNC_xdp_adjust_meta:
80348034
case BPF_FUNC_xdp_adjust_tail:
8035-
/* tail-called program could call any of the above */
8036-
case BPF_FUNC_tail_call:
80378035
return true;
80388036
default:
80398037
return false;

tools/testing/selftests/bpf/progs/verifier_sock.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,10 +1117,10 @@ int tail_call(struct __sk_buff *sk)
11171117
return 0;
11181118
}
11191119

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

@@ -1131,4 +1131,18 @@ int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
11311131
return TCX_PASS;
11321132
}
11331133

1134+
/* Direct tail calls do not invalidate packet pointers. */
1135+
SEC("tc")
1136+
__success
1137+
int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
1138+
{
1139+
int *p = (void *)(long)sk->data;
1140+
1141+
if ((void *)(p + 1) > (void *)(long)sk->data_end)
1142+
return TCX_DROP;
1143+
bpf_tail_call_static(sk, &jmp_table, 0);
1144+
*p = 42; /* this is NOT unsafe: tail calls don't return */
1145+
return TCX_PASS;
1146+
}
1147+
11341148
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)