Skip to content

Commit d89d7ff

Browse files
edumazetkuba-moo
authored andcommitted
ipv6: ensure sane device mtu in tunnels
Another syzbot report [1] with no reproducer hints at a bug in ip6_gre tunnel (dev:ip6gretap0) Since ipv6 mcast code makes sure to read dev->mtu once and applies a sanity check on it (see commit b9b312a "ipv6: mcast: better catch silly mtu values"), a remaining possibility is that a layer is able to set dev->mtu to an underflowed value (high order bit set). This could happen indeed in ip6gre_tnl_link_config_route(), ip6_tnl_link_config() and ipip6_tunnel_bind_dev() Make sure to sanitize mtu value in a local variable before it is written once on dev->mtu, as lockless readers could catch wrong temporary value. [1] skbuff: skb_over_panic: text:ffff80000b7a2f38 len:40 put:40 head:ffff000149dcf200 data:ffff000149dcf2b0 tail:0xd8 end:0xc0 dev:ip6gretap0 ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:120 Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP Modules linked in: CPU: 1 PID: 10241 Comm: kworker/1:1 Not tainted 6.0.0-rc7-syzkaller-18095-gbbed346d5a96 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/30/2022 Workqueue: mld mld_ifc_work pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : skb_panic+0x4c/0x50 net/core/skbuff.c:116 lr : skb_panic+0x4c/0x50 net/core/skbuff.c:116 sp : ffff800020dd3b60 x29: ffff800020dd3b70 x28: 0000000000000000 x27: ffff00010df2a800 x26: 00000000000000c0 x25: 00000000000000b0 x24: ffff000149dcf200 x23: 00000000000000c0 x22: 00000000000000d8 x21: ffff80000b7a2f38 x20: ffff00014c2f7800 x19: 0000000000000028 x18: 00000000000001a9 x17: 0000000000000000 x16: ffff80000db49158 x15: ffff000113bf1a80 x14: 0000000000000000 x13: 00000000ffffffff x12: ffff000113bf1a80 x11: ff808000081c0d5c x10: 0000000000000000 x9 : 73f125dc5c63ba00 x8 : 73f125dc5c63ba00 x7 : ffff800008161d1c x6 : 0000000000000000 x5 : 0000000000000080 x4 : 0000000000000001 x3 : 0000000000000000 x2 : ffff0001fefddcd0 x1 : 0000000100000000 x0 : 0000000000000089 Call trace: skb_panic+0x4c/0x50 net/core/skbuff.c:116 skb_over_panic net/core/skbuff.c:125 [inline] skb_put+0xd4/0xdc net/core/skbuff.c:2049 ip6_mc_hdr net/ipv6/mcast.c:1714 [inline] mld_newpack+0x14c/0x270 net/ipv6/mcast.c:1765 add_grhead net/ipv6/mcast.c:1851 [inline] add_grec+0xa20/0xae0 net/ipv6/mcast.c:1989 mld_send_cr+0x438/0x5a8 net/ipv6/mcast.c:2115 mld_ifc_work+0x38/0x290 net/ipv6/mcast.c:2653 process_one_work+0x2d8/0x504 kernel/workqueue.c:2289 worker_thread+0x340/0x610 kernel/workqueue.c:2436 kthread+0x12c/0x158 kernel/kthread.c:376 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:860 Code: 91011400 aa0803e1 a90027ea 94373093 (d4210000) Fixes: c12b395 ("gre: Support GRE over IPv6") Reported-by: syzbot <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 88619e7 commit d89d7ff

File tree

3 files changed

+18
-13
lines changed

3 files changed

+18
-13
lines changed

net/ipv6/ip6_gre.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,14 +1175,16 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
11751175
dev->needed_headroom = dst_len;
11761176

11771177
if (set_mtu) {
1178-
dev->mtu = rt->dst.dev->mtu - t_hlen;
1178+
int mtu = rt->dst.dev->mtu - t_hlen;
1179+
11791180
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
1180-
dev->mtu -= 8;
1181+
mtu -= 8;
11811182
if (dev->type == ARPHRD_ETHER)
1182-
dev->mtu -= ETH_HLEN;
1183+
mtu -= ETH_HLEN;
11831184

1184-
if (dev->mtu < IPV6_MIN_MTU)
1185-
dev->mtu = IPV6_MIN_MTU;
1185+
if (mtu < IPV6_MIN_MTU)
1186+
mtu = IPV6_MIN_MTU;
1187+
WRITE_ONCE(dev->mtu, mtu);
11861188
}
11871189
}
11881190
ip6_rt_put(rt);

net/ipv6/ip6_tunnel.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,8 +1450,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
14501450
struct net_device *tdev = NULL;
14511451
struct __ip6_tnl_parm *p = &t->parms;
14521452
struct flowi6 *fl6 = &t->fl.u.ip6;
1453-
unsigned int mtu;
14541453
int t_hlen;
1454+
int mtu;
14551455

14561456
__dev_addr_set(dev, &p->laddr, sizeof(struct in6_addr));
14571457
memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
@@ -1498,12 +1498,13 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
14981498
dev->hard_header_len = tdev->hard_header_len + t_hlen;
14991499
mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU);
15001500

1501-
dev->mtu = mtu - t_hlen;
1501+
mtu = mtu - t_hlen;
15021502
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
1503-
dev->mtu -= 8;
1503+
mtu -= 8;
15041504

1505-
if (dev->mtu < IPV6_MIN_MTU)
1506-
dev->mtu = IPV6_MIN_MTU;
1505+
if (mtu < IPV6_MIN_MTU)
1506+
mtu = IPV6_MIN_MTU;
1507+
WRITE_ONCE(dev->mtu, mtu);
15071508
}
15081509
}
15091510
}

net/ipv6/sit.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,10 +1124,12 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
11241124

11251125
if (tdev && !netif_is_l3_master(tdev)) {
11261126
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1127+
int mtu;
11271128

1128-
dev->mtu = tdev->mtu - t_hlen;
1129-
if (dev->mtu < IPV6_MIN_MTU)
1130-
dev->mtu = IPV6_MIN_MTU;
1129+
mtu = tdev->mtu - t_hlen;
1130+
if (mtu < IPV6_MIN_MTU)
1131+
mtu = IPV6_MIN_MTU;
1132+
WRITE_ONCE(dev->mtu, mtu);
11311133
}
11321134
}
11331135

0 commit comments

Comments
 (0)