Skip to content

Commit 0ce1822

Browse files
TaeheeYoodavem330
authored andcommitted
vxlan: add adjacent link to limit depth level
Current vxlan code doesn't limit the number of nested devices. Nested devices would be handled recursively and this routine needs huge stack memory. So, unlimited nested devices could make stack overflow. In order to fix this issue, this patch adds adjacent links. The adjacent link APIs internally check the depth level. Test commands: ip link add dummy0 type dummy ip link add vxlan0 type vxlan id 0 group 239.1.1.1 dev dummy0 \ dstport 4789 for i in {1..100} do let A=$i-1 ip link add vxlan$i type vxlan id $i group 239.1.1.1 \ dev vxlan$A dstport 4789 done ip link del dummy0 The top upper link is vxlan100 and the lowest link is vxlan0. When vxlan0 is deleting, the upper devices will be deleted recursively. It needs huge stack memory so it makes stack overflow. Splat looks like: [ 229.628477] ============================================================================= [ 229.629785] BUG page->ptl (Not tainted): Padding overwritten. 0x0000000026abf214-0x0000000091f6abb2 [ 229.629785] ----------------------------------------------------------------------------- [ 229.629785] [ 229.655439] ================================================================== [ 229.629785] INFO: Slab 0x00000000ff7cfda8 objects=19 used=19 fp=0x00000000fe33776c flags=0x200000000010200 [ 229.655688] BUG: KASAN: stack-out-of-bounds in unmap_single_vma+0x25a/0x2e0 [ 229.655688] Read of size 8 at addr ffff888113076928 by task vlan-network-in/2334 [ 229.655688] [ 229.629785] Padding 0000000026abf214: 00 80 14 0d 81 88 ff ff 68 91 81 14 81 88 ff ff ........h....... [ 229.629785] Padding 0000000001e24790: 38 91 81 14 81 88 ff ff 68 91 81 14 81 88 ff ff 8.......h....... [ 229.629785] Padding 00000000b39397c8: 33 30 62 a7 ff ff ff ff ff eb 60 22 10 f1 ff 1f 30b.......`".... [ 229.629785] Padding 00000000bc98f53a: 80 60 07 13 81 88 ff ff 00 80 14 0d 81 88 ff ff .`.............. [ 229.629785] Padding 000000002aa8123d: 68 91 81 14 81 88 ff ff f7 21 17 a7 ff ff ff ff h........!...... [ 229.629785] Padding 000000001c8c2369: 08 81 14 0d 81 88 ff ff 03 02 00 00 00 00 00 00 ................ [ 229.629785] Padding 000000004e290c5d: 21 90 a2 21 10 ed ff ff 00 00 00 00 00 fc ff df !..!............ [ 229.629785] Padding 000000000e25d731: 18 60 07 13 81 88 ff ff c0 8b 13 05 81 88 ff ff .`.............. [ 229.629785] Padding 000000007adc7ab3: b3 8a b5 41 00 00 00 00 ...A.... [ 229.629785] FIX page->ptl: Restoring 0x0000000026abf214-0x0000000091f6abb2=0x5a [ ... ] Fixes: acaf4e7 ("net: vxlan: when lower dev unregisters remove vxlan dev as well") Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 32b6d34 commit 0ce1822

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

