Skip to content

Commit a32aee8

Browse files
mrpreMartin KaFai Lau
authored andcommitted
bpf: fix filed access without lock
The tcp_bpf_recvmsg_parser() function, running in user context, retrieves seq_copied from tcp_sk without holding the socket lock, and stores it in a local variable seq. However, the softirq context can modify tcp_sk->seq_copied concurrently, for example, n tcp_read_sock(). As a result, the seq value is stale when it is assigned back to tcp_sk->copied_seq at the end of tcp_bpf_recvmsg_parser(), leading to incorrect behavior. Due to concurrency, the copied_seq field in tcp_bpf_recvmsg_parser() might be set to an incorrect value (less than the actual copied_seq) at the end of function: 'WRITE_ONCE(tcp->copied_seq, seq)'. This causes the 'offset' to be negative in tcp_read_sock()->tcp_recv_skb() when processing new incoming packets (sk->copied_seq - skb->seq becomes less than 0), and all subsequent packets will be dropped. Signed-off-by: Jiayuan Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]>
1 parent 740be3b commit a32aee8

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

net/ipv4/tcp_bpf.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,11 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
221221
int flags,
222222
int *addr_len)
223223
{
224-
struct tcp_sock *tcp = tcp_sk(sk);
225224
int peek = flags & MSG_PEEK;
226-
u32 seq = tcp->copied_seq;
227225
struct sk_psock *psock;
226+
struct tcp_sock *tcp;
228227
int copied = 0;
228+
u32 seq;
229229

230230
if (unlikely(flags & MSG_ERRQUEUE))
231231
return inet_recv_error(sk, msg, len, addr_len);
@@ -238,7 +238,8 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
238238
return tcp_recvmsg(sk, msg, len, flags, addr_len);
239239

240240
lock_sock(sk);
241-
241+
tcp = tcp_sk(sk);
242+
seq = tcp->copied_seq;
242243
/* We may have received data on the sk_receive_queue pre-accept and
243244
* then we can not use read_skb in this context because we haven't
244245
* assigned a sk_socket yet so have no link to the ops. The work-around

0 commit comments

Comments
 (0)