linux/drivers/target
Nicholas Bellinger bd4e2d2907 target: Fix NULL dereference during LUN lookup + active I/O shutdown
When transport_clear_lun_ref() is shutting down a se_lun via
configfs with new I/O in-flight, it's possible to trigger a
NULL pointer dereference in transport_lookup_cmd_lun() due
to the fact percpu_ref_get() doesn't do any __PERCPU_REF_DEAD
checking before incrementing lun->lun_ref.count after
lun->lun_ref has switched to atomic_t mode.

This results in a NULL pointer dereference as LUN shutdown
code in core_tpg_remove_lun() continues running after the
existing ->release() -> core_tpg_lun_ref_release() callback
completes, and clears the RCU protected se_lun->lun_se_dev
pointer.

During the OOPs, the state of lun->lun_ref in the process
which triggered the NULL pointer dereference looks like
the following on v4.1.y stable code:

struct se_lun {
  lun_link_magic = 4294932337,
  lun_status = TRANSPORT_LUN_STATUS_FREE,

  .....

  lun_se_dev = 0x0,
  lun_sep = 0x0,

  .....

  lun_ref = {
    count = {
      counter = 1
    },
    percpu_count_ptr = 3,
    release = 0xffffffffa02fa1e0 <core_tpg_lun_ref_release>,
    confirm_switch = 0x0,
    force_atomic = false,
    rcu = {
      next = 0xffff88154fa1a5d0,
      func = 0xffffffff8137c4c0 <percpu_ref_switch_to_atomic_rcu>
    }
  }
}

To address this bug, use percpu_ref_tryget_live() to ensure
once __PERCPU_REF_DEAD is visable on all CPUs and ->lun_ref
has switched to atomic_t, all new I/Os will fail to obtain
a new lun->lun_ref reference.

Also use an explicit percpu_ref_kill_and_confirm() callback
to block on ->lun_ref_comp to allow the first stage and
associated RCU grace period to complete, and then block on
->lun_ref_shutdown waiting for the final percpu_ref_put()
to drop the last reference via transport_lun_remove_cmd()
before continuing with core_tpg_remove_lun() shutdown.

Reported-by: Rob Millner <rlm@daterainc.com>
Tested-by: Rob Millner <rlm@daterainc.com>
Cc: Rob Millner <rlm@daterainc.com>
Tested-by: Vaibhav Tandon <vst@datera.io>
Cc: Vaibhav Tandon <vst@datera.io>
Tested-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Cc: <stable@vger.kernel.org> # v3.14+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
2017-02-26 16:08:44 -08:00
..
iscsi target/iscsi: Fix unsolicited data seq_end_offset calculation 2017-02-18 21:24:21 -08:00
loopback target: Minimize #include directives 2016-12-09 10:22:28 -08:00
sbp sbp-target: Add an #include directive 2016-12-09 10:20:10 -08:00
tcm_fc target/tcm_fc: Remove a set-but-not-used variable 2017-02-09 00:39:06 -08:00
Kconfig
Makefile
target_core_alua.c target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_alua.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_configfs.c Merge branch 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux 2016-12-21 10:16:05 -08:00
target_core_device.c target: Fix NULL dereference during LUN lookup + active I/O shutdown 2017-02-26 16:08:44 -08:00
target_core_fabric_configfs.c fs: configfs: don't return anything from drop_link 2016-12-01 10:50:49 +01:00
target_core_fabric_lib.c
target_core_file.c target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_file.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_hba.c target: Fix target_sense_desc_format NULL pointer dereference 2015-09-24 23:17:23 -07:00
target_core_iblock.c block,fs: use REQ_* flags directly 2016-11-01 09:43:26 -06:00
target_core_iblock.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_internal.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_pr.c target: Fix spelling mistake and unwrap multi-line text 2016-12-16 11:16:08 +01:00
target_core_pr.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_pscsi.c target: avoid accessing .bi_vcnt directly 2016-11-22 08:57:55 -07:00
target_core_pscsi.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_rd.c target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_rd.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_sbc.c target: Remove command flag CMD_T_BUSY 2017-02-09 00:39:15 -08:00
target_core_spc.c target: Remove enum transport_lunflags_table 2016-03-10 21:48:55 -08:00
target_core_stat.c target: export protocol identifier 2017-02-18 21:36:50 -08:00
target_core_tmr.c target: Delete tmr from list before processing 2017-02-20 14:37:19 -08:00
target_core_tpg.c target: Fix NULL dereference during LUN lookup + active I/O shutdown 2017-02-26 16:08:44 -08:00
target_core_transport.c target: Fix NULL dereference during LUN lookup + active I/O shutdown 2017-02-26 16:08:44 -08:00
target_core_ua.c
target_core_ua.h target: Minimize #include directives 2016-12-09 10:22:28 -08:00
target_core_user.c Merge branch 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux 2016-12-21 10:16:05 -08:00
target_core_xcopy.c target: Use correct SCSI status during EXTENDED_COPY exception 2017-02-08 07:46:54 -08:00
target_core_xcopy.h target: check for XCOPY parameter truncation 2017-01-10 08:41:27 -08:00