From 35afa65642a9a88c81913377b93a3a66220f8b9d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 23 Sep 2015 07:49:26 +0000 Subject: [PATCH] target: Fix v4.1 UNIT_ATTENTION se_node_acl->device_list[] NULL pointer This patch fixes a v4.1 only regression bug as reported by Martin where UNIT_ATTENTION checking for pre v4.2-rc1 RCU conversion code legacy se_node_acl->device_list[] was hitting a NULL pointer dereference in: [ 1858.639654] CPU: 2 PID: 1293 Comm: kworker/2:1 Tainted: G I 4.1.6-fixxcopy+ #1 [ 1858.639699] Hardware name: Dell Inc. PowerEdge R410/0N83VF, BIOS 1.11.0 07/20/2012 [ 1858.639747] Workqueue: xcopy_wq target_xcopy_do_work [target_core_mod] [ 1858.639782] task: ffff880036f0cbe0 ti: ffff880317940000 task.ti: ffff880317940000 [ 1858.639822] RIP: 0010:[] [] target_scsi3_ua_check+0x24/0x60 [target_core_mod] [ 1858.639884] RSP: 0018:ffff880317943ce0 EFLAGS: 00010282 [ 1858.639913] RAX: 0000000000000000 RBX: ffff880317943dc0 RCX: 0000000000000000 [ 1858.639950] RDX: 0000000000000000 RSI: ffff880317943dd0 RDI: ffff88030eaee408 [ 1858.639987] RBP: ffff88030eaee408 R08: 0000000000000001 R09: 0000000000000001 [ 1858.640025] R10: 0000000000000000 R11: 00000000000706e0 R12: ffff880315e0a000 [ 1858.640062] R13: ffff88030eaee408 R14: 0000000000000001 R15: ffff88030eaee408 [ 1858.640100] FS: 0000000000000000(0000) GS:ffff880322e80000(0000) knlGS:0000000000000000 [ 1858.640143] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 1858.640173] CR2: 0000000000000000 CR3: 000000000180d000 CR4: 00000000000006e0 [ 1858.640210] Stack: [ 1858.640223] ffffffffa01cadfa ffff88030eaee400 ffff880318e7c340 ffff880315e0a000 [ 1858.640267] ffffffffa01d8c25 ffff8800cae809e0 0000000000000400 0000000000000400 [ 1858.640310] ffff880318e7c3d0 0000000006b75800 0000000000080000 ffff88030eaee400 [ 1858.640354] Call Trace: [ 1858.640379] [] ? target_setup_cmd_from_cdb+0x13a/0x2c0 [target_core_mod] [ 1858.640429] [] ? target_xcopy_setup_pt_cmd+0x85/0x320 [target_core_mod] [ 1858.640479] [] ? target_xcopy_do_work+0x264/0x700 [target_core_mod] [ 1858.640526] [] ? pick_next_task_fair+0x720/0x8f0 [ 1858.640562] [] ? process_one_work+0x14b/0x430 [ 1858.640595] [] ? worker_thread+0x6b/0x560 [ 1858.640627] [] ? rescuer_thread+0x390/0x390 [ 1858.640661] [] ? kthread+0xd3/0xf0 [ 1858.640689] [] ? kthread_create_on_node+0x180/0x180 Also, check for the same se_node_acl->device_list[] during EXTENDED_COPY operation as a non-holding persistent reservation port. Reported-by: Martin Svec Tested-by: Martin Svec Cc: Martin Svec Cc: Alex Gorbachev Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_pr.c | 3 +++ drivers/target/target_core_ua.c | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index a15411c..08aa7cc 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -328,6 +328,9 @@ static int core_scsi3_pr_seq_non_holder( int legacy = 0; /* Act like a legacy device and return * RESERVATION CONFLICT on some CDBs */ + if (!se_sess->se_node_acl->device_list) + return; + se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; /* * Determine if the registration should be ignored due to diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 1738b16..9fc33e8 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -48,7 +48,7 @@ target_scsi3_ua_check(struct se_cmd *cmd) return 0; nacl = sess->se_node_acl; - if (!nacl) + if (!nacl || !nacl->device_list) return 0; deve = nacl->device_list[cmd->orig_fe_lun]; @@ -90,7 +90,7 @@ int core_scsi3_ua_allocate( /* * PASSTHROUGH OPS */ - if (!nacl) + if (!nacl || !nacl->device_list) return -EINVAL; ua = kmem_cache_zalloc(se_ua_cache, GFP_ATOMIC); @@ -208,7 +208,7 @@ void core_scsi3_ua_for_check_condition( return; nacl = sess->se_node_acl; - if (!nacl) + if (!nacl || !nacl->device_list) return; spin_lock_irq(&nacl->device_list_lock); @@ -276,7 +276,7 @@ int core_scsi3_ua_clear_for_request_sense( return -EINVAL; nacl = sess->se_node_acl; - if (!nacl) + if (!nacl || !nacl->device_list) return -EINVAL; spin_lock_irq(&nacl->device_list_lock); -- 2.7.4