IB/hfi1: Fix NULL pointer dereference when invalid num_vls is used
authorSebastian Sanchez <sebastian.sanchez@intel.com>
Tue, 1 May 2018 12:35:58 +0000 (05:35 -0700)
committerDoug Ledford <dledford@redhat.com>
Thu, 3 May 2018 19:24:47 +0000 (15:24 -0400)
When an invalid num_vls is used as a module parameter, the code
execution follows an exception path where the macro dd_dev_err()
expects dd->pcidev->dev not to be NULL in hfi1_init_dd(). This
causes a NULL pointer dereference.

Fix hfi1_init_dd() by initializing dd->pcidev and dd->pcidev->dev
earlier in the code. If a dd exists, then dd->pcidev and
dd->pcidev->dev always exists.

BUG: unable to handle kernel NULL pointer dereference
at 00000000000000f0
IP: __dev_printk+0x15/0x90
Workqueue: events work_for_cpu_fn
RIP: 0010:__dev_printk+0x15/0x90
Call Trace:
 dev_err+0x6c/0x90
 ? hfi1_init_pportdata+0x38d/0x3f0 [hfi1]
 hfi1_init_dd+0xdd/0x2530 [hfi1]
 ? pci_conf1_read+0xb2/0xf0
 ? pci_read_config_word.part.9+0x64/0x80
 ? pci_conf1_write+0xb0/0xf0
 ? pcie_capability_clear_and_set_word+0x57/0x80
 init_one+0x141/0x490 [hfi1]
 local_pci_probe+0x3f/0xa0
 work_for_cpu_fn+0x10/0x20
 process_one_work+0x152/0x350
 worker_thread+0x1cf/0x3e0
 kthread+0xf5/0x130
 ? max_active_store+0x80/0x80
 ? kthread_bind+0x10/0x10
 ? do_syscall_64+0x6e/0x1a0
 ? SyS_exit_group+0x10/0x10
 ret_from_fork+0x35/0x40

Cc: <stable@vger.kernel.org> # 4.9.x
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: Sebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/pcie.c

index c45cca556942e5988a50849aac6334af0176201c..b417e3b40e4a84cdcf71afeb41c0e5713ebd63d7 100644 (file)
@@ -1265,6 +1265,8 @@ struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, size_t extra)
                return ERR_PTR(-ENOMEM);
        dd->num_pports = nports;
        dd->pport = (struct hfi1_pportdata *)(dd + 1);
+       dd->pcidev = pdev;
+       pci_set_drvdata(pdev, dd);
 
        INIT_LIST_HEAD(&dd->list);
        idr_preload(GFP_KERNEL);
index 83d66e862207c6f7a31ab5e7eac48a441b82e115..c1c982908b4bb2ad000fc1aa507be0036f78789d 100644 (file)
@@ -163,9 +163,6 @@ int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev)
        resource_size_t addr;
        int ret = 0;
 
-       dd->pcidev = pdev;
-       pci_set_drvdata(pdev, dd);
-
        addr = pci_resource_start(pdev, 0);
        len = pci_resource_len(pdev, 0);