[PATCH] drm/nouveau/iccsense: fix memory leak in nvkm_iccsense_oneinit
Muhammad Bilal <[email protected]> Tue, 4 Aug 2026 02:50:22 +0500
| Newsgroups | org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
nvbios_iccsense_parse() allocates stbl.rail via kmalloc_objs() to hold
the per-entry power-rail table parsed out of the vbios ICCSENSE table
(drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c). The only
consumer of that table, nvkm_iccsense_oneinit(), copies the fields it
needs into freshly allocated struct nvkm_iccsense_rail nodes but never
frees stbl.rail itself, on either the normal return path or the
-ENOMEM error path taken when a rail node allocation fails.
nvkm_iccsense_dtor() only walks and frees iccsense->rails (the copied
nodes) and iccsense->sensors -- it has no reference to the transient
stbl.rail array, so that allocation is unrecoverably leaked every time
oneinit() runs.
Observed with kmemleak on a KASAN build:
unreferenced object 0xffff888104cbe480 (size 96)
comm "(udev-worker)" pid 526
backtrace:
nvbios_iccsense_parse+0x217/0x740 [nouveau]
nvkm_iccsense_oneinit+0x140/0xdd0
Free stbl.rail once we're done consuming it, via a common exit path
that also covers the -ENOMEM case.
Note: ret is reset to 0 immediately before the loop rather than at
declaration time, since it is already in use a few lines earlier for
the unrelated nvbios_power_budget_header()/nvbios_power_budget_entry()
return codes. Returning it unreset from the done: label would leak
that unrelated (and commonly non-zero, e.g. on boards without a power
budget table) status code out of oneinit() on the success path.
Fixes: b71c0892631a ("drm/nouveau/iccsense: implement for ina209, ina219 and ina3221")
Cc: [email protected]
Signed-off-by: Muhammad Bilal <[email protected]>
---
drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
index 3ccdbbe2fad0..6bfe4913dcb6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
@@ -239,6 +239,7 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
return 0;
iccsense->data_valid = true;
+ ret = 0;
for (i = 0; i < stbl.nr_entry; ++i) {
struct pwr_rail_t *pwr_rail = &stbl.rail[i];
struct nvkm_iccsense_sensor *sensor;
@@ -280,8 +281,10 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
}
rail = kmalloc_obj(*rail);
- if (!rail)
- return -ENOMEM;
+ if (!rail) {
+ ret = -ENOMEM;
+ goto done;
+ }
rail->read = read;
rail->sensor = sensor;
@@ -291,7 +294,10 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
list_add_tail(&rail->head, &iccsense->rails);
}
}
- return 0;
+
+done:
+ kfree(stbl.rail);
+ return ret;
}
static int
--
2.55.0