From: Kyle Zeng SO_CNX_ADVICE calls __dst_negative_advice() while holding the socket lock. Connected UDP sends can still invalidate or replace sk_dst_cache without that lock. A concurrent sk_dst_check() can drop the final destination reference and allow an RCU callback to destroy it while __dst_negative_advice() retains only a borrowed pointer. This can cause a use-after-free while accessing dst->ops or running the negative_advice callback. The writer-side ordering fixed by commit 92f1655aa2b2 ("net: fix __dst_negative_advice() race") does not protect this reader from an independent cache replacement. Hold an RCU read-side critical section across the lookup and callback. This follows the datagram release callbacks and covers IPv4, IPv6, and XFRM advice without changing cache-reset or reference-ownership rules. Fixes: a87cb3e48ee8 ("net: Facility to report route quality of connected sockets") Signed-off-by: Kyle Zeng Signed-off-by: Eric Dumazet --- include/net/sock.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 173b37b2b8bb..0c1a6895d347 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2218,10 +2218,13 @@ sk_dst_get(const struct sock *sk) static inline void __dst_negative_advice(struct sock *sk) { - struct dst_entry *dst = __sk_dst_get(sk); + struct dst_entry *dst; + rcu_read_lock(); + dst = __sk_dst_get(sk); if (dst && dst->ops->negative_advice) dst->ops->negative_advice(sk, dst); + rcu_read_unlock(); } static inline void dst_negative_advice(struct sock *sk) -- 2.53.0