diff options
author | Bart Van Assche <bvanassche@acm.org> | 2018-11-27 15:51:58 -0800 |
---|---|---|
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) | |
download | lwn-ad669505c4e9db9af9faeb5c51aa399326a80d91.tar.gz lwn-ad669505c4e9db9af9faeb5c51aa399326a80d91.zip |
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 { struct se_node_acl *se_node_acl; struct se_portal_group *se_tpg; void *fabric_sess_ptr; + struct percpu_ref cmd_count; struct list_head sess_list; struct list_head sess_acl_list; 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 *, struct se_session *, void *)); void target_remove_session(struct se_session *); -void transport_init_session(struct se_session *); +int transport_init_session(struct se_session *se_sess); struct se_session *transport_alloc_session(enum target_prot_op); int transport_alloc_session_tags(struct se_session *, unsigned int, unsigned int); |