From: Mike Christie michael.christie@oracle.com
stable inclusion from stable-v5.10.112 commit 129db30599bc8b4a7cd0f219feb1e0154802e3d2 category: bugfix bugzilla: 188286, https://gitee.com/openeuler/kernel/issues/I67L59 CVE: NA
----------------------------------------
commit 0aadafb5c34403a7cced1a8d61877048dc059f70 upstream.
This patch fixes a bug where when using iSCSI offload we can free an endpoint while userspace still thinks it's active. That then causes the endpoint ID to be reused for a new connection's endpoint while userspace still thinks the ID is for the original connection. Userspace will then end up disconnecting a running connection's endpoint or trying to bind to another connection's endpoint.
This bug is a regression added in:
Commit 23d6fefbb3f6 ("scsi: iscsi: Fix in-kernel conn failure handling")
where we added a in kernel ep_disconnect call to fix a bug in:
Commit 0ab710458da1 ("scsi: iscsi: Perform connection failure entirely in kernel space")
where we would call stop_conn without having done ep_disconnect. This early ep_disconnect call will then free the endpoint and it's ID while userspace still thinks the ID is valid.
Fix the early release of the ID by having the in kernel recovery code keep a reference to the endpoint until userspace has called into the kernel to finish cleaning up the endpoint/connection. It requires the previous commit "scsi: iscsi: Release endpoint ID when its freed" which moved the freeing of the ID until when the endpoint is released.
Link: https://lore.kernel.org/r/20220408001314.5014-5-michael.christie@oracle.com Fixes: 23d6fefbb3f6 ("scsi: iscsi: Fix in-kernel conn failure handling") Tested-by: Manish Rangankar mrangankar@marvell.com Reviewed-by: Lee Duncan lduncan@suse.com Reviewed-by: Chris Leech cleech@redhat.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com --- drivers/scsi/scsi_transport_iscsi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index f0d0fd0e69ea..89a23983e57c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2259,7 +2259,11 @@ static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn, mutex_unlock(&conn->ep_mutex);
flush_work(&conn->cleanup_work); - + /* + * Userspace is now done with the EP so we can release the ref + * iscsi_cleanup_conn_work_fn took. + */ + iscsi_put_endpoint(ep); mutex_lock(&conn->ep_mutex); } } @@ -2341,6 +2345,12 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work) return; }
+ /* + * Get a ref to the ep, so we don't release its ID until after + * userspace is done referencing it in iscsi_if_disconnect_bound_ep. + */ + if (conn->ep) + get_device(&conn->ep->dev); iscsi_ep_disconnect(conn, false);
if (system_state != SYSTEM_RUNNING) {