[PATCH 07/21] target: Fix a use-after-free in core_tpg_del_initiator_node_acl()

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

 



Target drivers like ib_srpt can call transport_deregister_session()
while core_tpg_del_initiator_node_acl() is processing sess_acl_list.
Avoid that this scenario triggers a use-after-free by postponing
freeing a session object until core_tpg_del_initiator_node_acl() has
finished accessing that session object. Keep the se_tpg and
fabric_sess_ptr member variables as long as the session object
exists.

This patch fixes the following crash:

general protection fault: 0000 [#1] SMP
CPU: 5 PID: 15050 Comm: rmdir Tainted: G            E   4.4.0-rc7+ #1
Hardware name: Dell Inc. PowerEdge R430/03XKDV, BIOS 1.0.2 11/17/2014
task: ffff880428349f40 ti: ffff880426584000 task.ti: ffff880426584000
RIP: 0010:[<ffffffff8126ef7d>]  [<ffffffff8126ef7d>] __list_del_entry+0x2d/0xd0
RSP: 0018:ffff880426587cd8  EFLAGS: 00010a83
RAX: 6b6b6b6b6b6b6b6b RBX: ffff8804273687c0 RCX: dead000000000200
RDX: 6b6b6b6b6b6b6b6b RSI: ffff88042834ab20 RDI: ffff8804273687c0
RBP: ffff880426587ce8 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000000 R12: ffff880426587d48
R13: ffff88041fc66a30 R14: 6b6b6b6b6b6b6b2b R15: ffff880427368780
FS:  00007f8b4ad54700(0000) GS:ffff88046e4a0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fec7ed44000 CR3: 0000000075a30000 CR4: 00000000001406e0
Stack:
 ffff88041fc66a30 ffff880427368780 ffff880426587d08 ffffffff8126f031
 ffff880426587d08 ffff880422106618 ffff880426587d98 ffffffffa04f8390
 ffff88045e5271b8 0000000000000000 ffff880426587d48 ffff880400000001
Call Trace:
 [<ffffffff8126f031>] list_del+0x11/0x40
 [<ffffffffa04f8390>] core_tpg_del_initiator_node_acl+0x110/0x200 [target_core_mod]
 [<ffffffffa04ebcaf>] target_fabric_nacl_base_release+0x4f/0x60 [target_core_mod]
 [<ffffffffa0482bef>] config_item_release+0x6f/0xc0 [configfs]
 [<ffffffffa0482c5b>] config_item_put+0x1b/0x20 [configfs]
 [<ffffffffa0481f88>] configfs_rmdir+0x1e8/0x2e0 [configfs]
 [<ffffffff81183461>] vfs_rmdir+0x81/0x120
 [<ffffffff81187246>] do_rmdir+0x146/0x190
 [<ffffffff811872d1>] SyS_rmdir+0x11/0x20
 [<ffffffff8151c857>] entry_SYSCALL_64_fastpath+0x12/0x6f

Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Andy Grover <agrover@xxxxxxxxxx>
Cc: Sagi Grimberg <sagig@xxxxxxxxxxxx>
---
 drivers/target/target_core_transport.c | 27 ++++++++++++++++++++-------
 include/target/target_core_base.h      |  1 +
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 6bb712f..e41dba5 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -240,6 +240,8 @@ struct se_session *transport_init_session(enum target_prot_op sup_prot_ops)
 	INIT_LIST_HEAD(&se_sess->sess_wait_list);
 	spin_lock_init(&se_sess->sess_cmd_lock);
 	kref_init(&se_sess->sess_kref);
+	kref_init(&se_sess->kref2);
+	kref_get(&se_sess->kref2);
 	se_sess->sup_prot_ops = sup_prot_ops;
 
 	return se_sess;
@@ -375,6 +377,18 @@ void transport_register_session(
 }
 EXPORT_SYMBOL(transport_register_session);
 
+static void target_release_session2(struct kref *kref)
+{
+	struct se_session *sess = container_of(kref, typeof(*sess), kref2);
+
+	transport_free_session(sess);
+}
+
+static void target_put_session2(struct se_session *sess)
+{
+	kref_put(&sess->kref2, target_release_session2);
+}
+
 static void target_release_session(struct kref *kref)
 {
 	struct se_session *se_sess = container_of(kref,
@@ -382,6 +396,7 @@ static void target_release_session(struct kref *kref)
 	struct se_portal_group *se_tpg = se_sess->se_tpg;
 
 	se_tpg->se_tpg_tfo->close_session(se_sess);
+	target_put_session2(se_sess);
 }
 
 void target_get_session(struct se_session *se_sess)
@@ -480,16 +495,13 @@ void transport_deregister_session(struct se_session *se_sess)
 	unsigned long flags;
 	bool comp_nacl = true, drop_nacl = false;
 
-	if (!se_tpg) {
-		transport_free_session(se_sess);
-		return;
-	}
+	if (!se_tpg)
+		goto put;
+
 	se_tfo = se_tpg->se_tpg_tfo;
 
 	spin_lock_irqsave(&se_tpg->session_lock, flags);
 	list_del(&se_sess->sess_list);
-	se_sess->se_tpg = NULL;
-	se_sess->fabric_sess_ptr = NULL;
 	spin_unlock_irqrestore(&se_tpg->session_lock, flags);
 
 	/*
@@ -523,7 +535,8 @@ void transport_deregister_session(struct se_session *se_sess)
 	if (se_nacl && comp_nacl)
 		target_put_nacl(se_nacl);
 
-	transport_free_session(se_sess);
+put:
+	target_put_session2(se_sess);
 }
 EXPORT_SYMBOL(transport_deregister_session);
 
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index ec368e9..ba203c2 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -611,6 +611,7 @@ struct se_session {
 	struct list_head	sess_wait_list;
 	spinlock_t		sess_cmd_lock;
 	struct kref		sess_kref;
+	struct kref		kref2;
 	void			*sess_cmd_map;
 	struct percpu_ida	sess_tag_pool;
 };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe target-devel" 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]     [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