mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
batman-adv: clean untagged VLAN on netdev registration failure
commit8669a550c7upstream. When an mesh interface is registered, it creates an untagged struct batadv_meshif_vlan on top of it via the NETDEV_REGISTER notifier. But in this process, another receiver of this notification can veto the registration. The netdev registration will be aborted because of this veto. The register_netdevice() call will try to clean up the net_device using unregister_netdevice_queue() - which only uses the .priv_destructor to free private resources. In this situation, .dellink will not be called. The cleanup of the untagged batadv_meshif_vlan must thefore be done in the destructor to avoid a leak of this object. Cc: stable@vger.kernel.org Fixes:5d2c05b213("batman-adv: add per VLAN interface attribute framework") [ switch to old "mesh_iface" name "soft_iface" ] Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e6640923af
commit
f2423da559
@@ -258,6 +258,7 @@ err_orig:
|
||||
void batadv_mesh_free(struct net_device *soft_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
struct batadv_softif_vlan *vlan;
|
||||
|
||||
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
|
||||
|
||||
@@ -273,6 +274,13 @@ void batadv_mesh_free(struct net_device *soft_iface)
|
||||
|
||||
batadv_mcast_free(bat_priv);
|
||||
|
||||
/* destroy the "untagged" VLAN */
|
||||
vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS);
|
||||
if (vlan) {
|
||||
batadv_softif_destroy_vlan(bat_priv, vlan);
|
||||
batadv_softif_vlan_put(vlan);
|
||||
}
|
||||
|
||||
/* Free the TT and the originator tables only after having terminated
|
||||
* all the other depending components which may use these structures for
|
||||
* their purposes.
|
||||
|
||||
@@ -603,8 +603,8 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @vlan: the object to remove
|
||||
*/
|
||||
static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
|
||||
struct batadv_softif_vlan *vlan)
|
||||
void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
|
||||
struct batadv_softif_vlan *vlan)
|
||||
{
|
||||
/* explicitly remove the associated TT local entry because it is marked
|
||||
* with the NOPURGE flag
|
||||
@@ -1086,22 +1086,13 @@ static int batadv_softif_newlink(struct net *src_net, struct net_device *dev,
|
||||
static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
|
||||
list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
|
||||
if (hard_iface->soft_iface == soft_iface)
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
}
|
||||
|
||||
/* destroy the "untagged" VLAN */
|
||||
vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS);
|
||||
if (vlan) {
|
||||
batadv_softif_destroy_vlan(bat_priv, vlan);
|
||||
batadv_softif_vlan_put(vlan);
|
||||
}
|
||||
|
||||
unregister_netdevice_queue(soft_iface, head);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
|
||||
bool batadv_softif_is_valid(const struct net_device *net_dev);
|
||||
extern struct rtnl_link_ops batadv_link_ops;
|
||||
int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
|
||||
void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
|
||||
struct batadv_softif_vlan *vlan);
|
||||
void batadv_softif_vlan_release(struct kref *ref);
|
||||
struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
|
||||
unsigned short vid);
|
||||
|
||||
Reference in New Issue
Block a user