On Mon, 22 Jan 2024 10:45:30 +0200 Danielle Ratson wrote: > #include <linux/ethtool.h> > +#include <linux/sfp.h> > +#include <linux/firmware.h> alphabetical order, please > +static int > +module_flash_fw_schedule(struct net_device *dev, > + struct ethtool_module_fw_flash_params *params, > + struct netlink_ext_ack *extack) > +{ > + const struct ethtool_ops *ops = dev->ethtool_ops; > + struct ethtool_module_fw_flash *module_fw; > + int err; > + > + if (!ops->set_module_eeprom_by_page || > + !ops->get_module_eeprom_by_page) { > + NL_SET_ERR_MSG(extack, > + "Flashing module firmware is not supported by this device"); > + return -EOPNOTSUPP; > + } > + > + if (dev->module_fw_flash_in_progress) { > + NL_SET_ERR_MSG(extack, "Module firmware flashing already in progress"); > + return -EBUSY; > + } > + > + module_fw = kzalloc(sizeof(*module_fw), GFP_KERNEL); > + if (!module_fw) > + return -ENOMEM; > + > + module_fw->params = *params; > + err = request_firmware(&module_fw->fw, module_fw->params.file_name, request_firmware_direct() ? I think udev timeout is 30 sec and we're holding rtnl_lock.. I don't remember why we didn't use that in devlink > + &dev->dev); > + if (err) { > + NL_SET_ERR_MSG(extack, > + "Failed to request module firmware image"); > + goto err_request_firmware; > + } > + > + err = module_flash_fw_work_init(module_fw, dev, extack); > + if (err < 0) { > + NL_SET_ERR_MSG(extack, > + "Flashing module firmware is not supported by this device"); > + goto err_work_init; > + } > + > + dev->module_fw_flash_in_progress = true; What does this protect us from? > +static int module_flash_fw(struct net_device *dev, struct nlattr **tb, > + struct netlink_ext_ack *extack) > +{ > + struct ethtool_module_fw_flash_params params = {}; > + struct nlattr *attr; > + > + if (!tb[ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME]) { > + NL_SET_ERR_MSG_ATTR(extack, GENL_REQ_ATTR_CHECK, and you can check it in the caller, before taking rtnl_lock. > + tb[ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME], > + "File name attribute is missing"); > + return -EINVAL; > + } > + > + params.file_name = > + nla_data(tb[ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME]); Hm. I think you copy the param struct by value to the work container. nla_data() is in the skb which is going to get freed after _ACT returns. So if anyone tries to access the name from the work it's going to UAF? > + > + attr = tb[ETHTOOL_A_MODULE_FW_FLASH_PASSWORD]; > + if (attr) { > + params.password = cpu_to_be32(nla_get_u32(attr)); > + params.password_valid = true; > + } > + > + return module_flash_fw_schedule(dev, ¶ms, extack); > +}