* FAILED: patch "[PATCH] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()" failed to apply to 5.15-stable tree
@ 2026-09-03 14:00 gregkh
2026-09-08 22:37 ` [PATCH 5.15.y 1/3] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
2026-09-09 0:25 ` [PATCH 5.15.y 1/2] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
0 siblings, 2 replies; 6+ messages in thread
From: gregkh @ 2026-09-03 14:00 UTC (permalink / raw)
To: andrea.mayer, horms, kuba, xmei5; +Cc: stable
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x f826df95332c07380206dbd54178b6eefb311aba
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090351-sagging-obliged-3e7b@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f826df95332c07380206dbd54178b6eefb311aba Mon Sep 17 00:00:00 2001
From: Andrea Mayer <andrea.mayer@uniroma2.it>
Date: Mon, 17 Aug 2026 15:26:44 +0200
Subject: [PATCH] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()
ipv6_rpl_srh_rcv() dereferences idev from __in6_dev_get() without a NULL
check when reading idev->cnf.rpl_seg_enabled.
When the device's MTU drops below IPV6_MIN_MTU, addrconf_ifdown() clears
dev->ip6_ptr through RCU_INIT_POINTER(). A packet that passed the idev
check in ip6_rcv_core() can then reach ipv6_rpl_srh_rcv() with
dev->ip6_ptr already NULL.
Reproduced by flooding the receiving interface with ping6 traffic while
flapping its MTU between 1500 and 1200:
BUG: KASAN: null-ptr-deref in ipv6_rpl_srh_rcv+0xb3/0x1070
Read of size 4 at addr 00000000000006b4 by task ping6/394
CPU: 2 UID: 0 PID: 394 Comm: ping6 Not tainted 7.2.0-rc7-micro-vm-dev-00095-g24ef02f934ee #240 PREEMPT(full)
Call Trace:
<IRQ>
kasan_report+0xc6/0x100
ipv6_rpl_srh_rcv+0xb3/0x1070
ip6_protocol_deliver_rcu+0x759/0x9a0
ip6_input_finish+0xa8/0x1b0
ip6_input+0xe1/0x490
ipv6_rcv+0x33d/0x460
__netif_receive_skb_one_core+0xd6/0x130
process_backlog+0x2cc/0xa00
__napi_poll.constprop.0+0x56/0x270
net_rx_action+0x327/0x730
handle_softirqs+0x11e/0x630
do_softirq+0xb3/0xf0
</IRQ>
Both ipv6_rpl_srh_rcv() and ipv6_srh_rcv() are called only from
ipv6_rthdr_rcv(), which already has an idev lookup.
Fix the NULL dereference on the RPL path by checking idev in
ipv6_rthdr_rcv(), before it calls either function. The callees take idev as
an argument and no longer call __in6_dev_get(), so the packet is now
dropped in one place, with SKB_DROP_REASON_IPV6DISABLED on both paths.
Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
Cc: stable@vger.kernel.org
Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Tested-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260817132644.2223-1-andrea.mayer@uniroma2.it
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 9c677eb1d1a6..51941ad656a3 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -368,23 +368,16 @@ static void seg6_update_csum(struct sk_buff *skb)
(__be32 *)addr);
}
-static int ipv6_srh_rcv(struct sk_buff *skb)
+static int ipv6_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
{
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(skb->dev);
struct ipv6_sr_hdr *hdr;
- struct inet6_dev *idev;
struct in6_addr *addr;
int accept_seg6;
hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
- idev = __in6_dev_get(skb->dev);
- if (!idev) {
- kfree_skb(skb);
- return -1;
- }
-
accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled),
READ_ONCE(idev->cnf.seg6_enabled));
@@ -485,12 +478,11 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
return -1;
}
-static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
{
struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr;
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(skb->dev);
- struct inet6_dev *idev;
struct ipv6hdr *oldhdr;
unsigned int chdr_len;
unsigned char *buf;
@@ -499,8 +491,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
u64 n = 0;
u32 r;
- idev = __in6_dev_get(skb->dev);
-
accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
READ_ONCE(idev->cnf.rpl_seg_enabled));
if (!accept_rpl_seg) {
@@ -689,10 +679,14 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
switch (hdr->type) {
case IPV6_SRCRT_TYPE_4:
/* segment routing */
- return ipv6_srh_rcv(skb);
+ if (!idev)
+ goto disabled;
+ return ipv6_srh_rcv(skb, idev);
case IPV6_SRCRT_TYPE_3:
/* rpl segment routing */
- return ipv6_rpl_srh_rcv(skb);
+ if (!idev)
+ goto disabled;
+ return ipv6_rpl_srh_rcv(skb, idev);
default:
break;
}
@@ -837,6 +831,10 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
(&hdr->type) - skb_network_header(skb));
return -1;
+
+disabled:
+ kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED);
+ return -1;
}
static const struct inet6_protocol rthdr_protocol = {
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5.15.y 1/3] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR
2026-09-03 14:00 FAILED: patch "[PATCH] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()" failed to apply to 5.15-stable tree gregkh
@ 2026-09-08 22:37 ` Sasha Levin
2026-09-08 22:37 ` [PATCH 5.15.y 2/3] ipv6: icmp6: add drop reason support to ndisc_rcv() Sasha Levin
2026-09-08 22:37 ` [PATCH 5.15.y 3/3] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv() Sasha Levin
2026-09-09 0:25 ` [PATCH 5.15.y 1/2] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
1 sibling, 2 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-08 22:37 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, Jakub Kicinski, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 3bdfb04f13ebdd4ae50fc5dc595663874781e48c ]
IPv4 reassembly unit can decide to drop frags based on
/proc/sys/net/ipv4/ipfrag_max_dist sysctl.
Add a specific drop reason to track this specific
and weird case.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Stable adaptation: the fragment drop-reason hunks rely on prerequisite
plumbing absent from 5.15 and do not affect the target fix. Replace them
with the missing IPV6DISABLED drop reason and RPL devconf read annotation
needed to make the target apply and build. ]
[ sashal: Reduced backport -- upstream 3bdfb04f13ebd touches 2 file(s), this
backport carries 3. Not backported here:
include/net/dropreason.h
net/ipv4/ip_fragment.c
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: f826df95332c ("ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/skbuff.h | 1 +
include/trace/events/skb.h | 1 +
net/ipv6/exthdrs.c | 5 ++---
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 24ceeab1b509f..af4924ceafe61 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -337,6 +337,7 @@ enum skb_drop_reason {
* is multicast, but L3 is
* unicast.
*/
+ SKB_DROP_REASON_IPV6DISABLED, /* IPv6 is disabled on the device */
SKB_DROP_REASON_MAX,
};
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index 485a1d3034a4b..33bebe0c7677e 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -23,6 +23,7 @@
EM(SKB_DROP_REASON_IP_RPFILTER, IP_RPFILTER) \
EM(SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST, \
UNICAST_IN_L2_MULTICAST) \
+ EM(SKB_DROP_REASON_IPV6DISABLED, IPV6DISABLED) \
EMe(SKB_DROP_REASON_MAX, MAX)
#undef EM
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 3c6de4ccbf53b..6111fe395ff09 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -505,9 +505,8 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
idev = __in6_dev_get(skb->dev);
- accept_rpl_seg = net->ipv6.devconf_all->rpl_seg_enabled;
- if (accept_rpl_seg > idev->cnf.rpl_seg_enabled)
- accept_rpl_seg = idev->cnf.rpl_seg_enabled;
+ accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
+ READ_ONCE(idev->cnf.rpl_seg_enabled));
if (!accept_rpl_seg) {
kfree_skb(skb);
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5.15.y 2/3] ipv6: icmp6: add drop reason support to ndisc_rcv()
2026-09-08 22:37 ` [PATCH 5.15.y 1/3] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
@ 2026-09-08 22:37 ` Sasha Levin
2026-09-08 22:37 ` [PATCH 5.15.y 3/3] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv() Sasha Levin
1 sibling, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-08 22:37 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, David Ahern, Jakub Kicinski, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 545dbcd124b02c9dc93c8a5894c71d682effc3e6 ]
Creates three new drop reasons:
SKB_DROP_REASON_IPV6_NDISC_FRAG: invalid frag (suppress_frag_ndisc).
SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT: invalid hop limit.
SKB_DROP_REASON_IPV6_NDISC_BAD_CODE: invalid NDISC icmp6 code.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ sashal: Reduced backport -- upstream 545dbcd124b02 touches 4 file(s), this
backport carries 1. Not backported here:
include/net/dropreason.h
include/net/ndisc.h
net/ipv6/icmp.c
net/ipv6/ndisc.c
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: f826df95332c ("ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/exthdrs.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6111fe395ff09..1a9e2f989734c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -495,9 +495,9 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
struct net *net = dev_net(skb->dev);
struct inet6_dev *idev;
struct ipv6hdr *oldhdr;
- struct in6_addr addr;
unsigned int chdr_len;
unsigned char *buf;
+ struct in6_addr addr;
int accept_rpl_seg;
int i, err;
u64 n = 0;
@@ -507,7 +507,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
READ_ONCE(idev->cnf.rpl_seg_enabled));
-
if (!accept_rpl_seg) {
kfree_skb(skb);
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5.15.y 3/3] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()
2026-09-08 22:37 ` [PATCH 5.15.y 1/3] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
2026-09-08 22:37 ` [PATCH 5.15.y 2/3] ipv6: icmp6: add drop reason support to ndisc_rcv() Sasha Levin
@ 2026-09-08 22:37 ` Sasha Levin
1 sibling, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-08 22:37 UTC (permalink / raw)
To: stable; +Cc: Andrea Mayer, Xiang Mei, Simon Horman, Jakub Kicinski,
Sasha Levin
From: Andrea Mayer <andrea.mayer@uniroma2.it>
[ Upstream commit f826df95332c07380206dbd54178b6eefb311aba ]
ipv6_rpl_srh_rcv() dereferences idev from __in6_dev_get() without a NULL
check when reading idev->cnf.rpl_seg_enabled.
When the device's MTU drops below IPV6_MIN_MTU, addrconf_ifdown() clears
dev->ip6_ptr through RCU_INIT_POINTER(). A packet that passed the idev
check in ip6_rcv_core() can then reach ipv6_rpl_srh_rcv() with
dev->ip6_ptr already NULL.
Reproduced by flooding the receiving interface with ping6 traffic while
flapping its MTU between 1500 and 1200:
BUG: KASAN: null-ptr-deref in ipv6_rpl_srh_rcv+0xb3/0x1070
Read of size 4 at addr 00000000000006b4 by task ping6/394
CPU: 2 UID: 0 PID: 394 Comm: ping6 Not tainted 7.2.0-rc7-micro-vm-dev-00095-g24ef02f934ee #240 PREEMPT(full)
Call Trace:
<IRQ>
kasan_report+0xc6/0x100
ipv6_rpl_srh_rcv+0xb3/0x1070
ip6_protocol_deliver_rcu+0x759/0x9a0
ip6_input_finish+0xa8/0x1b0
ip6_input+0xe1/0x490
ipv6_rcv+0x33d/0x460
__netif_receive_skb_one_core+0xd6/0x130
process_backlog+0x2cc/0xa00
__napi_poll.constprop.0+0x56/0x270
net_rx_action+0x327/0x730
handle_softirqs+0x11e/0x630
do_softirq+0xb3/0xf0
</IRQ>
Both ipv6_rpl_srh_rcv() and ipv6_srh_rcv() are called only from
ipv6_rthdr_rcv(), which already has an idev lookup.
Fix the NULL dereference on the RPL path by checking idev in
ipv6_rthdr_rcv(), before it calls either function. The callees take idev as
an argument and no longer call __in6_dev_get(), so the packet is now
dropped in one place, with SKB_DROP_REASON_IPV6DISABLED on both paths.
Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
Cc: stable@vger.kernel.org
Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Tested-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260817132644.2223-1-andrea.mayer@uniroma2.it
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/exthdrs.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 1a9e2f989734c..8fb56237c771e 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -365,23 +365,16 @@ static void seg6_update_csum(struct sk_buff *skb)
(__be32 *)addr);
}
-static int ipv6_srh_rcv(struct sk_buff *skb)
+static int ipv6_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
{
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(skb->dev);
struct ipv6_sr_hdr *hdr;
- struct inet6_dev *idev;
struct in6_addr *addr;
int accept_seg6;
hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
- idev = __in6_dev_get(skb->dev);
- if (!idev) {
- kfree_skb(skb);
- return -1;
- }
-
accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled),
READ_ONCE(idev->cnf.seg6_enabled));
@@ -488,12 +481,11 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
return -1;
}
-static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
{
struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr;
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(skb->dev);
- struct inet6_dev *idev;
struct ipv6hdr *oldhdr;
unsigned int chdr_len;
unsigned char *buf;
@@ -503,8 +495,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
u64 n = 0;
u32 r;
- idev = __in6_dev_get(skb->dev);
-
accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
READ_ONCE(idev->cnf.rpl_seg_enabled));
if (!accept_rpl_seg) {
@@ -715,10 +705,14 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
switch (hdr->type) {
case IPV6_SRCRT_TYPE_4:
/* segment routing */
- return ipv6_srh_rcv(skb);
+ if (!idev)
+ goto disabled;
+ return ipv6_srh_rcv(skb, idev);
case IPV6_SRCRT_TYPE_3:
/* rpl segment routing */
- return ipv6_rpl_srh_rcv(skb);
+ if (!idev)
+ goto disabled;
+ return ipv6_rpl_srh_rcv(skb, idev);
default:
break;
}
@@ -866,6 +860,10 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
(&hdr->type) - skb_network_header(skb));
return -1;
+
+disabled:
+ kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED);
+ return -1;
}
static const struct inet6_protocol rthdr_protocol = {
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5.15.y 1/2] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR
2026-09-03 14:00 FAILED: patch "[PATCH] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()" failed to apply to 5.15-stable tree gregkh
2026-09-08 22:37 ` [PATCH 5.15.y 1/3] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
@ 2026-09-09 0:25 ` Sasha Levin
2026-09-09 0:25 ` [PATCH 5.15.y 2/2] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv() Sasha Levin
1 sibling, 1 reply; 6+ messages in thread
From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, Jakub Kicinski, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 3bdfb04f13ebdd4ae50fc5dc595663874781e48c ]
IPv4 reassembly unit can decide to drop frags based on
/proc/sys/net/ipv4/ipfrag_max_dist sysctl.
Add a specific drop reason to track this specific
and weird case.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Backport to 5.15: the original IPv4 drop-reason change cannot be
represented because this tree predates include/net/dropreason.h and the
reason-aware fragment purge API. Add only SKB_DROP_REASON_IPV6DISABLED to
the older enum and trace table, and align the IPv6 routing-header code so
the dependent fix applies cleanly. ]
[ sashal: Reduced backport -- upstream 3bdfb04f13ebd touches 2 file(s), this
backport carries 3. Not backported here:
include/net/dropreason.h
net/ipv4/ip_fragment.c
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: f826df95332c ("ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/skbuff.h | 1 +
include/trace/events/skb.h | 1 +
net/ipv6/exthdrs.c | 12 +++---------
3 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 24ceeab1b509f..af4924ceafe61 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -337,6 +337,7 @@ enum skb_drop_reason {
* is multicast, but L3 is
* unicast.
*/
+ SKB_DROP_REASON_IPV6DISABLED, /* IPv6 is disabled on the device */
SKB_DROP_REASON_MAX,
};
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index 485a1d3034a4b..33bebe0c7677e 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -23,6 +23,7 @@
EM(SKB_DROP_REASON_IP_RPFILTER, IP_RPFILTER) \
EM(SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST, \
UNICAST_IN_L2_MULTICAST) \
+ EM(SKB_DROP_REASON_IPV6DISABLED, IPV6DISABLED) \
EMe(SKB_DROP_REASON_MAX, MAX)
#undef EM
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 3c6de4ccbf53b..3bfe826c3134f 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -495,7 +495,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
struct net *net = dev_net(skb->dev);
struct inet6_dev *idev;
struct ipv6hdr *oldhdr;
- struct in6_addr addr;
unsigned int chdr_len;
unsigned char *buf;
int accept_rpl_seg;
@@ -505,10 +504,8 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
idev = __in6_dev_get(skb->dev);
- accept_rpl_seg = net->ipv6.devconf_all->rpl_seg_enabled;
- if (accept_rpl_seg > idev->cnf.rpl_seg_enabled)
- accept_rpl_seg = idev->cnf.rpl_seg_enabled;
-
+ accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
+ READ_ONCE(idev->cnf.rpl_seg_enabled));
if (!accept_rpl_seg) {
kfree_skb(skb);
return -1;
@@ -607,9 +604,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
return -1;
}
- addr = ipv6_hdr(skb)->daddr;
- ipv6_hdr(skb)->daddr = ohdr->rpl_segaddr[i];
- ohdr->rpl_segaddr[i] = addr;
+ swap(ipv6_hdr(skb)->daddr, ohdr->rpl_segaddr[i]);
ipv6_rpl_srh_compress(chdr, ohdr, &ipv6_hdr(skb)->daddr, n);
@@ -690,7 +685,6 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
struct net *net = dev_net(skb->dev);
int accept_source_route;
- idev = __in6_dev_get(skb->dev);
accept_source_route = READ_ONCE(net->ipv6.devconf_all->accept_source_route);
if (idev)
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5.15.y 2/2] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()
2026-09-09 0:25 ` [PATCH 5.15.y 1/2] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
@ 2026-09-09 0:25 ` Sasha Levin
0 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw)
To: stable; +Cc: Andrea Mayer, Xiang Mei, Simon Horman, Jakub Kicinski,
Sasha Levin
From: Andrea Mayer <andrea.mayer@uniroma2.it>
[ Upstream commit f826df95332c07380206dbd54178b6eefb311aba ]
ipv6_rpl_srh_rcv() dereferences idev from __in6_dev_get() without a NULL
check when reading idev->cnf.rpl_seg_enabled.
When the device's MTU drops below IPV6_MIN_MTU, addrconf_ifdown() clears
dev->ip6_ptr through RCU_INIT_POINTER(). A packet that passed the idev
check in ip6_rcv_core() can then reach ipv6_rpl_srh_rcv() with
dev->ip6_ptr already NULL.
Reproduced by flooding the receiving interface with ping6 traffic while
flapping its MTU between 1500 and 1200:
BUG: KASAN: null-ptr-deref in ipv6_rpl_srh_rcv+0xb3/0x1070
Read of size 4 at addr 00000000000006b4 by task ping6/394
CPU: 2 UID: 0 PID: 394 Comm: ping6 Not tainted 7.2.0-rc7-micro-vm-dev-00095-g24ef02f934ee #240 PREEMPT(full)
Call Trace:
<IRQ>
kasan_report+0xc6/0x100
ipv6_rpl_srh_rcv+0xb3/0x1070
ip6_protocol_deliver_rcu+0x759/0x9a0
ip6_input_finish+0xa8/0x1b0
ip6_input+0xe1/0x490
ipv6_rcv+0x33d/0x460
__netif_receive_skb_one_core+0xd6/0x130
process_backlog+0x2cc/0xa00
__napi_poll.constprop.0+0x56/0x270
net_rx_action+0x327/0x730
handle_softirqs+0x11e/0x630
do_softirq+0xb3/0xf0
</IRQ>
Both ipv6_rpl_srh_rcv() and ipv6_srh_rcv() are called only from
ipv6_rthdr_rcv(), which already has an idev lookup.
Fix the NULL dereference on the RPL path by checking idev in
ipv6_rthdr_rcv(), before it calls either function. The callees take idev as
an argument and no longer call __in6_dev_get(), so the packet is now
dropped in one place, with SKB_DROP_REASON_IPV6DISABLED on both paths.
Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
Cc: stable@vger.kernel.org
Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Tested-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260817132644.2223-1-andrea.mayer@uniroma2.it
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/exthdrs.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 3bfe826c3134f..259340357a389 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -365,23 +365,16 @@ static void seg6_update_csum(struct sk_buff *skb)
(__be32 *)addr);
}
-static int ipv6_srh_rcv(struct sk_buff *skb)
+static int ipv6_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
{
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(skb->dev);
struct ipv6_sr_hdr *hdr;
- struct inet6_dev *idev;
struct in6_addr *addr;
int accept_seg6;
hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
- idev = __in6_dev_get(skb->dev);
- if (!idev) {
- kfree_skb(skb);
- return -1;
- }
-
accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled),
READ_ONCE(idev->cnf.seg6_enabled));
@@ -488,12 +481,11 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
return -1;
}
-static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
{
struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr;
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(skb->dev);
- struct inet6_dev *idev;
struct ipv6hdr *oldhdr;
unsigned int chdr_len;
unsigned char *buf;
@@ -502,8 +494,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
u64 n = 0;
u32 r;
- idev = __in6_dev_get(skb->dev);
-
accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
READ_ONCE(idev->cnf.rpl_seg_enabled));
if (!accept_rpl_seg) {
@@ -711,10 +701,14 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
switch (hdr->type) {
case IPV6_SRCRT_TYPE_4:
/* segment routing */
- return ipv6_srh_rcv(skb);
+ if (!idev)
+ goto disabled;
+ return ipv6_srh_rcv(skb, idev);
case IPV6_SRCRT_TYPE_3:
/* rpl segment routing */
- return ipv6_rpl_srh_rcv(skb);
+ if (!idev)
+ goto disabled;
+ return ipv6_rpl_srh_rcv(skb, idev);
default:
break;
}
@@ -862,6 +856,10 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
(&hdr->type) - skb_network_header(skb));
return -1;
+
+disabled:
+ kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED);
+ return -1;
}
static const struct inet6_protocol rthdr_protocol = {
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-09 0:25 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 14:00 FAILED: patch "[PATCH] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()" failed to apply to 5.15-stable tree gregkh
2026-09-08 22:37 ` [PATCH 5.15.y 1/3] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
2026-09-08 22:37 ` [PATCH 5.15.y 2/3] ipv6: icmp6: add drop reason support to ndisc_rcv() Sasha Levin
2026-09-08 22:37 ` [PATCH 5.15.y 3/3] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv() Sasha Levin
2026-09-09 0:25 ` [PATCH 5.15.y 1/2] net: dropreason: add SKB_DROP_REASON_FRAG_TOO_FAR Sasha Levin
2026-09-09 0:25 ` [PATCH 5.15.y 2/2] ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv() Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox