aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rdma/hfi1/init.c
diff options
context:
space:
mode:
authorDennis Dalessandro <dennis.dalessandro@intel.com>2016-05-19 05:26:44 -0700
committerDoug Ledford <dledford@redhat.com>2016-05-26 11:35:13 -0400
commite11ffbd57520c3832e05f2f5f19e9ff6adbb7cdc (patch)
tree6926bb60c32447ffc09e68e909492d85c0044c38 /drivers/staging/rdma/hfi1/init.c
parentIB/hfi1: Add trace message in user IOCTL handling (diff)
downloadlinux-dev-e11ffbd57520c3832e05f2f5f19e9ff6adbb7cdc.tar.xz
linux-dev-e11ffbd57520c3832e05f2f5f19e9ff6adbb7cdc.zip
IB/hfi1: Do not free hfi1 cdev parent structure early
The deletion of a cdev is not a fence for holding off references to the structure. The driver attempts to delete the cdev and then proceeds to free the parent structure, the hfi1_devdata, or dd. This can potentially lead to a kernel panic in situations where a user has an FD for the cdev open, and the pci device gets removed. If the user then closes the FD there will be a NULL dereference when trying to do put on the cdev's kobject. Fix this by pointing the cdev's kobject.parent at a new kobject embedded in its parent structure. Also take a reference when the device is opened and put it back when it is closed. Reviewed-by: Mitko Haralanov <mitko.haralanov@intel.com> Signed-off-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/staging/rdma/hfi1/init.c')
-rw-r--r--drivers/staging/rdma/hfi1/init.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/staging/rdma/hfi1/init.c b/drivers/staging/rdma/hfi1/init.c
index b9beaae5953d..5cc492e5776d 100644
--- a/drivers/staging/rdma/hfi1/init.c
+++ b/drivers/staging/rdma/hfi1/init.c
@@ -989,8 +989,10 @@ static void release_asic_data(struct hfi1_devdata *dd)
dd->asic_data = NULL;
}
-void hfi1_free_devdata(struct hfi1_devdata *dd)
+static void __hfi1_free_devdata(struct kobject *kobj)
{
+ struct hfi1_devdata *dd =
+ container_of(kobj, struct hfi1_devdata, kobj);
unsigned long flags;
spin_lock_irqsave(&hfi1_devs_lock, flags);
@@ -1007,6 +1009,15 @@ void hfi1_free_devdata(struct hfi1_devdata *dd)
rvt_dealloc_device(&dd->verbs_dev.rdi);
}
+static struct kobj_type hfi1_devdata_type = {
+ .release = __hfi1_free_devdata,
+};
+
+void hfi1_free_devdata(struct hfi1_devdata *dd)
+{
+ kobject_put(&dd->kobj);
+}
+
/*
* Allocate our primary per-unit data structure. Must be done via verbs
* allocator, because the verbs cleanup process both does cleanup and
@@ -1102,6 +1113,7 @@ struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, size_t extra)
&pdev->dev,
"Could not alloc cpulist info, cpu affinity might be wrong\n");
}
+ kobject_init(&dd->kobj, &hfi1_devdata_type);
return dd;
bail: