From: Philo Lu <lulie@linux.alibaba.com>
To: stable@vger.kernel.org
Cc: bigeasy@linutronix.de, willemb@google.com,
kerneljasonxing@gmail.com, edumazet@google.com,
pabeni@redhat.com, lulie@linux.alibaba.com, davem@davemloft.net,
kuba@kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, dust.li@linux.alibaba.com,
heiko.stuebner@cherry.de
Subject: [PATCH 6.6.y] net: Drop the lock in skb_may_tx_timestamp()
Date: Thu, 9 Jul 2026 20:58:16 +0800 [thread overview]
Message-ID: <20260709125816.86769-1-lulie@linux.alibaba.com> (raw)
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
not be taken in IRQ context, only softirq is okay. A few drivers receive
the timestamp via a dedicated interrupt and complete the TX timestamp
from that handler. This will lead to a deadlock if the lock is already
write-locked on the same CPU.
Taking the lock can be avoided. The socket (pointed by the skb) will
remain valid until the skb is released. The ->sk_socket and ->file
member will be set to NULL once the user closes the socket which may
happen before the timestamp arrives.
If we happen to observe the pointer while the socket is closing but
before the pointer is set to NULL then we may use it because both
pointer (and the file's cred member) are RCU freed.
Drop the lock. Use READ_ONCE() to obtain the individual pointer. Add a
matching WRITE_ONCE() where the pointer are cleared.
Link: https://lore.kernel.org/all/20260205145104.iWinkXHv@linutronix.de
Fixes: b245be1f4db1a ("net-timestamp: no-payload only sysctl")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260220183858.N4ERjFW6@linutronix.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
[ adapted sk_set_socket() in include/net/sock.h to fix the conflict from
not having commit 5d6b58c932ec ("net: lockless sock_i_ino()") and the
additional previous changes required by it.
It comes down to just now having the lines of
if (sock) {
WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
}
below the changed line. ]
Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
---
This patch is same as that in 6.12 (c770217044d9), and it can be also applied
to 6.1/5.15/5.10 except for line number differences. I'll send patches for the
other versions if this one looks good.
---
include/net/sock.h | 2 +-
net/core/skbuff.c | 23 ++++++++++++++++++-----
net/socket.c | 2 +-
3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index a6944844553af..c1f129a532b20 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2155,7 +2155,7 @@ static inline int sk_rx_queue_get(const struct sock *sk)
static inline void sk_set_socket(struct sock *sk, struct socket *sock)
{
- sk->sk_socket = sock;
+ WRITE_ONCE(sk->sk_socket, sock);
}
static inline wait_queue_head_t *sk_sleep(struct sock *sk)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c5e2ae6d0406b..732204d99822a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -5258,15 +5258,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
{
- bool ret;
+ struct socket *sock;
+ struct file *file;
+ bool ret = false;
if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
return true;
- read_lock_bh(&sk->sk_callback_lock);
- ret = sk->sk_socket && sk->sk_socket->file &&
- file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
- read_unlock_bh(&sk->sk_callback_lock);
+ /* The sk pointer remains valid as long as the skb is. The sk_socket and
+ * file pointer may become NULL if the socket is closed. Both structures
+ * (including file->cred) are RCU freed which means they can be accessed
+ * within a RCU read section.
+ */
+ rcu_read_lock();
+ sock = READ_ONCE(sk->sk_socket);
+ if (!sock)
+ goto out;
+ file = READ_ONCE(sock->file);
+ if (!file)
+ goto out;
+ ret = file_ns_capable(file, &init_user_ns, CAP_NET_RAW);
+out:
+ rcu_read_unlock();
return ret;
}
diff --git a/net/socket.c b/net/socket.c
index fa242d7e51c79..ae31c54664632 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -671,7 +671,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
iput(SOCK_INODE(sock));
return;
}
- sock->file = NULL;
+ WRITE_ONCE(sock->file, NULL);
}
/**
--
2.47.3
next reply other threads:[~2026-07-09 12:58 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 12:58 Philo Lu [this message]
2026-07-10 21:03 ` [PATCH 6.6.y] net: Drop the lock in skb_may_tx_timestamp() Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260709125816.86769-1-lulie@linux.alibaba.com \
--to=lulie@linux.alibaba.com \
--cc=bigeasy@linutronix.de \
--cc=davem@davemloft.net \
--cc=dust.li@linux.alibaba.com \
--cc=edumazet@google.com \
--cc=heiko.stuebner@cherry.de \
--cc=kerneljasonxing@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@vger.kernel.org \
--cc=willemb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox