[PATCH V2] target: fix a race condition between login_work and the login thread

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.
Also fix other potential race conditions in the error paths.

V2: remove an unnecessary call to cancel_delayed_work();
    fix a potential race condition in iscsi_start_negotiation() and
    in iscsi_target_do_login_rx()'s error paths

Signed-off-by: Maurizio Lombardi <mlombard@xxxxxxxxxx>
---
 drivers/target/iscsi/iscsi_target_nego.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index f2919319ad38..465c53b9ddb3 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -645,7 +645,6 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
 						    LOGIN_FLAGS_WRITE_ACTIVE))
 			goto err;
 	} else if (rc == 1) {
-		cancel_delayed_work(&conn->login_work);
 		iscsi_target_nego_release(conn);
 		iscsi_post_login_handler(np, conn, zero_tsih);
 		iscsit_deaccess_np(np, tpg, tpg_np);
@@ -654,7 +653,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
 
 err:
 	iscsi_target_restore_sock_callbacks(conn);
-	cancel_delayed_work(&conn->login_work);
+	cancel_delayed_work_sync(&conn->login_work);
 	iscsi_target_login_drop(conn, login);
 	iscsit_deaccess_np(np, tpg, tpg_np);
 }
@@ -1058,6 +1057,7 @@ static int iscsi_target_do_login(struct iscsit_conn *conn, struct iscsi_login *l
 				login->tsih = conn->sess->tsih;
 				login->login_complete = 1;
 				iscsi_target_restore_sock_callbacks(conn);
+				cancel_delayed_work_sync(&conn->login_work);
 				if (iscsi_target_do_tx_login_io(conn,
 						login) < 0)
 					return -1;
@@ -1363,8 +1363,8 @@ int iscsi_target_start_negotiation(
 		ret = -1;
 
 	if (ret < 0) {
-		cancel_delayed_work_sync(&conn->login_work);
 		iscsi_target_restore_sock_callbacks(conn);
+		cancel_delayed_work_sync(&conn->login_work);
 		iscsi_remove_failed_auth_entry(conn);
 	}
 	if (ret != 0)
-- 
2.31.1




[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux