diff options
author | Bart Van Assche <bvanassche@acm.org> | 2018-11-27 18:51:58 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-12-07 21:20:07 -0500 |
commit | ad669505c4e9db9af9faeb5c51aa399326a80d91 (patch) | |
tree | dafa06323672f2c181781a0a59e40e43e71dfa4b /include/target | |
parent | a95be3842c51c9ac32fe17faedf2c156ccf81bd7 (diff) |
scsi: target/core: Make sure that target_wait_for_sess_cmds() waits long enough
A session must only be released after all code that accesses the session
structure has finished. Make sure that this is the case by introducing a
new command counter per session that is only decremented after the
.release_cmd() callback has finished. This patch fixes the following crash:
BUG: KASAN: use-after-free in do_raw_spin_lock+0x1c/0x130
Read of size 4 at addr ffff8801534b16e4 by task rmdir/14805
CPU: 16 PID: 14805 Comm: rmdir Not tainted 4.18.0-rc2-dbg+ #5
Call Trace:
dump_stack+0xa4/0xf5
print_address_description+0x6f/0x270
kasan_report+0x241/0x360
__asan_load4+0x78/0x80
do_raw_spin_lock+0x1c/0x130
_raw_spin_lock_irqsave+0x52/0x60
srpt_set_ch_state+0x27/0x70 [ib_srpt]
srpt_disconnect_ch+0x1b/0xc0 [ib_srpt]
srpt_close_session+0xa8/0x260 [ib_srpt]
target_shutdown_sessions+0x170/0x180 [target_core_mod]
core_tpg_del_initiator_node_acl+0xf3/0x200 [target_core_mod]
target_fabric_nacl_base_release+0x25/0x30 [target_core_mod]
config_item_release+0x9c/0x110 [configfs]
config_item_put+0x26/0x30 [configfs]
configfs_rmdir+0x3b8/0x510 [configfs]
vfs_rmdir+0xb3/0x1e0
do_rmdir+0x262/0x2c0
do_syscall_64+0x77/0x230
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Cc: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: Mike Christie <mchristi@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: David Disseldorp <ddiss@suse.de>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'include/target')
-rw-r--r-- | include/target/target_core_base.h | 1 | ||||
-rw-r--r-- | include/target/target_core_fabric.h | 2 |
2 files changed, 2 insertions, 1 deletions
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index bb965a355187..6e34ec4df6b7 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -603,6 +603,7 @@ struct se_session { | |||
603 | struct se_node_acl *se_node_acl; | 603 | struct se_node_acl *se_node_acl; |
604 | struct se_portal_group *se_tpg; | 604 | struct se_portal_group *se_tpg; |
605 | void *fabric_sess_ptr; | 605 | void *fabric_sess_ptr; |
606 | struct percpu_ref cmd_count; | ||
606 | struct list_head sess_list; | 607 | struct list_head sess_list; |
607 | struct list_head sess_acl_list; | 608 | struct list_head sess_acl_list; |
608 | struct list_head sess_cmd_list; | 609 | struct list_head sess_cmd_list; |
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 0a1595f3c5a1..3b81a5b01497 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h | |||
@@ -126,7 +126,7 @@ struct se_session *target_setup_session(struct se_portal_group *, | |||
126 | struct se_session *, void *)); | 126 | struct se_session *, void *)); |
127 | void target_remove_session(struct se_session *); | 127 | void target_remove_session(struct se_session *); |
128 | 128 | ||
129 | void transport_init_session(struct se_session *); | 129 | int transport_init_session(struct se_session *se_sess); |
130 | struct se_session *transport_alloc_session(enum target_prot_op); | 130 | struct se_session *transport_alloc_session(enum target_prot_op); |
131 | int transport_alloc_session_tags(struct se_session *, unsigned int, | 131 | int transport_alloc_session_tags(struct se_session *, unsigned int, |
132 | unsigned int); | 132 | unsigned int); |