Skip to content

Commit 5fcd392

Browse files
axiqiagregkh
authored andcommitted
dmaengine: idxd: fix memory leak in error handling path of idxd_setup_wqs
commit 3fd2f4b upstream. Memory allocated for wqs is not freed if an error occurs during idxd_setup_wqs(). To fix it, free the allocated memory in the reverse order of allocation before exiting the function in case of an error. Fixes: 7c5dd23 ("dmaengine: idxd: fix wq conf_dev 'struct device' lifetime") Fixes: 700af3a ("dmaengine: idxd: add 'struct idxd_dev' as wrapper for conf_dev") Fixes: de5819b ("dmaengine: idxd: track enabled workqueues in bitmap") Fixes: b0325ae ("dmaengine: idxd: add WQ operation cap restriction support") Cc: [email protected] Signed-off-by: Shuai Xue <[email protected]> Reviewed-by: Dave Jiang <[email protected]> Reviewed-by: Fenghua Yu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6b5d770 commit 5fcd392

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

drivers/dma/idxd/init.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
167167

168168
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
169169
if (!idxd->wq_enable_map) {
170-
kfree(idxd->wqs);
171-
return -ENOMEM;
170+
rc = -ENOMEM;
171+
goto err_bitmap;
172172
}
173173

174174
for (i = 0; i < idxd->max_wqs; i++) {
@@ -187,10 +187,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
187187
conf_dev->bus = &dsa_bus_type;
188188
conf_dev->type = &idxd_wq_device_type;
189189
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
190-
if (rc < 0) {
191-
put_device(conf_dev);
190+
if (rc < 0)
192191
goto err;
193-
}
194192

195193
mutex_init(&wq->wq_lock);
196194
init_waitqueue_head(&wq->err_queue);
@@ -201,17 +199,15 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
201199
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
202200
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
203201
if (!wq->wqcfg) {
204-
put_device(conf_dev);
205202
rc = -ENOMEM;
206203
goto err;
207204
}
208205

209206
if (idxd->hw.wq_cap.op_config) {
210207
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
211208
if (!wq->opcap_bmap) {
212-
put_device(conf_dev);
213209
rc = -ENOMEM;
214-
goto err;
210+
goto err_opcap_bmap;
215211
}
216212
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
217213
}
@@ -222,12 +218,28 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
222218

223219
return 0;
224220

225-
err:
221+
err_opcap_bmap:
222+
kfree(wq->wqcfg);
223+
224+
err:
225+
put_device(conf_dev);
226+
kfree(wq);
227+
226228
while (--i >= 0) {
227229
wq = idxd->wqs[i];
230+
if (idxd->hw.wq_cap.op_config)
231+
bitmap_free(wq->opcap_bmap);
232+
kfree(wq->wqcfg);
228233
conf_dev = wq_confdev(wq);
229234
put_device(conf_dev);
235+
kfree(wq);
236+
230237
}
238+
bitmap_free(idxd->wq_enable_map);
239+
240+
err_bitmap:
241+
kfree(idxd->wqs);
242+
231243
return rc;
232244
}
233245

0 commit comments

Comments
 (0)