]>
Commit | Line | Data |
---|---|---|
9889d8f6 GKH |
1 | From d4a2618fa77b5e58ec15342972bd3505a1c3f551 Mon Sep 17 00:00:00 2001 |
2 | From: Lukasz Dorau <lukasz.dorau@intel.com> | |
3 | Date: Wed, 3 Apr 2013 10:27:17 +0200 | |
4 | Subject: SCSI: libsas: fix handling vacant phy in sas_set_ex_phy() | |
5 | ||
6 | From: Lukasz Dorau <lukasz.dorau@intel.com> | |
7 | ||
8 | commit d4a2618fa77b5e58ec15342972bd3505a1c3f551 upstream. | |
9 | ||
10 | If a result of the SMP discover function is PHY VACANT, | |
11 | the content of discover response structure (dr) is not valid. | |
12 | It sometimes happens that dr->attached_sas_addr can contain | |
13 | even SAS address of other phy. In such case an invalid phy | |
14 | is created, what causes NULL pointer dereference during | |
15 | destruction of expander's phys. | |
16 | ||
17 | So if a result of SMP function is PHY VACANT, the content of discover | |
18 | response structure (dr) must not be copied to phy structure. | |
19 | ||
20 | This patch fixes the following bug: | |
21 | ||
22 | BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 | |
23 | IP: [<ffffffff811c9002>] sysfs_find_dirent+0x12/0x90 | |
24 | Call Trace: | |
25 | [<ffffffff811c95f5>] sysfs_get_dirent+0x35/0x80 | |
26 | [<ffffffff811cb55e>] sysfs_unmerge_group+0x1e/0xb0 | |
27 | [<ffffffff813329f4>] dpm_sysfs_remove+0x24/0x90 | |
28 | [<ffffffff8132b0f4>] device_del+0x44/0x1d0 | |
29 | [<ffffffffa016fc59>] sas_rphy_delete+0x9/0x20 [scsi_transport_sas] | |
30 | [<ffffffffa01a16f6>] sas_destruct_devices+0xe6/0x110 [libsas] | |
31 | [<ffffffff8107ac7c>] process_one_work+0x16c/0x350 | |
32 | [<ffffffff8107d84a>] worker_thread+0x17a/0x410 | |
33 | [<ffffffff81081b76>] kthread+0x96/0xa0 | |
34 | [<ffffffff81464944>] kernel_thread_helper+0x4/0x10 | |
35 | ||
36 | Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com> | |
37 | Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com> | |
38 | Reviewed-by: Maciej Patelczyk <maciej.patelczyk@intel.com> | |
39 | Signed-off-by: James Bottomley <JBottomley@Parallels.com> | |
40 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
41 | ||
42 | --- | |
43 | drivers/scsi/libsas/sas_expander.c | 12 ++++++++++++ | |
44 | 1 file changed, 12 insertions(+) | |
45 | ||
46 | --- a/drivers/scsi/libsas/sas_expander.c | |
47 | +++ b/drivers/scsi/libsas/sas_expander.c | |
48 | @@ -235,6 +235,17 @@ static void sas_set_ex_phy(struct domain | |
49 | linkrate = phy->linkrate; | |
50 | memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); | |
51 | ||
52 | + /* Handle vacant phy - rest of dr data is not valid so skip it */ | |
53 | + if (phy->phy_state == PHY_VACANT) { | |
54 | + memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | |
55 | + phy->attached_dev_type = NO_DEVICE; | |
56 | + if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { | |
57 | + phy->phy_id = phy_id; | |
58 | + goto skip; | |
59 | + } else | |
60 | + goto out; | |
61 | + } | |
62 | + | |
63 | phy->attached_dev_type = to_dev_type(dr); | |
64 | if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) | |
65 | goto out; | |
66 | @@ -272,6 +283,7 @@ static void sas_set_ex_phy(struct domain | |
67 | phy->phy->maximum_linkrate = dr->pmax_linkrate; | |
68 | phy->phy->negotiated_linkrate = phy->linkrate; | |
69 | ||
70 | + skip: | |
71 | if (new_phy) | |
72 | if (sas_phy_add(phy->phy)) { | |
73 | sas_phy_free(phy->phy); |