Skip to content

Commit 64c7d05

Browse files
committed
netstacklat: Protect out-of-order tracking with spinlocks
Currently there is no synchronization between the updates and checks of the per-socket ooo-range used to filter out potentially HOL-blocked measurements. While the kernel holds a socket lock when the ooo-range is updated in tcp_data_queue_ofo(), the kernel does not seem to hold a socket lock by the time we check the ooo-range in tcp_recv_timestamp(). To prevent the check of the ooo-range from reading the ooo-range while it's concurrently updated (resulting in a potentially inconsistent state), add a bpf_spin_lock to protect updates and checks of the ooo-range. Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
1 parent 8798bdf commit 64c7d05

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

netstacklat/netstacklat.bpf.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct sk_buff___old {
4343
} __attribute__((preserve_access_index));
4444

4545
struct tcp_sock_ooo_range {
46+
struct bpf_spin_lock lock;
4647
u32 ooo_seq_end;
4748
/* indicates if ooo_seq_end is still valid (as 0 can be valid seq) */
4849
bool active;
@@ -363,13 +364,15 @@ static void tcp_update_ooo_range(struct sock *sk, struct sk_buff *skb)
363364
if (!tp_ooo_range)
364365
return;
365366

367+
bpf_spin_lock(&tp_ooo_range->lock);
366368
if (tp_ooo_range->active) {
367369
if (u32_lt(tp_ooo_range->ooo_seq_end, TCP_SKB_CB(skb)->end_seq))
368370
tp_ooo_range->ooo_seq_end = TCP_SKB_CB(skb)->end_seq;
369371
} else {
370372
tp_ooo_range->ooo_seq_end = TCP_SKB_CB(skb)->end_seq;
371373
tp_ooo_range->active = true;
372374
}
375+
bpf_spin_unlock(&tp_ooo_range->lock);
373376

374377
}
375378

@@ -378,16 +381,14 @@ static bool tcp_read_in_ooo_range(struct sock *sk)
378381
struct tcp_sock_ooo_range *tp_ooo_range;
379382
struct tcp_sock *tp = tcp_sk(sk);
380383
u32 last_read_seq;
384+
bool ret;
381385
int err;
382386

383387
tp_ooo_range = bpf_sk_storage_get(&netstack_tcp_ooo_range, sk, NULL, 0);
384388
if (!tp_ooo_range)
385389
/* no recorded ooo-range for sock, so cannot be in ooo-range */
386390
return false;
387391

388-
if (!tp_ooo_range->active)
389-
return false;
390-
391392
err = bpf_core_read(&last_read_seq, sizeof(last_read_seq), &tp->copied_seq);
392393
if (err) {
393394
/*
@@ -400,12 +401,20 @@ static bool tcp_read_in_ooo_range(struct sock *sk)
400401
return false;
401402
}
402403

403-
if (u32_lt(tp_ooo_range->ooo_seq_end, last_read_seq)) {
404-
tp_ooo_range->active = false;
405-
return false;
406-
} else {
407-
return true;
404+
bpf_spin_lock(&tp_ooo_range->lock);
405+
if (!tp_ooo_range->active) {
406+
ret = false;
407+
} else {
408+
if (u32_lt(tp_ooo_range->ooo_seq_end, last_read_seq)) {
409+
tp_ooo_range->active = false;
410+
ret = false;
411+
} else {
412+
ret = true;
413+
}
408414
}
415+
416+
bpf_spin_unlock(&tp_ooo_range->lock);
417+
return ret;
409418
}
410419

411420
SEC("fentry/ip_rcv_core")

0 commit comments

Comments
 (0)