drivers/net/vxlan.c

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3566,25 +3566,28 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
35663566
{
35673567
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
35683568
struct vxlan_dev *vxlan = netdev_priv(dev);
3569+
struct net_device *remote_dev = NULL;
35693570
struct vxlan_fdb *f = NULL;
35703571
bool unregister = false;
3572+
struct vxlan_rdst *dst;
35713573
int err;
35723574

3575+
dst = &vxlan->default_dst;
35733576
err = vxlan_dev_configure(net, dev, conf, false, extack);
35743577
if (err)
35753578
return err;
35763579

35773580
dev->ethtool_ops = &vxlan_ethtool_ops;
35783581

35793582
/* create an fdb entry for a valid default destination */
3580-
if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
3583+
if (!vxlan_addr_any(&dst->remote_ip)) {
35813584
err = vxlan_fdb_create(vxlan, all_zeros_mac,
3582-
&vxlan->default_dst.remote_ip,
3585+
&dst->remote_ip,
35833586
NUD_REACHABLE | NUD_PERMANENT,
35843587
vxlan->cfg.dst_port,
3585-
vxlan->default_dst.remote_vni,
3586-
vxlan->default_dst.remote_vni,
3587-
vxlan->default_dst.remote_ifindex,
3588+
dst->remote_vni,
3589+
dst->remote_vni,
3590+
dst->remote_ifindex,
35883591
NTF_SELF, &f);
35893592
if (err)
35903593
return err;
@@ -3595,26 +3598,41 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
35953598
goto errout;
35963599
unregister = true;
35973600

3601+
if (dst->remote_ifindex) {
3602+
remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
3603+
if (!remote_dev)
3604+
goto errout;
3605+
3606+
err = netdev_upper_dev_link(remote_dev, dev, extack);
3607+
if (err)
3608+
goto errout;
3609+
}
3610+
35983611
err = rtnl_configure_link(dev, NULL);
35993612
if (err)
3600-
goto errout;
3613+
goto unlink;
36013614

36023615
if (f) {
3603-
vxlan_fdb_insert(vxlan, all_zeros_mac,
3604-
vxlan->default_dst.remote_vni, f);
3616+
vxlan_fdb_insert(vxlan, all_zeros_mac, dst->remote_vni, f);
36053617

36063618
/* notify default fdb entry */
36073619
err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f),
36083620
RTM_NEWNEIGH, true, extack);
36093621
if (err) {
36103622
vxlan_fdb_destroy(vxlan, f, false, false);
3623+
if (remote_dev)
3624+
netdev_upper_dev_unlink(remote_dev, dev);
36113625
goto unregister;
36123626
}
36133627
}
36143628

36153629
list_add(&vxlan->next, &vn->vxlan_list);
3630+
if (remote_dev)
3631+
dst->remote_dev = remote_dev;
36163632
return 0;
3617-
3633+
unlink:
3634+
if (remote_dev)
3635+
netdev_upper_dev_unlink(remote_dev, dev);
36183636
errout:
36193637
/* unregister_netdevice() destroys the default FDB entry with deletion
36203638
* notification. But the addition notification was not sent yet, so
@@ -3932,11 +3950,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
39323950
struct netlink_ext_ack *extack)
39333951
{
39343952
struct vxlan_dev *vxlan = netdev_priv(dev);
3935-
struct vxlan_rdst *dst = &vxlan->default_dst;
39363953
struct net_device *lowerdev;
39373954
struct vxlan_config conf;
3955+
struct vxlan_rdst *dst;
39383956
int err;
39393957

3958+
dst = &vxlan->default_dst;
39403959
err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
39413960
if (err)
39423961
return err;
@@ -3946,6 +3965,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
39463965
if (err)
39473966
return err;
39483967

3968+
err = netdev_adjacent_change_prepare(dst->remote_dev, lowerdev, dev,
3969+
extack);
3970+
if (err)
3971+
return err;
3972+
39493973
/* handle default dst entry */
39503974
if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
39513975
u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni);
@@ -3962,6 +3986,8 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
39623986
NTF_SELF, true, extack);
39633987
if (err) {
39643988
spin_unlock_bh(&vxlan->hash_lock[hash_index]);
3989+
netdev_adjacent_change_abort(dst->remote_dev,
3990+
lowerdev, dev);
39653991
return err;
39663992
}
39673993
}
@@ -3979,6 +4005,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
39794005
if (conf.age_interval != vxlan->cfg.age_interval)
39804006
mod_timer(&vxlan->age_timer, jiffies);
39814007

4008+
netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev);
4009+
if (lowerdev && lowerdev != dst->remote_dev)
4010+
dst->remote_dev = lowerdev;
4011+
4012+
netdev_update_lockdep_key(lowerdev);
39824013
vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
39834014
return 0;
39844015
}
@@ -3991,6 +4022,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
39914022

39924023
list_del(&vxlan->next);
39934024
unregister_netdevice_queue(dev, head);
4025+
if (vxlan->default_dst.remote_dev)
4026+
netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev);
39944027
}
39954028

39964029
static size_t vxlan_get_size(const struct net_device *dev)

include/net/vxlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ struct vxlan_rdst {
197197
u8 offloaded:1;
198198
__be32 remote_vni;
199199
u32 remote_ifindex;
200+
struct net_device *remote_dev;
200201
struct list_head list;
201202
struct rcu_head rcu;
202203
struct dst_cache dst_cache;

0 commit comments

Comments
 (0)