diff options
author | Maurizio Lombardi <mlombard@redhat.com> | 2022-11-15 15:56:38 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-12-31 15:33:06 +0300 |
commit | 3ecdca49ca49d4770639d81503c873b6d25887c4 (patch) | |
tree | bc3e6d6dfab32bbd229233812e1ea58f67f1bf04 | |
parent | 04371a75a58422a301a9ff9ae3babd310ac3bb3f (diff) | |
download | linux-3ecdca49ca49d4770639d81503c873b6d25887c4.tar.xz |
scsi: target: iscsi: Fix a race condition between login_work and the login thread
[ Upstream commit fec1b2fa62c162d03f5dcd7b03e3c89d3116d49f ]
In case a malicious initiator sends some random data immediately after a
login PDU; the iscsi_target_sk_data_ready() callback will schedule the
login_work and, at the same time, the negotiation may end without clearing
the LOGIN_FLAGS_INITIAL_PDU flag (because no additional PDU exchanges are
required to complete the login).
The login has been completed but the login_work function will find the
LOGIN_FLAGS_INITIAL_PDU flag set and will never stop from rescheduling
itself; at this point, if the initiator drops the connection, the
iscsit_conn structure will be freed, login_work will dereference a released
socket structure and the kernel crashes.
BUG: kernel NULL pointer dereference, address: 0000000000000230
PF: supervisor write access in kernel mode
PF: error_code(0x0002) - not-present page
Workqueue: events iscsi_target_do_login_rx [iscsi_target_mod]
RIP: 0010:_raw_read_lock_bh+0x15/0x30
Call trace:
iscsi_target_do_login_rx+0x75/0x3f0 [iscsi_target_mod]
process_one_work+0x1e8/0x3c0
Fix this bug by forcing login_work to stop after the login has been
completed and the socket callbacks have been restored.
Add a comment to clearify the return values of iscsi_target_do_login()
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
Link: https://lore.kernel.org/r/20221115125638.102517-1-mlombard@redhat.com
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/target/iscsi/iscsi_target_nego.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index f2919319ad38..ff49c8f3fe24 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -1018,6 +1018,13 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_lo return 0; } +/* + * RETURN VALUE: + * + * 1 = Login successful + * -1 = Login failed + * 0 = More PDU exchanges required + */ static int iscsi_target_do_login(struct iscsit_conn *conn, struct iscsi_login *login) { int pdu_count = 0; @@ -1363,12 +1370,13 @@ int iscsi_target_start_negotiation( ret = -1; if (ret < 0) { - cancel_delayed_work_sync(&conn->login_work); iscsi_target_restore_sock_callbacks(conn); iscsi_remove_failed_auth_entry(conn); } - if (ret != 0) + if (ret != 0) { + cancel_delayed_work_sync(&conn->login_work); iscsi_target_nego_release(conn); + } return ret; } |