Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 233c7df

Browse files
jpirkodavem330
authored andcommitted
macvlan: fix passthru mode race between dev removal and rx path
Currently, if macvlan in passthru mode is created and data are rxed and you remove this device, following panic happens: NULL pointer dereference at 0000000000000198 IP: [<ffffffffa0196058>] macvlan_handle_frame+0x153/0x1f7 [macvlan] I'm using following script to trigger this: <script> while [ 1 ] do ip link add link e1 name macvtap0 type macvtap mode passthru ip link set e1 up ip link set macvtap0 up IFINDEX=`ip link |grep macvtap0 | cut -f 1 -d ':'` cat /dev/tap$IFINDEX >/dev/null & ip link del dev macvtap0 done </script> I run this script while "ping -f" is running on another machine to send packets to e1 rx. Reason of the panic is that list_first_entry() is blindly called in macvlan_handle_frame() even if the list was empty. vlan is set to incorrect pointer which leads to the crash. I'm fixing this by protecting port->vlans list by rcu and by preventing from getting incorrect pointer in case the list is empty. Introduced by: commit eb06acd "macvlan: Introduce 'passthru' mode to takeover the underlying device" Signed-off-by: Jiri Pirko <[email protected]> Acked-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fb863b8 commit 233c7df

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

drivers/net/macvlan.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
229229
}
230230

231231
if (port->passthru)
232-
vlan = list_first_entry(&port->vlans, struct macvlan_dev, list);
232+
vlan = list_first_or_null_rcu(&port->vlans,
233+
struct macvlan_dev, list);
233234
else
234235
vlan = macvlan_hash_lookup(port, eth->h_dest);
235236
if (vlan == NULL)
@@ -814,7 +815,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
814815
if (err < 0)
815816
goto upper_dev_unlink;
816817

817-
list_add_tail(&vlan->list, &port->vlans);
818+
list_add_tail_rcu(&vlan->list, &port->vlans);
818819
netif_stacked_transfer_operstate(lowerdev, dev);
819820

820821
return 0;
@@ -842,7 +843,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head)
842843
{
843844
struct macvlan_dev *vlan = netdev_priv(dev);
844845

845-
list_del(&vlan->list);
846+
list_del_rcu(&vlan->list);
846847
unregister_netdevice_queue(dev, head);
847848
netdev_upper_dev_unlink(vlan->lowerdev, dev);
848849
}

0 commit comments

Comments
 (0)