Re: [PATCH 02/15] Fix use-after-free for task management requests

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

 



On Fri, 12 Jun 2009 11:35:49 +0900
FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx> wrote:

> On Tue, 09 Jun 2009 18:21:53 +0200
> Arne Redlich <arne.redlich@xxxxxxxxxxxxxx> wrote:
> 
> > If a task management request for a command that is already processed is
> > received, the tm req will wait for the command to finish. If meanwhile the
> > connection is closed (as a means of error recovery), the tm req might be
> > freed prematurely, which will lead to a use-after-free upon completion of the
> > task.
> > 
> > Signed-off-by: Arne Redlich <arne.redlich@xxxxxxxxxxxxxx>
> > ---
> >  usr/iscsi/iscsid.c |   18 +++++++++++++++---
> >  usr/iscsi/iscsid.h |    1 +
> >  usr/target.c       |   19 +++++++++++++------
> >  usr/tgtd.h         |   14 +++++++++++---
> >  4 files changed, 40 insertions(+), 12 deletions(-)
> 
> I think that this patch is correct however, we don't need
> task->conn->state checking in iscsi_tm_done() to free tm req (as
> iscsi_scsi_cmd_done does)?

Sorry for the delay, I've merged this with some cleanups.

The following patch was merged:

=
From: Arne Redlich <arne.redlich@xxxxxxxxxxxxxx>
Subject: [PATCH] fix use-after-free for task management requests

If a task management request for a command that is already processed
is received, the tm req will wait for the command to finish. If
meanwhile the connection is closed (as a means of error recovery), the
tm req might be freed prematurely, which will lead to a use-after-free
upon completion of th\ e task.

Signed-off-by: Arne Redlich <arne.redlich@xxxxxxxxxxxxxx>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
---
 usr/iscsi/iscsid.c |   20 +++++++++++++++++---
 usr/target.c       |   22 +++++++++++++++++-----
 usr/tgtd.h         |   14 +++++++++++---
 3 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index b952c08..206a67d 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -1332,9 +1332,23 @@ static int iscsi_tm_execute(struct iscsi_task *task)
 
 	if (err)
 		task->result = err;
-	else
-		target_mgmt_request(conn->session->target->tid, conn->session->tsih,
-				    (unsigned long) task, fn, req->lun, req->itt, 0);
+	else {
+		int ret;
+		ret = target_mgmt_request(conn->session->target->tid,
+					  conn->session->tsih,
+					  (unsigned long)task, fn, req->lun,
+					  req->itt, 0);
+		set_task_in_scsi(task);
+		switch (ret) {
+		case MGMT_REQ_QUEUED:
+			break;
+		case MGMT_REQ_FAILED:
+		case MGMT_REQ_DONE:
+			clear_task_in_scsi(task);
+			break;
+		}
+	}
+
 	return err;
 }
 
diff --git a/usr/target.c b/usr/target.c
index 08c0dca..9d979bf 100644
--- a/usr/target.c
+++ b/usr/target.c
@@ -1005,8 +1005,10 @@ static int abort_task_set(struct mgmt_req *mreq, struct target* target,
 	return count;
 }
 
-void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
-			 int function, uint8_t *lun_buf, uint64_t tag, int host_no)
+enum mgmt_req_result target_mgmt_request(int tid, uint64_t itn_id,
+					 uint64_t req_id, int function,
+					 uint8_t *lun_buf, uint64_t tag,
+					 int host_no)
 {
 	struct target *target;
 	struct mgmt_req *mreq;
@@ -1019,12 +1021,15 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 	target = target_lookup(tid);
 	if (!target) {
 		eprintf("invalid tid %d\n", tid);
-		return;
+		return MGMT_REQ_FAILED;
 	}
 
 	mreq = zalloc(sizeof(*mreq));
-	if (!mreq)
-		return;
+	if (!mreq) {
+		eprintf("failed to allocate mgmt_req\n");
+		return MGMT_REQ_FAILED;
+	}
+
 	mreq->mid = req_id;
 	mreq->itn_id = itn_id;
 	mreq->function = function;
@@ -1096,6 +1101,13 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 		tgt_drivers[target->lid]->mgmt_end_notify(mreq);
 		free(mreq);
 	}
+
+	if (err)
+		return err;
+	else if (send)
+		return MGMT_REQ_DONE;
+
+	return MGMT_REQ_QUEUED;
 }
 
 struct account_entry {
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 12a20dc..303627e 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -169,6 +169,12 @@ struct mgmt_req {
 	uint64_t itn_id;
 };
 
+enum mgmt_req_result {
+	MGMT_REQ_FAILED = -1,
+	MGMT_REQ_DONE,
+	MGMT_REQ_QUEUED,
+};
+
 #ifdef USE_KERNEL
 extern int kreq_init(void);
 #else
@@ -224,9 +230,11 @@ extern int tgt_event_modify(int fd, int events);
 extern int target_cmd_queue(int tid, struct scsi_cmd *cmd);
 extern void target_cmd_done(struct scsi_cmd *cmd);
 struct scsi_cmd *target_cmd_lookup(int tid, uint64_t itn_id, uint64_t tag);
-extern void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
-				int function, uint8_t *lun, uint64_t tag,
-				int host_no);
+
+extern enum mgmt_req_result target_mgmt_request(int tid, uint64_t itn_id,
+						uint64_t req_id, int function,
+						uint8_t *lun, uint64_t tag,
+						int host_no);
 
 extern void target_cmd_io_done(struct scsi_cmd *cmd, int result);
 extern int ua_sense_del(struct scsi_cmd *cmd, int del);
-- 
1.6.0.6


--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux