pping: Move NULL-check to compile with LLVM-15

When compiled with LLVM-15 (clang-15 and llc-15), the verifier would
reject the tsmap_cleanup program as reported in #63. To prevent this
add a NULL-check for df_state after the map lookup, to convince the
verifier that we're not trying to dereference a pointer to a map value
before checking for NULL. This fix ensures that the generated bytecode
by LLVM-12 to LLVM-15 passes the verifier (tested on kernel 5.19.3).

There was already an NULL-check for df_state in the (inlined by the
compiler) function fstate_from_dfkey() which checked df_state before
accessing its fields (the specific access that angered the verifier
was df_state->dir2). However, with LLVM-15 the compiler reorders the
operations so that df_state->dir2 is accessed before the NULL-check is
performed, thus upsetting the verifier. This commit removes the
internal NULL-check in fstate_from_dfkey() and instead performs the
relevant NULL-check directly in the tsmap_cleanup prog instead. In all
other places that fstate_from_dfkey() ends up being called there are
already NULL-checks for df_state to enable early returns.

Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
This commit is contained in:
Simon Sundberg
2022-11-08 17:45:34 +01:00
committed by Toke Høiland-Jørgensen
parent 5e5c55772f
commit 9be0a6a8e4

View File

@@ -228,9 +228,6 @@ static void make_dualflow_key(struct network_tuple *key,
static struct flow_state *fstate_from_dfkey(struct dual_flow_state *df_state,
bool is_dfkey)
{
if (!df_state)
return NULL;
return is_dfkey ? &df_state->dir1 : &df_state->dir2;
}
@@ -1127,7 +1124,7 @@ SEC("iter/bpf_map_elem")
int tsmap_cleanup(struct bpf_iter__bpf_map_elem *ctx)
{
struct packet_id local_pid;
struct flow_state *f_state;
struct flow_state *f_state = NULL;
struct dual_flow_state *df_state;
struct network_tuple df_key;
struct packet_id *pid = ctx->key;
@@ -1146,7 +1143,8 @@ int tsmap_cleanup(struct bpf_iter__bpf_map_elem *ctx)
make_dualflow_key(&df_key, &pid->flow);
df_state = bpf_map_lookup_elem(&flow_state, &df_key);
f_state = get_flowstate_from_dualflow(df_state, &pid->flow);
if (df_state)
f_state = get_flowstate_from_dualflow(df_state, &pid->flow);
rtt = f_state ? f_state->srtt : 0;
if ((rtt && now - *timestamp > rtt * TIMESTAMP_RTT_LIFETIME) ||