Skip to content

Commit 4e65a8b

Browse files
edumazetkuba-moo
authored andcommitted
ipv6: ioam: fix potential NULL dereferences in __ioam6_fill_trace_data()
We need to check __in6_dev_get() for possible NULL value, as suggested by Yiming Qian. Also add skb_dst_dev_rcu() instead of skb_dst_dev(), and two missing READ_ONCE(). Note that @dev can't be NULL. Fixes: 9ee11f0 ("ipv6: ioam: Data plane support for Pre-allocated Trace") Reported-by: Yiming Qian <yimingqian591@gmail.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Justin Iurman <justin.iurman@gmail.com> Link: https://patch.msgid.link/20260402101732.1188059-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 285fa6b commit 4e65a8b

1 file changed

Lines changed: 16 additions & 11 deletions

File tree

net/ipv6/ioam6.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,9 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
710710
struct ioam6_schema *sc,
711711
unsigned int sclen, bool is_input)
712712
{
713-
struct net_device *dev = skb_dst_dev(skb);
713+
/* Note: skb_dst_dev_rcu() can't be NULL at this point. */
714+
struct net_device *dev = skb_dst_dev_rcu(skb);
715+
struct inet6_dev *i_skb_dev, *idev;
714716
struct timespec64 ts;
715717
ktime_t tstamp;
716718
u64 raw64;
@@ -721,32 +723,35 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
721723

722724
data = trace->data + trace->remlen * 4 - trace->nodelen * 4 - sclen * 4;
723725

726+
i_skb_dev = skb->dev ? __in6_dev_get(skb->dev) : NULL;
727+
idev = __in6_dev_get(dev);
728+
724729
/* hop_lim and node_id */
725730
if (trace->type.bit0) {
726731
byte = ipv6_hdr(skb)->hop_limit;
727732
if (is_input)
728733
byte--;
729734

730-
raw32 = dev_net(dev)->ipv6.sysctl.ioam6_id;
735+
raw32 = READ_ONCE(dev_net(dev)->ipv6.sysctl.ioam6_id);
731736

732737
*(__be32 *)data = cpu_to_be32((byte << 24) | raw32);
733738
data += sizeof(__be32);
734739
}
735740

736741
/* ingress_if_id and egress_if_id */
737742
if (trace->type.bit1) {
738-
if (!skb->dev)
743+
if (!i_skb_dev)
739744
raw16 = IOAM6_U16_UNAVAILABLE;
740745
else
741-
raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_id);
746+
raw16 = (__force u16)READ_ONCE(i_skb_dev->cnf.ioam6_id);
742747

743748
*(__be16 *)data = cpu_to_be16(raw16);
744749
data += sizeof(__be16);
745750

746-
if (dev->flags & IFF_LOOPBACK)
751+
if ((dev->flags & IFF_LOOPBACK) || !idev)
747752
raw16 = IOAM6_U16_UNAVAILABLE;
748753
else
749-
raw16 = (__force u16)READ_ONCE(__in6_dev_get(dev)->cnf.ioam6_id);
754+
raw16 = (__force u16)READ_ONCE(idev->cnf.ioam6_id);
750755

751756
*(__be16 *)data = cpu_to_be16(raw16);
752757
data += sizeof(__be16);
@@ -822,26 +827,26 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
822827
if (is_input)
823828
byte--;
824829

825-
raw64 = dev_net(dev)->ipv6.sysctl.ioam6_id_wide;
830+
raw64 = READ_ONCE(dev_net(dev)->ipv6.sysctl.ioam6_id_wide);
826831

827832
*(__be64 *)data = cpu_to_be64(((u64)byte << 56) | raw64);
828833
data += sizeof(__be64);
829834
}
830835

831836
/* ingress_if_id and egress_if_id (wide) */
832837
if (trace->type.bit9) {
833-
if (!skb->dev)
838+
if (!i_skb_dev)
834839
raw32 = IOAM6_U32_UNAVAILABLE;
835840
else
836-
raw32 = READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_id_wide);
841+
raw32 = READ_ONCE(i_skb_dev->cnf.ioam6_id_wide);
837842

838843
*(__be32 *)data = cpu_to_be32(raw32);
839844
data += sizeof(__be32);
840845

841-
if (dev->flags & IFF_LOOPBACK)
846+
if ((dev->flags & IFF_LOOPBACK) || !idev)
842847
raw32 = IOAM6_U32_UNAVAILABLE;
843848
else
844-
raw32 = READ_ONCE(__in6_dev_get(dev)->cnf.ioam6_id_wide);
849+
raw32 = READ_ONCE(idev->cnf.ioam6_id_wide);
845850

846851
*(__be32 *)data = cpu_to_be32(raw32);
847852
data += sizeof(__be32);

0 commit comments

Comments
 (0)