Skip to content

Commit 5a52a7a

Browse files
ssanchez11dledford
authored andcommitted
IB/hfi1: NULL pointer dereference when freeing rhashtable
A NULL pointer dereference occurs when the driver is unloaded, and the SDMA rhashtable is freed if the rhashtable_init() function has not been called. Prevent this by changing sdma_rht to be a pointer to a dynamically allocated hash table. The NULL-ness of the pointer serves as an indication that the hash table was initialized and that it needs to be destroyed. Fixes: 0cb2aa6 ("IB/hfi1: Add sysfs interface for affinity setup") Reviewed-by: Mike Marciniszyn <mike.marciniszyn@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>
1 parent 8688426 commit 5a52a7a

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

drivers/infiniband/hw/hfi1/hfi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,7 @@ struct hfi1_devdata {
11671167
bool eprom_available; /* true if EPROM is available for this device */
11681168
bool aspm_supported; /* Does HW support ASPM */
11691169
bool aspm_enabled; /* ASPM state: enabled/disabled */
1170-
struct rhashtable sdma_rht;
1170+
struct rhashtable *sdma_rht;
11711171

11721172
struct kobject kobj;
11731173
};

drivers/infiniband/hw/hfi1/sdma.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd,
868868

869869
cpu_id = smp_processor_id();
870870
rcu_read_lock();
871-
rht_node = rhashtable_lookup_fast(&dd->sdma_rht, &cpu_id,
871+
rht_node = rhashtable_lookup_fast(dd->sdma_rht, &cpu_id,
872872
sdma_rht_params);
873873

874874
if (rht_node && rht_node->map[vl]) {
@@ -962,7 +962,7 @@ ssize_t sdma_set_cpu_to_sde_map(struct sdma_engine *sde, const char *buf,
962962
continue;
963963
}
964964

965-
rht_node = rhashtable_lookup_fast(&dd->sdma_rht, &cpu,
965+
rht_node = rhashtable_lookup_fast(dd->sdma_rht, &cpu,
966966
sdma_rht_params);
967967
if (!rht_node) {
968968
rht_node = kzalloc(sizeof(*rht_node), GFP_KERNEL);
@@ -982,7 +982,7 @@ ssize_t sdma_set_cpu_to_sde_map(struct sdma_engine *sde, const char *buf,
982982
rht_node->map[vl]->ctr = 1;
983983
rht_node->map[vl]->sde[0] = sde;
984984

985-
ret = rhashtable_insert_fast(&dd->sdma_rht,
985+
ret = rhashtable_insert_fast(dd->sdma_rht,
986986
&rht_node->node,
987987
sdma_rht_params);
988988
if (ret) {
@@ -1025,7 +1025,7 @@ ssize_t sdma_set_cpu_to_sde_map(struct sdma_engine *sde, const char *buf,
10251025
if (cpumask_test_cpu(cpu, mask))
10261026
continue;
10271027

1028-
rht_node = rhashtable_lookup_fast(&dd->sdma_rht, &cpu,
1028+
rht_node = rhashtable_lookup_fast(dd->sdma_rht, &cpu,
10291029
sdma_rht_params);
10301030
if (rht_node) {
10311031
bool empty = true;
@@ -1049,7 +1049,7 @@ ssize_t sdma_set_cpu_to_sde_map(struct sdma_engine *sde, const char *buf,
10491049
}
10501050

10511051
if (empty) {
1052-
ret = rhashtable_remove_fast(&dd->sdma_rht,
1052+
ret = rhashtable_remove_fast(dd->sdma_rht,
10531053
&rht_node->node,
10541054
sdma_rht_params);
10551055
WARN_ON(ret);
@@ -1108,7 +1108,7 @@ void sdma_seqfile_dump_cpu_list(struct seq_file *s,
11081108
struct sdma_rht_node *rht_node;
11091109
int i, j;
11101110

1111-
rht_node = rhashtable_lookup_fast(&dd->sdma_rht, &cpuid,
1111+
rht_node = rhashtable_lookup_fast(dd->sdma_rht, &cpuid,
11121112
sdma_rht_params);
11131113
if (!rht_node)
11141114
return;
@@ -1322,6 +1322,12 @@ static void sdma_clean(struct hfi1_devdata *dd, size_t num_engines)
13221322
synchronize_rcu();
13231323
kfree(dd->per_sdma);
13241324
dd->per_sdma = NULL;
1325+
1326+
if (dd->sdma_rht) {
1327+
rhashtable_free_and_destroy(dd->sdma_rht, sdma_rht_free, NULL);
1328+
kfree(dd->sdma_rht);
1329+
dd->sdma_rht = NULL;
1330+
}
13251331
}
13261332

13271333
/**
@@ -1341,12 +1347,14 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
13411347
{
13421348
unsigned this_idx;
13431349
struct sdma_engine *sde;
1350+
struct rhashtable *tmp_sdma_rht;
13441351
u16 descq_cnt;
13451352
void *curr_head;
13461353
struct hfi1_pportdata *ppd = dd->pport + port;
13471354
u32 per_sdma_credits;
13481355
uint idle_cnt = sdma_idle_cnt;
13491356
size_t num_engines = dd->chip_sdma_engines;
1357+
int ret = -ENOMEM;
13501358

13511359
if (!HFI1_CAP_IS_KSET(SDMA)) {
13521360
HFI1_CAP_CLEAR(SDMA_AHG);
@@ -1378,7 +1386,7 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
13781386
/* alloc memory for array of send engines */
13791387
dd->per_sdma = kcalloc(num_engines, sizeof(*dd->per_sdma), GFP_KERNEL);
13801388
if (!dd->per_sdma)
1381-
return -ENOMEM;
1389+
return ret;
13821390

13831391
idle_cnt = ns_to_cclock(dd, idle_cnt);
13841392
if (!sdma_desct_intr)
@@ -1507,18 +1515,27 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
15071515
dd->flags |= HFI1_HAS_SEND_DMA;
15081516
dd->flags |= idle_cnt ? HFI1_HAS_SDMA_TIMEOUT : 0;
15091517
dd->num_sdma = num_engines;
1510-
if (sdma_map_init(dd, port, ppd->vls_operational, NULL))
1518+
ret = sdma_map_init(dd, port, ppd->vls_operational, NULL);
1519+
if (ret < 0)
1520+
goto bail;
1521+
1522+
tmp_sdma_rht = kzalloc(sizeof(*tmp_sdma_rht), GFP_KERNEL);
1523+
if (!tmp_sdma_rht) {
1524+
ret = -ENOMEM;
15111525
goto bail;
1526+
}
15121527

1513-
if (rhashtable_init(&dd->sdma_rht, &sdma_rht_params))
1528+
ret = rhashtable_init(tmp_sdma_rht, &sdma_rht_params);
1529+
if (ret < 0)
15141530
goto bail;
1531+
dd->sdma_rht = tmp_sdma_rht;
15151532

15161533
dd_dev_info(dd, "SDMA num_sdma: %u\n", dd->num_sdma);
15171534
return 0;
15181535

15191536
bail:
15201537
sdma_clean(dd, num_engines);
1521-
return -ENOMEM;
1538+
return ret;
15221539
}
15231540

15241541
/**
@@ -1604,7 +1621,6 @@ void sdma_exit(struct hfi1_devdata *dd)
16041621
sdma_finalput(&sde->state);
16051622
}
16061623
sdma_clean(dd, dd->num_sdma);
1607-
rhashtable_free_and_destroy(&dd->sdma_rht, sdma_rht_free, NULL);
16081624
}
16091625

16101626
/*

0 commit comments

Comments
 (0)