Patch "rxrpc: Fix data-race warning and potential load/store tearing" has been added to the 6.12-stable tree
gregkh at linuxfoundation.org
gregkh at linuxfoundation.org
Tue Feb 3 06:50:48 PST 2026
This is a note to let you know that I've just added the patch titled
rxrpc: Fix data-race warning and potential load/store tearing
to the 6.12-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
rxrpc-fix-data-race-warning-and-potential-load-store-tearing.patch
and it can be found in the queue-6.12 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.
>From stable+bounces-212715-greg=kroah.com at vger.kernel.org Thu Jan 29 01:11:05 2026
From: Sasha Levin <sashal at kernel.org>
Date: Wed, 28 Jan 2026 19:10:48 -0500
Subject: rxrpc: Fix data-race warning and potential load/store tearing
To: stable at vger.kernel.org
Cc: David Howells <dhowells at redhat.com>, syzbot+6182afad5045e6703b3d at syzkaller.appspotmail.com, Marc Dionne <marc.dionne at auristor.com>, Simon Horman <horms at kernel.org>, linux-afs at lists.infradead.org, stable at kernel.org, Jakub Kicinski <kuba at kernel.org>, Sasha Levin <sashal at kernel.org>
Message-ID: <20260129001048.2933922-1-sashal at kernel.org>
From: David Howells <dhowells at redhat.com>
[ Upstream commit 5d5fe8bcd331f1e34e0943ec7c18432edfcf0e8b ]
Fix the following:
BUG: KCSAN: data-race in rxrpc_peer_keepalive_worker / rxrpc_send_data_packet
which is reporting an issue with the reads and writes to ->last_tx_at in:
conn->peer->last_tx_at = ktime_get_seconds();
and:
keepalive_at = peer->last_tx_at + RXRPC_KEEPALIVE_TIME;
The lockless accesses to these to values aren't actually a problem as the
read only needs an approximate time of last transmission for the purposes
of deciding whether or not the transmission of a keepalive packet is
warranted yet.
Also, as ->last_tx_at is a 64-bit value, tearing can occur on a 32-bit
arch.
Fix both of these by switching to an unsigned int for ->last_tx_at and only
storing the LSW of the time64_t. It can then be reconstructed at need
provided no more than 68 years has elapsed since the last transmission.
Fixes: ace45bec6d77 ("rxrpc: Fix firewall route keepalive")
Reported-by: syzbot+6182afad5045e6703b3d at syzkaller.appspotmail.com
Closes: https://lore.kernel.org/r/695e7cfb.050a0220.1c677c.036b.GAE@google.com/
Signed-off-by: David Howells <dhowells at redhat.com>
cc: Marc Dionne <marc.dionne at auristor.com>
cc: Simon Horman <horms at kernel.org>
cc: linux-afs at lists.infradead.org
cc: stable at kernel.org
Link: https://patch.msgid.link/1107124.1768903985@warthog.procyon.org.uk
Signed-off-by: Jakub Kicinski <kuba at kernel.org>
[ different struct fields (peer->mtu, peer->srtt_us, peer->rto_us) and different output.c code structure ]
Signed-off-by: Sasha Levin <sashal at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
net/rxrpc/ar-internal.h | 9 ++++++++-
net/rxrpc/conn_event.c | 2 +-
net/rxrpc/output.c | 10 +++++-----
net/rxrpc/peer_event.c | 17 ++++++++++++++++-
net/rxrpc/proc.c | 4 ++--
net/rxrpc/rxkad.c | 4 ++--
6 files changed, 34 insertions(+), 12 deletions(-)
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -335,7 +335,7 @@ struct rxrpc_peer {
struct hlist_head error_targets; /* targets for net error distribution */
struct rb_root service_conns; /* Service connections */
struct list_head keepalive_link; /* Link in net->peer_keepalive[] */
- time64_t last_tx_at; /* Last time packet sent here */
+ unsigned int last_tx_at; /* Last time packet sent here (time64_t LSW) */
seqlock_t service_conn_lock;
spinlock_t lock; /* access lock */
unsigned int if_mtu; /* interface MTU for this peer */
@@ -1161,6 +1161,13 @@ void rxrpc_transmit_one(struct rxrpc_cal
void rxrpc_input_error(struct rxrpc_local *, struct sk_buff *);
void rxrpc_peer_keepalive_worker(struct work_struct *);
+/* Update the last transmission time on a peer for keepalive purposes. */
+static inline void rxrpc_peer_mark_tx(struct rxrpc_peer *peer)
+{
+ /* To avoid tearing on 32-bit systems, we only keep the LSW. */
+ WRITE_ONCE(peer->last_tx_at, ktime_get_seconds());
+}
+
/*
* peer_object.c
*/
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -180,7 +180,7 @@ void rxrpc_conn_retransmit_call(struct r
}
ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len);
- conn->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(conn->peer);
if (ret < 0)
trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret,
rxrpc_tx_point_call_final_resend);
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -209,7 +209,7 @@ static void rxrpc_send_ack_packet(struct
iov_iter_kvec(&msg.msg_iter, WRITE, txb->kvec, txb->nr_kvec, txb->len);
rxrpc_local_dont_fragment(conn->local, false);
ret = do_udp_sendmsg(conn->local->socket, &msg, txb->len);
- call->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(call->peer);
if (ret < 0) {
trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret,
rxrpc_tx_point_call_ack);
@@ -310,7 +310,7 @@ int rxrpc_send_abort_packet(struct rxrpc
iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt));
ret = do_udp_sendmsg(conn->local->socket, &msg, sizeof(pkt));
- conn->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(conn->peer);
if (ret < 0)
trace_rxrpc_tx_fail(call->debug_id, serial, ret,
rxrpc_tx_point_call_abort);
@@ -486,7 +486,7 @@ retry:
*/
rxrpc_inc_stat(call->rxnet, stat_tx_data_send);
ret = do_udp_sendmsg(conn->local->socket, &msg, len);
- conn->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(conn->peer);
if (ret < 0) {
rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail);
@@ -573,7 +573,7 @@ void rxrpc_send_conn_abort(struct rxrpc_
trace_rxrpc_tx_packet(conn->debug_id, &whdr, rxrpc_tx_point_conn_abort);
- conn->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(conn->peer);
}
/*
@@ -692,7 +692,7 @@ void rxrpc_send_keepalive(struct rxrpc_p
trace_rxrpc_tx_packet(peer->debug_id, &whdr,
rxrpc_tx_point_version_keepalive);
- peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(peer);
_leave("");
}
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -225,6 +225,21 @@ static void rxrpc_distribute_error(struc
}
/*
+ * Reconstruct the last transmission time. The difference calculated should be
+ * valid provided no more than ~68 years elapsed since the last transmission.
+ */
+static time64_t rxrpc_peer_get_tx_mark(const struct rxrpc_peer *peer, time64_t base)
+{
+ s32 last_tx_at = READ_ONCE(peer->last_tx_at);
+ s32 base_lsw = base;
+ s32 diff = last_tx_at - base_lsw;
+
+ diff = clamp(diff, -RXRPC_KEEPALIVE_TIME, RXRPC_KEEPALIVE_TIME);
+
+ return diff + base;
+}
+
+/*
* Perform keep-alive pings.
*/
static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net *rxnet,
@@ -252,7 +267,7 @@ static void rxrpc_peer_keepalive_dispatc
spin_unlock_bh(&rxnet->peer_hash_lock);
if (use) {
- keepalive_at = peer->last_tx_at + RXRPC_KEEPALIVE_TIME;
+ keepalive_at = rxrpc_peer_get_tx_mark(peer, base) + RXRPC_KEEPALIVE_TIME;
slot = keepalive_at - base;
_debug("%02x peer %u t=%d {%pISp}",
cursor, peer->debug_id, slot, &peer->srx.transport);
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -299,13 +299,13 @@ static int rxrpc_peer_seq_show(struct se
now = ktime_get_seconds();
seq_printf(seq,
"UDP %-47.47s %-47.47s %3u"
- " %3u %5u %6llus %8u %8u\n",
+ " %3u %5u %6ds %8u %8u\n",
lbuff,
rbuff,
refcount_read(&peer->ref),
peer->cong_ssthresh,
peer->mtu,
- now - peer->last_tx_at,
+ (s32)now - (s32)READ_ONCE(peer->last_tx_at),
peer->srtt_us >> 3,
peer->rto_us);
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -676,7 +676,7 @@ static int rxkad_issue_challenge(struct
return -EAGAIN;
}
- conn->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(conn->peer);
trace_rxrpc_tx_packet(conn->debug_id, &whdr,
rxrpc_tx_point_rxkad_challenge);
_leave(" = 0");
@@ -734,7 +734,7 @@ static int rxkad_send_response(struct rx
return -EAGAIN;
}
- conn->peer->last_tx_at = ktime_get_seconds();
+ rxrpc_peer_mark_tx(conn->peer);
_leave(" = 0");
return 0;
}
Patches currently in stable-queue which might be from sashal at kernel.org are
queue-6.12/dma-pool-distinguish-between-missing-and-exhausted-a.patch
queue-6.12/nfc-nci-fix-race-between-rfkill-and-nci_unregister_d.patch
queue-6.12/bcache-fix-i-o-accounting-leak-in-detached_dev_do_re.patch
queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-fix-error-me.patch
queue-6.12/ipv6-use-the-right-ifindex-when-replying-to-icmpv6-f.patch
queue-6.12/bluetooth-hci_uart-fix-null-ptr-deref-in-hci_uart_wr.patch
queue-6.12/ice-stop-counting-udp-csum-mismatch-as-rx_errors.patch
queue-6.12/net-phy-micrel-fix-clk-warning-when-removing-the-dri.patch
queue-6.12/scsi-firewire-sbp-target-fix-overflow-in-sbp_make_tp.patch
queue-6.12/net-wwan-t7xx-fix-potential-skb-frags-overflow-in-rx.patch
queue-6.12/gpio-virtuser-fix-uaf-in-configfs-release-path.patch
queue-6.12/asoc-intel-sof_es8336-fix-headphone-gpio-logic-inver.patch
queue-6.12/net-mlx5-initialize-events-outside-devlink-lock.patch
queue-6.12/ice-fix-null-pointer-dereference-in-ice_vsi_set_napi.patch
queue-6.12/sched-deadline-fix-stuck-dl_server.patch
queue-6.12/nfc-llcp-fix-memleak-in-nfc_llcp_send_ui_frame.patch
queue-6.12/sched-deadline-document-dl_server.patch
queue-6.12/net-mlx5e-tc-delete-flows-only-for-existing-peers.patch
queue-6.12/net-mlx5e-skip-esn-replay-window-setup-for-ipsec-cry.patch
queue-6.12/rocker-fix-memory-leak-in-rocker_world_port_post_fin.patch
queue-6.12/net-mvpp2-cls-fix-memory-leak-in-mvpp2_ethtool_cls_r.patch
queue-6.12/net-bridge-fix-static-key-check.patch
queue-6.12/bonding-annotate-data-races-around-slave-last_rx.patch
queue-6.12/net-mlx5-fix-memory-leak-in-esw_acl_ingress_lgcy_set.patch
queue-6.12/bcache-use-bio-cloning-for-detached-device-requests.patch
queue-6.12/bcache-fix-improper-use-of-bi_end_io.patch
queue-6.12/net-mlx5-fs-fix-inverted-cap-check-in-tx-flow-table-.patch
queue-6.12/net-bcmasp-fix-early-exit-leak-with-fixed-phy.patch
queue-6.12/gpiolib-acpi-use-bit_ull-for-u64-mask-in-address-spa.patch
queue-6.12/rxrpc-fix-data-race-warning-and-potential-load-store-tearing.patch
queue-6.12/can-at91_can-fix-memory-leak-in-at91_can_probe.patch
queue-6.12/ksmbd-smbd-fix-dma_unmap_sg-nents.patch
queue-6.12/octeon_ep-fix-memory-leak-in-octep_device_setup.patch
queue-6.12/net-mlx5-fix-vhca_id-access-call-trace-use-before-al.patch
queue-6.12/bluetooth-mgmt-fix-memory-leak-in-set_ssp_complete.patch
More information about the linux-afs
mailing list