tcp: annotate data-races around tw->tw_ts_recent and tw->tw_ts_recent_stamp
JIRA: https://issues.redhat.com/browse/RHEL-9279 Upstream Status: commit 69e0b33a7fce CS9 lacks both support for TCP Authentication option and usec resolution for TCP timestamps. Both features are out of scope, so do needed context fixups. This change was added to reduce conflicts in the followup patch. commit 69e0b33a7fce4d96649b9fa32e56b696921aa48e Author: Eric Dumazet <edumazet@google.com> Date: Mon Jun 3 15:51:06 2024 +0000 tcp: annotate data-races around tw->tw_ts_recent and tw->tw_ts_recent_stamp These fields can be read and written locklessly, add annotations around these minor races. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> Conflicts: net/ipv4/tcp_ipv4.c net/ipv6/tcp_ipv6.c Signed-off-by: Florian Westphal <fwestpha@redhat.com>
This commit is contained in:
parent
903e29dd1d
commit
23f780623d
|
@ -111,6 +111,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
|||
const struct inet_timewait_sock *tw = inet_twsk(sktw);
|
||||
const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
int ts_recent_stamp;
|
||||
|
||||
if (reuse == 2) {
|
||||
/* Still does not detect *everything* that goes through
|
||||
|
@ -149,9 +150,10 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
|||
If TW bucket has been already destroyed we fall back to VJ's scheme
|
||||
and use initial timestamp retrieved from peer table.
|
||||
*/
|
||||
if (tcptw->tw_ts_recent_stamp &&
|
||||
ts_recent_stamp = READ_ONCE(tcptw->tw_ts_recent_stamp);
|
||||
if (ts_recent_stamp &&
|
||||
(!twp || (reuse && time_after32(ktime_get_seconds(),
|
||||
tcptw->tw_ts_recent_stamp)))) {
|
||||
ts_recent_stamp)))) {
|
||||
/* inet_twsk_hashdance() sets sk_refcnt after putting twsk
|
||||
* and releasing the bucket lock.
|
||||
*/
|
||||
|
@ -175,8 +177,8 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
|||
if (!seq)
|
||||
seq = 1;
|
||||
WRITE_ONCE(tp->write_seq, seq);
|
||||
tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
|
||||
tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
|
||||
tp->rx_opt.ts_recent = READ_ONCE(tcptw->tw_ts_recent);
|
||||
tp->rx_opt.ts_recent_stamp = ts_recent_stamp;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -946,7 +948,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
|
|||
tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
|
||||
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
|
||||
tcp_time_stamp_raw() + tcptw->tw_ts_offset,
|
||||
tcptw->tw_ts_recent,
|
||||
READ_ONCE(tcptw->tw_ts_recent),
|
||||
tw->tw_bound_dev_if,
|
||||
tcp_twsk_md5_key(tcptw),
|
||||
tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0,
|
||||
|
|
|
@ -96,16 +96,18 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
|
|||
struct tcp_options_received tmp_opt;
|
||||
struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
|
||||
bool paws_reject = false;
|
||||
int ts_recent_stamp;
|
||||
|
||||
tmp_opt.saw_tstamp = 0;
|
||||
if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
|
||||
ts_recent_stamp = READ_ONCE(tcptw->tw_ts_recent_stamp);
|
||||
if (th->doff > (sizeof(*th) >> 2) && ts_recent_stamp) {
|
||||
tcp_parse_options(twsk_net(tw), skb, &tmp_opt, 0, NULL);
|
||||
|
||||
if (tmp_opt.saw_tstamp) {
|
||||
if (tmp_opt.rcv_tsecr)
|
||||
tmp_opt.rcv_tsecr -= tcptw->tw_ts_offset;
|
||||
tmp_opt.ts_recent = tcptw->tw_ts_recent;
|
||||
tmp_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
|
||||
tmp_opt.ts_recent = READ_ONCE(tcptw->tw_ts_recent);
|
||||
tmp_opt.ts_recent_stamp = ts_recent_stamp;
|
||||
paws_reject = tcp_paws_reject(&tmp_opt, th->rst);
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +148,10 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
|
|||
tw->tw_substate = TCP_TIME_WAIT;
|
||||
tcptw->tw_rcv_nxt = TCP_SKB_CB(skb)->end_seq;
|
||||
if (tmp_opt.saw_tstamp) {
|
||||
tcptw->tw_ts_recent_stamp = ktime_get_seconds();
|
||||
tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
|
||||
WRITE_ONCE(tcptw->tw_ts_recent_stamp,
|
||||
ktime_get_seconds());
|
||||
WRITE_ONCE(tcptw->tw_ts_recent,
|
||||
tmp_opt.rcv_tsval);
|
||||
}
|
||||
|
||||
inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
|
||||
|
@ -191,8 +195,10 @@ kill:
|
|||
}
|
||||
|
||||
if (tmp_opt.saw_tstamp) {
|
||||
tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
|
||||
tcptw->tw_ts_recent_stamp = ktime_get_seconds();
|
||||
WRITE_ONCE(tcptw->tw_ts_recent,
|
||||
tmp_opt.rcv_tsval);
|
||||
WRITE_ONCE(tcptw->tw_ts_recent_stamp,
|
||||
ktime_get_seconds());
|
||||
}
|
||||
|
||||
inet_twsk_put(tw);
|
||||
|
@ -219,7 +225,7 @@ kill:
|
|||
if (th->syn && !th->rst && !th->ack && !paws_reject &&
|
||||
(after(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt) ||
|
||||
(tmp_opt.saw_tstamp &&
|
||||
(s32)(tcptw->tw_ts_recent - tmp_opt.rcv_tsval) < 0))) {
|
||||
(s32)(READ_ONCE(tcptw->tw_ts_recent) - tmp_opt.rcv_tsval) < 0))) {
|
||||
u32 isn = tcptw->tw_snd_nxt + 65535 + 2;
|
||||
if (isn == 0)
|
||||
isn++;
|
||||
|
|
|
@ -1094,7 +1094,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
|
|||
tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
|
||||
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
|
||||
tcp_time_stamp_raw() + tcptw->tw_ts_offset,
|
||||
tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw),
|
||||
READ_ONCE(tcptw->tw_ts_recent), tw->tw_bound_dev_if,
|
||||
tcp_twsk_md5_key(tcptw),
|
||||
tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel), tw->tw_priority,
|
||||
tw->tw_txhash);
|
||||
|
||||
|
|
Loading…
Reference in New Issue