Skip to content

Commit 27843ce

Browse files
edumazetkuba-moo
authored andcommitted
ipvlan: ensure network headers are in skb linear part
syzbot found that ipvlan_process_v6_outbound() was assuming the IPv6 network header isis present in skb->head [1] Add the needed pskb_network_may_pull() calls for both IPv4 and IPv6 handlers. [1] BUG: KMSAN: uninit-value in __ipv6_addr_type+0xa2/0x490 net/ipv6/addrconf_core.c:47 __ipv6_addr_type+0xa2/0x490 net/ipv6/addrconf_core.c:47 ipv6_addr_type include/net/ipv6.h:555 [inline] ip6_route_output_flags_noref net/ipv6/route.c:2616 [inline] ip6_route_output_flags+0x51/0x720 net/ipv6/route.c:2651 ip6_route_output include/net/ip6_route.h:93 [inline] ipvlan_route_v6_outbound+0x24e/0x520 drivers/net/ipvlan/ipvlan_core.c:476 ipvlan_process_v6_outbound drivers/net/ipvlan/ipvlan_core.c:491 [inline] ipvlan_process_outbound drivers/net/ipvlan/ipvlan_core.c:541 [inline] ipvlan_xmit_mode_l3 drivers/net/ipvlan/ipvlan_core.c:605 [inline] ipvlan_queue_xmit+0xd72/0x1780 drivers/net/ipvlan/ipvlan_core.c:671 ipvlan_start_xmit+0x5b/0x210 drivers/net/ipvlan/ipvlan_main.c:223 __netdev_start_xmit include/linux/netdevice.h:5150 [inline] netdev_start_xmit include/linux/netdevice.h:5159 [inline] xmit_one net/core/dev.c:3735 [inline] dev_hard_start_xmit+0x247/0xa20 net/core/dev.c:3751 sch_direct_xmit+0x399/0xd40 net/sched/sch_generic.c:343 qdisc_restart net/sched/sch_generic.c:408 [inline] __qdisc_run+0x14da/0x35d0 net/sched/sch_generic.c:416 qdisc_run+0x141/0x4d0 include/net/pkt_sched.h:127 net_tx_action+0x78b/0x940 net/core/dev.c:5484 handle_softirqs+0x1a0/0x7c0 kernel/softirq.c:561 __do_softirq+0x14/0x1a kernel/softirq.c:595 do_softirq+0x9a/0x100 kernel/softirq.c:462 __local_bh_enable_ip+0x9f/0xb0 kernel/softirq.c:389 local_bh_enable include/linux/bottom_half.h:33 [inline] rcu_read_unlock_bh include/linux/rcupdate.h:919 [inline] __dev_queue_xmit+0x2758/0x57d0 net/core/dev.c:4611 dev_queue_xmit include/linux/netdevice.h:3311 [inline] packet_xmit+0x9c/0x6c0 net/packet/af_packet.c:276 packet_snd net/packet/af_packet.c:3132 [inline] packet_sendmsg+0x93e0/0xa7e0 net/packet/af_packet.c:3164 sock_sendmsg_nosec net/socket.c:718 [inline] Fixes: 2ad7bf3 ("ipvlan: Initial check-in of the IPVLAN driver.") Reported-by: [email protected] Closes: https://lore.kernel.org/netdev/[email protected]/T/#u Signed-off-by: Eric Dumazet <[email protected]> Cc: Mahesh Bandewar <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent c180188 commit 27843ce

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

drivers/net/ipvlan/ipvlan_core.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,20 +416,25 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
416416

417417
static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb)
418418
{
419-
const struct iphdr *ip4h = ip_hdr(skb);
420419
struct net_device *dev = skb->dev;
421420
struct net *net = dev_net(dev);
422-
struct rtable *rt;
423421
int err, ret = NET_XMIT_DROP;
422+
const struct iphdr *ip4h;
423+
struct rtable *rt;
424424
struct flowi4 fl4 = {
425425
.flowi4_oif = dev->ifindex,
426-
.flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h)),
427426
.flowi4_flags = FLOWI_FLAG_ANYSRC,
428427
.flowi4_mark = skb->mark,
429-
.daddr = ip4h->daddr,
430-
.saddr = ip4h->saddr,
431428
};
432429

430+
if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
431+
goto err;
432+
433+
ip4h = ip_hdr(skb);
434+
fl4.daddr = ip4h->daddr;
435+
fl4.saddr = ip4h->saddr;
436+
fl4.flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h));
437+
433438
rt = ip_route_output_flow(net, &fl4, NULL);
434439
if (IS_ERR(rt))
435440
goto err;
@@ -488,6 +493,12 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
488493
struct net_device *dev = skb->dev;
489494
int err, ret = NET_XMIT_DROP;
490495

496+
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) {
497+
DEV_STATS_INC(dev, tx_errors);
498+
kfree_skb(skb);
499+
return ret;
500+
}
501+
491502
err = ipvlan_route_v6_outbound(dev, skb);
492503
if (unlikely(err)) {
493504
DEV_STATS_INC(dev, tx_errors);

0 commit comments

Comments
 (0)