Skip to content

Commit 99db195

Browse files
CKI Backport BotHangbin Liu
authored andcommitted
ipv6: icmp: convert to dev_net_rcu()
JIRA: https://issues.redhat.com/browse/RHEL-115578 commit 34aef2b Author: Eric Dumazet <edumazet@google.com> Date: Wed Feb 5 15:51:19 2025 +0000 ipv6: icmp: convert to dev_net_rcu() icmp6_send() must acquire rcu_read_lock() sooner to ensure the dev_net() call done from a safe context. Other ICMPv6 uses of dev_net() seem safe, change them to dev_net_rcu() to get LOCKDEP support to catch bugs. Fixes: 9a43b70 ("[NETNS][IPV6] icmp6 - make icmpv6_socket per namespace") Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20250205155120.1676781-12-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
1 parent 9fab3d9 commit 99db195

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

net/ipv6/icmp.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static int icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
7676
{
7777
/* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
7878
struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset);
79-
struct net *net = dev_net(skb->dev);
79+
struct net *net = dev_net_rcu(skb->dev);
8080

8181
if (type == ICMPV6_PKT_TOOBIG)
8282
ip6_update_pmtu(skb, net, info, skb->dev->ifindex, 0, sock_net_uid(net, NULL));
@@ -473,7 +473,10 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
473473

474474
if (!skb->dev)
475475
return;
476-
net = dev_net(skb->dev);
476+
477+
rcu_read_lock();
478+
479+
net = dev_net_rcu(skb->dev);
477480
mark = IP6_REPLY_MARK(net, skb->mark);
478481
/*
479482
* Make sure we respect the rules
@@ -496,7 +499,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
496499
!(type == ICMPV6_PARAMPROB &&
497500
code == ICMPV6_UNK_OPTION &&
498501
(opt_unrec(skb, info))))
499-
return;
502+
goto out;
500503

501504
saddr = NULL;
502505
}
@@ -526,7 +529,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
526529
if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
527530
net_dbg_ratelimited("icmp6_send: addr_any/mcast source [%pI6c > %pI6c]\n",
528531
&hdr->saddr, &hdr->daddr);
529-
return;
532+
goto out;
530533
}
531534

532535
/*
@@ -535,7 +538,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
535538
if (is_ineligible(skb)) {
536539
net_dbg_ratelimited("icmp6_send: no reply to icmp error [%pI6c > %pI6c]\n",
537540
&hdr->saddr, &hdr->daddr);
538-
return;
541+
goto out;
539542
}
540543

541544
/* Needed by both icmpv6_global_allow and icmpv6_xmit_lock */
@@ -582,7 +585,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
582585
np = inet6_sk(sk);
583586

584587
if (!icmpv6_xrlim_allow(sk, type, &fl6, apply_ratelimit))
585-
goto out;
588+
goto out_unlock;
586589

587590
tmp_hdr.icmp6_type = type;
588591
tmp_hdr.icmp6_code = code;
@@ -600,7 +603,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
600603

601604
dst = icmpv6_route_lookup(net, skb, sk, &fl6);
602605
if (IS_ERR(dst))
603-
goto out;
606+
goto out_unlock;
604607

605608
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
606609

@@ -616,7 +619,6 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
616619
goto out_dst_release;
617620
}
618621

619-
rcu_read_lock();
620622
idev = __in6_dev_get(skb->dev);
621623

622624
if (ip6_append_data(sk, icmpv6_getfrag, &msg,
@@ -630,13 +632,15 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
630632
icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
631633
len + sizeof(struct icmp6hdr));
632634
}
633-
rcu_read_unlock();
635+
634636
out_dst_release:
635637
dst_release(dst);
636-
out:
638+
out_unlock:
637639
icmpv6_xmit_unlock(sk);
638640
out_bh_enable:
639641
local_bh_enable();
642+
out:
643+
rcu_read_unlock();
640644
}
641645
EXPORT_SYMBOL(icmp6_send);
642646

@@ -679,8 +683,8 @@ int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type,
679683
skb_pull(skb2, nhs);
680684
skb_reset_network_header(skb2);
681685

682-
rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0,
683-
skb, 0);
686+
rt = rt6_lookup(dev_net_rcu(skb->dev), &ipv6_hdr(skb2)->saddr,
687+
NULL, 0, skb, 0);
684688

685689
if (rt && rt->dst.dev)
686690
skb2->dev = rt->dst.dev;
@@ -717,7 +721,7 @@ EXPORT_SYMBOL(ip6_err_gen_icmpv6_unreach);
717721

718722
static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb)
719723
{
720-
struct net *net = dev_net(skb->dev);
724+
struct net *net = dev_net_rcu(skb->dev);
721725
struct sock *sk;
722726
struct inet6_dev *idev;
723727
struct ipv6_pinfo *np;
@@ -832,7 +836,7 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type,
832836
u8 code, __be32 info)
833837
{
834838
struct inet6_skb_parm *opt = IP6CB(skb);
835-
struct net *net = dev_net(skb->dev);
839+
struct net *net = dev_net_rcu(skb->dev);
836840
const struct inet6_protocol *ipprot;
837841
enum skb_drop_reason reason;
838842
int inner_offset;
@@ -889,7 +893,7 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type,
889893
static int icmpv6_rcv(struct sk_buff *skb)
890894
{
891895
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
892-
struct net *net = dev_net(skb->dev);
896+
struct net *net = dev_net_rcu(skb->dev);
893897
struct net_device *dev = icmp6_dev(skb);
894898
struct inet6_dev *idev = __in6_dev_get(dev);
895899
const struct in6_addr *saddr, *daddr;
@@ -921,7 +925,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
921925
skb_set_network_header(skb, nh);
922926
}
923927

924-
__ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INMSGS);
928+
__ICMP6_INC_STATS(dev_net_rcu(dev), idev, ICMP6_MIB_INMSGS);
925929

926930
saddr = &ipv6_hdr(skb)->saddr;
927931
daddr = &ipv6_hdr(skb)->daddr;
@@ -939,7 +943,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
939943

940944
type = hdr->icmp6_type;
941945

942-
ICMP6MSGIN_INC_STATS(dev_net(dev), idev, type);
946+
ICMP6MSGIN_INC_STATS(dev_net_rcu(dev), idev, type);
943947

944948
switch (type) {
945949
case ICMPV6_ECHO_REQUEST:
@@ -1034,9 +1038,9 @@ static int icmpv6_rcv(struct sk_buff *skb)
10341038

10351039
csum_error:
10361040
reason = SKB_DROP_REASON_ICMP_CSUM;
1037-
__ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS);
1041+
__ICMP6_INC_STATS(dev_net_rcu(dev), idev, ICMP6_MIB_CSUMERRORS);
10381042
discard_it:
1039-
__ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INERRORS);
1043+
__ICMP6_INC_STATS(dev_net_rcu(dev), idev, ICMP6_MIB_INERRORS);
10401044
drop_no_count:
10411045
kfree_skb_reason(skb, reason);
10421046
return 0;

0 commit comments

Comments
 (0)