Skip to content

Commit 7b6a893

Browse files
edumazetdavem330
authored andcommitted
tcp: annotate races around tp->urg_data
tcp_poll() and tcp_ioctl() are reading tp->urg_data without socket lock owned. Also, it is faster to first check tp->urg_data in tcp_poll(), then tp->urg_seq == tp->copied_seq, because tp->urg_seq is located in a different/cold cache line. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0307a0b commit 7b6a893

File tree

2 files changed

+11
-10
lines changed

2 files changed

+11
-10
lines changed

net/ipv4/tcp.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -545,10 +545,11 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
545545
if (state != TCP_SYN_SENT &&
546546
(state != TCP_SYN_RECV || rcu_access_pointer(tp->fastopen_rsk))) {
547547
int target = sock_rcvlowat(sk, 0, INT_MAX);
548+
u16 urg_data = READ_ONCE(tp->urg_data);
548549

549-
if (READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq) &&
550-
!sock_flag(sk, SOCK_URGINLINE) &&
551-
tp->urg_data)
550+
if (urg_data &&
551+
READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq) &&
552+
!sock_flag(sk, SOCK_URGINLINE))
552553
target++;
553554

554555
if (tcp_stream_is_readable(sk, target))
@@ -573,7 +574,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
573574
} else
574575
mask |= EPOLLOUT | EPOLLWRNORM;
575576

576-
if (tp->urg_data & TCP_URG_VALID)
577+
if (urg_data & TCP_URG_VALID)
577578
mask |= EPOLLPRI;
578579
} else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
579580
/* Active TCP fastopen socket with defer_connect
@@ -607,7 +608,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
607608
unlock_sock_fast(sk, slow);
608609
break;
609610
case SIOCATMARK:
610-
answ = tp->urg_data &&
611+
answ = READ_ONCE(tp->urg_data) &&
611612
READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq);
612613
break;
613614
case SIOCOUTQ:
@@ -1465,7 +1466,7 @@ static int tcp_recv_urg(struct sock *sk, struct msghdr *msg, int len, int flags)
14651466
char c = tp->urg_data;
14661467

14671468
if (!(flags & MSG_PEEK))
1468-
tp->urg_data = TCP_URG_READ;
1469+
WRITE_ONCE(tp->urg_data, TCP_URG_READ);
14691470

14701471
/* Read urgent data. */
14711472
msg->msg_flags |= MSG_OOB;
@@ -2465,7 +2466,7 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
24652466

24662467
skip_copy:
24672468
if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) {
2468-
tp->urg_data = 0;
2469+
WRITE_ONCE(tp->urg_data, 0);
24692470
tcp_fast_path_check(sk);
24702471
}
24712472

@@ -2959,7 +2960,7 @@ int tcp_disconnect(struct sock *sk, int flags)
29592960
tcp_clear_xmit_timers(sk);
29602961
__skb_queue_purge(&sk->sk_receive_queue);
29612962
WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
2962-
tp->urg_data = 0;
2963+
WRITE_ONCE(tp->urg_data, 0);
29632964
tcp_write_queue_purge(sk);
29642965
tcp_fastopen_active_disable_ofo_check(sk);
29652966
skb_rbtree_purge(&tp->out_of_order_queue);

net/ipv4/tcp_input.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5591,7 +5591,7 @@ static void tcp_check_urg(struct sock *sk, const struct tcphdr *th)
55915591
}
55925592
}
55935593

5594-
tp->urg_data = TCP_URG_NOTYET;
5594+
WRITE_ONCE(tp->urg_data, TCP_URG_NOTYET);
55955595
WRITE_ONCE(tp->urg_seq, ptr);
55965596

55975597
/* Disable header prediction. */
@@ -5617,7 +5617,7 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t
56175617
u8 tmp;
56185618
if (skb_copy_bits(skb, ptr, &tmp, 1))
56195619
BUG();
5620-
tp->urg_data = TCP_URG_VALID | tmp;
5620+
WRITE_ONCE(tp->urg_data, TCP_URG_VALID | tmp);
56215621
if (!sock_flag(sk, SOCK_DEAD))
56225622
sk->sk_data_ready(sk);
56235623
}

0 commit comments

Comments
 (0)