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 "0000:00:10.0" >/sys/bus/pci/drivers/mlxsw_spectrum2/bind
devlink dev reload pci/0000:00:10.0 &
echo "0000:00:10.0" >/sys/bus/pci/drivers/mlxsw_spectrum2/unbind
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
0058b0a506
commit
5a508a254b
@@ -2699,7 +2699,7 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
|
||||
struct devlink *devlink = info->user_ptr[0];
|
||||
int err;
|
||||
|
||||
if (!devlink_reload_supported(devlink))
|
||||
if (!devlink_reload_supported(devlink) || !devlink->reload_enabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = devlink_resources_validate(devlink, NULL, info);
|
||||
@@ -6196,12 +6196,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
|
||||
*
|
||||
|
Reference in New Issue
Block a user