summaryrefslogtreecommitdiff
path: root/net/ipv6/ndisc.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2025-02-07 13:58:34 +0000
committerJakub Kicinski <kuba@kernel.org>2025-02-10 18:09:09 -0800
commit628e6d18930bbd21f2d4562228afe27694f66da9 (patch)
tree4ee9e91e855cc03159bba3fcbe5dd8a3d7767151 /net/ipv6/ndisc.c
parent48145a57d4bbe3496e8e4880b23ea6b511e6e519 (diff)
downloadlinux-628e6d18930bbd21f2d4562228afe27694f66da9.tar.gz
linux-628e6d18930bbd21f2d4562228afe27694f66da9.tar.bz2
linux-628e6d18930bbd21f2d4562228afe27694f66da9.zip
ndisc: use RCU protection in ndisc_alloc_skb()
ndisc_alloc_skb() can be called without RTNL or RCU being held. Add RCU protection to avoid possible UAF. Fixes: de09334b9326 ("ndisc: Introduce ndisc_alloc_skb() helper.") Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com> Link: https://patch.msgid.link/20250207135841.1948589-3-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r--net/ipv6/ndisc.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 264b10a94757..90f8aa2d7af2 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -418,15 +418,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
{
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
- struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
struct sk_buff *skb;
skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
- if (!skb) {
- ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
- __func__);
+ if (!skb)
return NULL;
- }
skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev;
@@ -437,7 +433,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
/* Manually assign socket ownership as we avoid calling
* sock_alloc_send_pskb() to bypass wmem buffer limits
*/
- skb_set_owner_w(skb, sk);
+ rcu_read_lock();
+ skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk);
+ rcu_read_unlock();
return skb;
}