devlink: disallow reload operation during device cleanup
There is a race between driver code that does setup/cleanup of device
and devlink reload operation that in some drivers works with the same
code. Use after free could we easily obtained by running:
while true; do
echo 10 > /sys/bus/netdevsim/new_device
devlink dev reload netdevsim/netdevsim10 &
echo 10 > /sys/bus/netdevsim/del_device
done
Fix this by enabling reload only after setup of device is complete and
disabling it at the beginning of the cleanup process.
Reported-by: Ido Schimmel <idosch@mellanox.com>
Fixes: 2d8dc5bbf4
("devlink: Add support for reload")
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
f95e6c9c46
commit
a0c76345e3
@@ -2791,6 +2791,9 @@ static int devlink_reload(struct devlink *devlink, struct net *dest_net,
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!devlink->reload_enabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = devlink->ops->reload_down(devlink, !!dest_net, extack);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -6308,12 +6311,49 @@ EXPORT_SYMBOL_GPL(devlink_register);
|
||||
void devlink_unregister(struct devlink *devlink)
|
||||
{
|
||||
mutex_lock(&devlink_mutex);
|
||||
WARN_ON(devlink_reload_supported(devlink) &&
|
||||
devlink->reload_enabled);
|
||||
devlink_notify(devlink, DEVLINK_CMD_DEL);
|
||||
list_del(&devlink->list);
|
||||
mutex_unlock(&devlink_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_unregister);
|
||||
|
||||
/**
|
||||
* devlink_reload_enable - Enable reload of devlink instance
|
||||
*
|
||||
* @devlink: devlink
|
||||
*
|
||||
* Should be called at end of device initialization
|
||||
* process when reload operation is supported.
|
||||
*/
|
||||
void devlink_reload_enable(struct devlink *devlink)
|
||||
{
|
||||
mutex_lock(&devlink_mutex);
|
||||
devlink->reload_enabled = true;
|
||||
mutex_unlock(&devlink_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_reload_enable);
|
||||
|
||||
/**
|
||||
* devlink_reload_disable - Disable reload of devlink instance
|
||||
*
|
||||
* @devlink: devlink
|
||||
*
|
||||
* Should be called at the beginning of device cleanup
|
||||
* process when reload operation is supported.
|
||||
*/
|
||||
void devlink_reload_disable(struct devlink *devlink)
|
||||
{
|
||||
mutex_lock(&devlink_mutex);
|
||||
/* Mutex is taken which ensures that no reload operation is in
|
||||
* progress while setting up forbidded flag.
|
||||
*/
|
||||
devlink->reload_enabled = false;
|
||||
mutex_unlock(&devlink_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_reload_disable);
|
||||
|
||||
/**
|
||||
* devlink_free - Free devlink instance resources
|
||||
*
|
||||
@@ -8201,7 +8241,7 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net)
|
||||
if (WARN_ON(!devlink_reload_supported(devlink)))
|
||||
continue;
|
||||
err = devlink_reload(devlink, &init_net, NULL);
|
||||
if (err)
|
||||
if (err && err != -EOPNOTSUPP)
|
||||
pr_warn("Failed to reload devlink instance into init_net\n");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user