scsi: libiscsi: Fix UAF in iscsi_conn_get_param()/iscsi_conn_teardown()

[ Upstream commit 1b8d0300a3e9f216ae4901bab886db7299899ec6 ]

|- iscsi_if_destroy_conn            |-dev_attr_show
 |-iscsi_conn_teardown
  |-spin_lock_bh                     |-iscsi_sw_tcp_conn_get_param

  |-kfree(conn->persistent_address)   |-iscsi_conn_get_param
  |-kfree(conn->local_ipaddr)
                                       ==>|-read persistent_address
                                       ==>|-read local_ipaddr
  |-spin_unlock_bh

When iscsi_conn_teardown() and iscsi_conn_get_param() happen in parallel, a
UAF may be triggered.

Link: https://lore.kernel.org/r/046ec8a0-ce95-d3fc-3235-666a7c65b224@huawei.com
Reported-by: Lu Tixiong <lutianxiong@huawei.com>
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Lee Duncan <lduncan@suse.com>
Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Lixiaokeng 2021-12-20 19:39:06 +08:00 committed by Greg Kroah-Hartman
parent 6a3ffcc9ff
commit 8b36aa5af4

View File

@ -2948,6 +2948,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
{ {
struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session; struct iscsi_session *session = conn->session;
char *tmp_persistent_address = conn->persistent_address;
char *tmp_local_ipaddr = conn->local_ipaddr;
del_timer_sync(&conn->transport_timer); del_timer_sync(&conn->transport_timer);
@ -2969,8 +2971,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
spin_lock_bh(&session->frwd_lock); spin_lock_bh(&session->frwd_lock);
free_pages((unsigned long) conn->data, free_pages((unsigned long) conn->data,
get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
kfree(conn->persistent_address);
kfree(conn->local_ipaddr);
/* regular RX path uses back_lock */ /* regular RX path uses back_lock */
spin_lock_bh(&session->back_lock); spin_lock_bh(&session->back_lock);
kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
@ -2982,6 +2982,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
mutex_unlock(&session->eh_mutex); mutex_unlock(&session->eh_mutex);
iscsi_destroy_conn(cls_conn); iscsi_destroy_conn(cls_conn);
kfree(tmp_persistent_address);
kfree(tmp_local_ipaddr);
} }
EXPORT_SYMBOL_GPL(iscsi_conn_teardown); EXPORT_SYMBOL_GPL(iscsi_conn_teardown);