On the legacy pre-NV25 DMA path (chipset < 0x25),
nouveau_gem_ioctl_pushbuf() copies each push descriptor's offset and
length (both __u64) from userspace and feeds them to
nouveau_bo_wr32(nvbo, (push[i].offset + push[i].length - 8)/ 4, cmd).
nouveau_bo_wr32() performs an unchecked "mem += index; *mem = val", so
the index must be bounded against the bo. Only push[i].bo_index is
validated; nothing constrains offset or length against
nvbo->bo.base.size.
Fix by rejecting offset + length < 8 or > nvbo->bo.base.size before the
nouveau_bo_wr32() call, mirroring the guard already present in the
sibling nouveau_gem_pushbuf_reloc_apply() path.
Fixes: a1606a9596e5 ("drm/nouveau: new gem pushbuf interface, bump to 0.0.16")
Reported-by: Yuhao Jiang <[email protected]>
Cc: [email protected]
Signed-off-by: Junrui Luo <[email protected]>
---
drivers/gpu/drm/nouveau/nouveau_gem.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c
b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 20dba02d6175..e9309279ba8d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -898,6 +898,17 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void
*data,
cmd = chan->push.addr + ((chan->dma.cur + 2) << 2);
cmd |= 0x20000000;
if (unlikely(cmd != req->suffix0)) {
+ if (unlikely(push[i].offset +
+ push[i].length < 8 ||
+ push[i].offset +
+ push[i].length >
+ nvbo->bo.base.size)) {
+ NV_PRINTK(err, cli, "push %d buffer not
within bo\n", i);
+ WIND_RING(chan);
+ ret = -EINVAL;
+ goto out;
+ }
+
if (!nvbo->kmap.virtual) {
ret = ttm_bo_kmap(&nvbo->bo, 0,
PFN_UP(nvbo->bo.base.size),
---
base-commit: ddd664bbff63e09e7a7f9acae9c43605d4cf185f
change-id: 20260607-fixes-51e37123eb9b
Best regards,
--
Junrui Luo <[email protected]>