nvmet: Fix use-after-free bug when a port is removed
When a port is removed through configfs, any connected controllers are still active and can still send commands. This causes a use-after-free bug which is detected by KASAN for any admin command that dereferences req->port (like in nvmet_execute_identify_ctrl). To fix this, disconnect all active controllers when a subsystem is removed from a port. This ensures there are no active controllers when the port is eventually removed. Signed-off-by: Logan Gunthorpe <logang@deltatee.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Max Gurtovoy <maxg@mellanox.com> Reviewed-by : Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
This commit is contained in:
parent
fab7772bfb
commit
3aed86731e
|
@ -675,6 +675,7 @@ static void nvmet_port_subsys_drop_link(struct config_item *parent,
|
|||
|
||||
found:
|
||||
list_del(&p->entry);
|
||||
nvmet_port_del_ctrls(port, subsys);
|
||||
nvmet_port_disc_changed(port, subsys);
|
||||
|
||||
if (list_empty(&port->subsystems))
|
||||
|
|
|
@ -280,6 +280,18 @@ void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nvmet_unregister_transport);
|
||||
|
||||
void nvmet_port_del_ctrls(struct nvmet_port *port, struct nvmet_subsys *subsys)
|
||||
{
|
||||
struct nvmet_ctrl *ctrl;
|
||||
|
||||
mutex_lock(&subsys->lock);
|
||||
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
|
||||
if (ctrl->port == port)
|
||||
ctrl->ops->delete_ctrl(ctrl);
|
||||
}
|
||||
mutex_unlock(&subsys->lock);
|
||||
}
|
||||
|
||||
int nvmet_enable_port(struct nvmet_port *port)
|
||||
{
|
||||
const struct nvmet_fabrics_ops *ops;
|
||||
|
|
|
@ -418,6 +418,9 @@ void nvmet_port_send_ana_event(struct nvmet_port *port);
|
|||
int nvmet_register_transport(const struct nvmet_fabrics_ops *ops);
|
||||
void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops);
|
||||
|
||||
void nvmet_port_del_ctrls(struct nvmet_port *port,
|
||||
struct nvmet_subsys *subsys);
|
||||
|
||||
int nvmet_enable_port(struct nvmet_port *port);
|
||||
void nvmet_disable_port(struct nvmet_port *port);
|
||||
|
||||
|
|
Loading…
Reference in New Issue