Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6da7be7d authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Simon Wunderlich
Browse files

batman-adv: Fix debugfs path for renamed softif



batman-adv is creating special debugfs directories in the init
net_namespace for each created soft-interface (batadv net_device). But it
is possible to rename a net_device to a completely different name then the
original one.

It can therefore happen that a user registers a new batadv net_device with
the name "bat0". batman-adv is then also adding a new directory under
$debugfs/batman-adv/ with the name "wlan0".

The user then decides to rename this device to "bat1" and registers a
different batadv device with the name "bat0". batman-adv will then try to
create a directory with the name "bat0" under $debugfs/batman-adv/ again.
But there already exists one with this name under this path and thus this
fails. batman-adv will detect a problem and rollback the registering of
this device.

batman-adv must therefore take care of renaming the debugfs directories for
soft-interfaces whenever it detects such a net_device rename.

Fixes: c6c8fea2 ("net: Add batman-adv meshing protocol")
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
parent 36dc621c
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -433,6 +433,26 @@ int batadv_debugfs_add_meshif(struct net_device *dev)
	return -ENOMEM;
}

/**
 * batadv_debugfs_rename_meshif() - Fix debugfs path for renamed softif
 * @dev: net_device which was renamed
 */
void batadv_debugfs_rename_meshif(struct net_device *dev)
{
	struct batadv_priv *bat_priv = netdev_priv(dev);
	const char *name = dev->name;
	struct dentry *dir;
	struct dentry *d;

	dir = bat_priv->debug_dir;
	if (!dir)
		return;

	d = debugfs_rename(dir->d_parent, dir, dir->d_parent, name);
	if (!d)
		pr_err("Can't rename debugfs dir to %s\n", name);
}

/**
 * batadv_debugfs_del_meshif() - Remove interface dependent debugfs entries
 * @dev: netdev struct of the soft interface
+5 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ struct net_device;
void batadv_debugfs_init(void);
void batadv_debugfs_destroy(void);
int batadv_debugfs_add_meshif(struct net_device *dev);
void batadv_debugfs_rename_meshif(struct net_device *dev);
void batadv_debugfs_del_meshif(struct net_device *dev);
int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface);
void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface);
@@ -50,6 +51,10 @@ static inline int batadv_debugfs_add_meshif(struct net_device *dev)
	return 0;
}

static inline void batadv_debugfs_rename_meshif(struct net_device *dev)
{
}

static inline void batadv_debugfs_del_meshif(struct net_device *dev)
{
}
+28 −6
Original line number Diff line number Diff line
@@ -989,21 +989,43 @@ void batadv_hardif_remove_interfaces(void)
	rtnl_unlock();
}

static int batadv_hard_if_event(struct notifier_block *this,
				unsigned long event, void *ptr)
/**
 * batadv_hard_if_event_softif() - Handle events for soft interfaces
 * @event: NETDEV_* event to handle
 * @net_dev: net_device which generated an event
 *
 * Return: NOTIFY_* result
 */
static int batadv_hard_if_event_softif(unsigned long event,
				       struct net_device *net_dev)
{
	struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
	struct batadv_hard_iface *hard_iface;
	struct batadv_hard_iface *primary_if = NULL;
	struct batadv_priv *bat_priv;

	if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
	switch (event) {
	case NETDEV_REGISTER:
		batadv_sysfs_add_meshif(net_dev);
		bat_priv = netdev_priv(net_dev);
		batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);
		break;
	case NETDEV_CHANGENAME:
		batadv_debugfs_rename_meshif(net_dev);
		break;
	}

	return NOTIFY_DONE;
}

static int batadv_hard_if_event(struct notifier_block *this,
				unsigned long event, void *ptr)
{
	struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
	struct batadv_hard_iface *hard_iface;
	struct batadv_hard_iface *primary_if = NULL;
	struct batadv_priv *bat_priv;

	if (batadv_softif_is_valid(net_dev))
		return batadv_hard_if_event_softif(event, net_dev);

	hard_iface = batadv_hardif_get_by_netdev(net_dev);
	if (!hard_iface && (event == NETDEV_REGISTER ||
			    event == NETDEV_POST_TYPE_CHANGE))