Skip to content

Commit e8af363

Browse files
edumazetgregkh
authored andcommitted
ipv6: mcast: add RCU protection to mld_newpack()
[ Upstream commit a527750d877fd334de87eef81f1cb5f0f0ca3373 ] mld_newpack() can be called without RTNL or RCU being held. Note that we no longer can use sock_alloc_send_skb() because ipv6.igmp_sk uses GFP_KERNEL allocations which can sleep. Instead use alloc_skb() and charge the net->ipv6.igmp_sk socket under RCU protection. Fixes: b8ad0cb ("[NETNS][IPV6] mcast - handle several network namespace") Signed-off-by: Eric Dumazet <[email protected]> Reviewed-by: David Ahern <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent a9319d8 commit e8af363

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

net/ipv6/mcast.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,28 +1731,32 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
17311731
struct net_device *dev = idev->dev;
17321732
int hlen = LL_RESERVED_SPACE(dev);
17331733
int tlen = dev->needed_tailroom;
1734-
struct net *net = dev_net(dev);
17351734
const struct in6_addr *saddr;
17361735
struct in6_addr addr_buf;
17371736
struct mld2_report *pmr;
17381737
struct sk_buff *skb;
17391738
unsigned int size;
17401739
struct sock *sk;
1741-
int err;
1740+
struct net *net;
17421741

1743-
sk = net->ipv6.igmp_sk;
17441742
/* we assume size > sizeof(ra) here
17451743
* Also try to not allocate high-order pages for big MTU
17461744
*/
17471745
size = min_t(int, mtu, PAGE_SIZE / 2) + hlen + tlen;
1748-
skb = sock_alloc_send_skb(sk, size, 1, &err);
1746+
skb = alloc_skb(size, GFP_KERNEL);
17491747
if (!skb)
17501748
return NULL;
17511749

17521750
skb->priority = TC_PRIO_CONTROL;
17531751
skb_reserve(skb, hlen);
17541752
skb_tailroom_reserve(skb, mtu, tlen);
17551753

1754+
rcu_read_lock();
1755+
1756+
net = dev_net_rcu(dev);
1757+
sk = net->ipv6.igmp_sk;
1758+
skb_set_owner_w(skb, sk);
1759+
17561760
if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
17571761
/* <draft-ietf-magma-mld-source-05.txt>:
17581762
* use unspecified address as the source address
@@ -1764,6 +1768,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
17641768

17651769
ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
17661770

1771+
rcu_read_unlock();
1772+
17671773
skb_put_data(skb, ra, sizeof(ra));
17681774

17691775
skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);

0 commit comments

Comments
 (0)