Skip to content

Commit acfa08d

Browse files
TaeheeYoointel-lab-lkp
authored andcommitted
ip_tunnel: fix use-after-free in ip_tunnel_lookup()
In the datapath, the ip_tunnel_lookup() is used and it internally uses fallback tunnel device pointer, which is fb_tunnel_dev. This pointer is protected by RTNL. It's not enough to be used in the datapath. So, this pointer would be used after an interface is deleted. It eventually results in the use-after-free problem. In order to avoid the problem, the new tunnel pointer variable is added, which indicates a fallback tunnel device's tunnel pointer. This is protected by both RTNL and RCU. So, it's safe to be used in the datapath. Test commands: ip netns add A ip netns add B ip link add eth0 type veth peer name eth1 ip link set eth0 netns A ip link set eth1 netns B ip netns exec A ip link set lo up ip netns exec A ip link set eth0 up ip netns exec A ip link add gre1 type gre local 10.0.0.1 \ remote 10.0.0.2 ip netns exec A ip link set gre1 up ip netns exec A ip a a 10.0.100.1/24 dev gre1 ip netns exec A ip a a 10.0.0.1/24 dev eth0 ip netns exec B ip link set lo up ip netns exec B ip link set eth1 up ip netns exec B ip link add gre1 type gre local 10.0.0.2 \ remote 10.0.0.1 ip netns exec B ip link set gre1 up ip netns exec B ip a a 10.0.100.2/24 dev gre1 ip netns exec B ip a a 10.0.0.2/24 dev eth1 ip netns exec A hping3 10.0.100.2 -2 --flood -d 60000 & ip netns del B Splat looks like: [ 133.319668][ C3] BUG: KASAN: use-after-free in ip_tunnel_lookup+0x9d6/0xde0 [ 133.343852][ C3] Read of size 4 at addr ffff8880b1701c84 by task hping3/1222 [ 133.344724][ C3] [ 133.345002][ C3] CPU: 3 PID: 1222 Comm: hping3 Not tainted 5.7.0+ torvalds#591 [ 133.345814][ C3] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 133.373336][ C3] Call Trace: [ 133.374792][ C3] <IRQ> [ 133.375205][ C3] dump_stack+0x96/0xdb [ 133.375789][ C3] print_address_description.constprop.6+0x2cc/0x450 [ 133.376720][ C3] ? ip_tunnel_lookup+0x9d6/0xde0 [ 133.377431][ C3] ? ip_tunnel_lookup+0x9d6/0xde0 [ 133.378130][ C3] ? ip_tunnel_lookup+0x9d6/0xde0 [ 133.378851][ C3] kasan_report+0x154/0x190 [ 133.379494][ C3] ? ip_tunnel_lookup+0x9d6/0xde0 [ 133.380200][ C3] ip_tunnel_lookup+0x9d6/0xde0 [ 133.380894][ C3] __ipgre_rcv+0x1ab/0xaa0 [ip_gre] [ 133.381630][ C3] ? rcu_read_lock_sched_held+0xc0/0xc0 [ 133.382429][ C3] gre_rcv+0x304/0x1910 [ip_gre] [ ... ] Fixes: c544193 ("GRE: Refactor GRE tunneling code.") Signed-off-by: Taehee Yoo <ap420073@gmail.com>
1 parent 96144c5 commit acfa08d

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

include/net/ip_tunnels.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ struct ip_tunnel_net {
164164
struct rtnl_link_ops *rtnl_link_ops;
165165
struct hlist_head tunnels[IP_TNL_HASH_SIZE];
166166
struct ip_tunnel __rcu *collect_md_tun;
167+
struct ip_tunnel __rcu *fb_tun;
167168
int type;
168169
};
169170

net/ipv4/ip_tunnel.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
162162
if (t && t->dev->flags & IFF_UP)
163163
return t;
164164

165-
if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP)
166-
return netdev_priv(itn->fb_tunnel_dev);
165+
t = rcu_dereference(itn->fb_tun);
166+
if (t && t->dev->flags & IFF_UP)
167+
return t;
167168

168169
return NULL;
169170
}
@@ -1059,6 +1060,7 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
10591060
it_init_net = net_generic(&init_net, ip_tnl_net_id);
10601061
itn->type = it_init_net->type;
10611062
itn->fb_tunnel_dev = NULL;
1063+
RCU_INIT_POINTER(itn->fb_tun, NULL);
10621064
return 0;
10631065
}
10641066

@@ -1074,8 +1076,9 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
10741076
if (!IS_ERR(itn->fb_tunnel_dev)) {
10751077
itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
10761078
itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev);
1077-
ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
10781079
itn->type = itn->fb_tunnel_dev->type;
1080+
rcu_assign_pointer(itn->fb_tun,
1081+
netdev_priv(itn->fb_tunnel_dev));
10791082
}
10801083
rtnl_unlock();
10811084

@@ -1262,6 +1265,8 @@ void ip_tunnel_uninit(struct net_device *dev)
12621265
/* fb_tunnel_dev will be unregisted in net-exit call. */
12631266
if (itn->fb_tunnel_dev != dev)
12641267
ip_tunnel_del(itn, netdev_priv(dev));
1268+
else
1269+
rcu_assign_pointer(itn->fb_tun, NULL);
12651270

12661271
dst_cache_reset(&tunnel->dst_cache);
12671272
}

0 commit comments

Comments
 (0)