Commit d4a2618fa77b5e58ec15342972bd3505a1c3f551
Committed by
James Bottomley
1 parent
9d85b59005
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
[SCSI] libsas: fix handling vacant phy in sas_set_ex_phy()
If a result of the SMP discover function is PHY VACANT, the content of discover response structure (dr) is not valid. It sometimes happens that dr->attached_sas_addr can contain even SAS address of other phy. In such case an invalid phy is created, what causes NULL pointer dereference during destruction of expander's phys. So if a result of SMP function is PHY VACANT, the content of discover response structure (dr) must not be copied to phy structure. This patch fixes the following bug: BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 IP: [<ffffffff811c9002>] sysfs_find_dirent+0x12/0x90 Call Trace: [<ffffffff811c95f5>] sysfs_get_dirent+0x35/0x80 [<ffffffff811cb55e>] sysfs_unmerge_group+0x1e/0xb0 [<ffffffff813329f4>] dpm_sysfs_remove+0x24/0x90 [<ffffffff8132b0f4>] device_del+0x44/0x1d0 [<ffffffffa016fc59>] sas_rphy_delete+0x9/0x20 [scsi_transport_sas] [<ffffffffa01a16f6>] sas_destruct_devices+0xe6/0x110 [libsas] [<ffffffff8107ac7c>] process_one_work+0x16c/0x350 [<ffffffff8107d84a>] worker_thread+0x17a/0x410 [<ffffffff81081b76>] kthread+0x96/0xa0 [<ffffffff81464944>] kernel_thread_helper+0x4/0x10 Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com> Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com> Reviewed-by: Maciej Patelczyk <maciej.patelczyk@intel.com> Cc: <stable@vger.kernel.org> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Showing 1 changed file with 12 additions and 0 deletions Side-by-side Diff
drivers/scsi/libsas/sas_expander.c
... | ... | @@ -235,6 +235,17 @@ |
235 | 235 | linkrate = phy->linkrate; |
236 | 236 | memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); |
237 | 237 | |
238 | + /* Handle vacant phy - rest of dr data is not valid so skip it */ | |
239 | + if (phy->phy_state == PHY_VACANT) { | |
240 | + memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | |
241 | + phy->attached_dev_type = NO_DEVICE; | |
242 | + if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { | |
243 | + phy->phy_id = phy_id; | |
244 | + goto skip; | |
245 | + } else | |
246 | + goto out; | |
247 | + } | |
248 | + | |
238 | 249 | phy->attached_dev_type = to_dev_type(dr); |
239 | 250 | if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) |
240 | 251 | goto out; |
... | ... | @@ -272,6 +283,7 @@ |
272 | 283 | phy->phy->maximum_linkrate = dr->pmax_linkrate; |
273 | 284 | phy->phy->negotiated_linkrate = phy->linkrate; |
274 | 285 | |
286 | + skip: | |
275 | 287 | if (new_phy) |
276 | 288 | if (sas_phy_add(phy->phy)) { |
277 | 289 | sas_phy_free(phy->phy); |