From 71abbe71a0a4a2ee1d811036252eb268b3b233aa Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Tue, 31 May 2022 00:24:25 +0000 Subject: [PATCH] nouveau(4): Plug leaks in nvkm_mem_new_host error branches. --- .../subdev/mmu/nouveau_nvkm_subdev_mmu_mem.c | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/mmu/nouveau_nvkm_subdev_mmu_mem.c b/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/mmu/nouveau_nvkm_subdev_mmu_mem.c index ead5e82fa2da..3dbe6c7fd56e 100644 --- a/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/mmu/nouveau_nvkm_subdev_mmu_mem.c +++ b/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/mmu/nouveau_nvkm_subdev_mmu_mem.c @@ -97,13 +97,17 @@ static void * nvkm_mem_dtor(struct nvkm_memory *memory) { struct nvkm_mem *mem = nvkm_mem(memory); +#ifdef __NetBSD__ + if (mem->dma) + kmem_free(mem->dma, mem->nseg * sizeof(mem->dma[0])); +#endif if (mem->mem) { #ifdef __NetBSD__ struct nvkm_device *device = mem->mmu->subdev.device; bus_dma_tag_t dmat = device->func->dma_tag(device); - kmem_free(mem->dma, - mem->dmamap->dm_nsegs * sizeof(mem->dma[0])); + bus_dmamap_unload(dmat, mem->dmamap); + bus_dmamap_destroy(dmat, mem->dmamap); bus_dmamem_free(dmat, mem->mem, mem->nseg); kmem_free(mem->mem, mem->pages * sizeof(mem->mem[0])); #else @@ -218,16 +222,22 @@ nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size, if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { if (args->v0.dma) { nvkm_memory_ctor(&nvkm_mem_dma, &mem->memory); +#ifdef __NetBSD__ mem->dmamap = args->v0.dma; - mem->dma = kmem_zalloc(mem->dmamap->dm_nsegs * + mem->nsegs = mem->dmamap->dm_nsegs; + mem->dma = kmem_zalloc(mem->nsegs * sizeof(mem->dma[0]), KM_SLEEP); for (unsigned i = 0; i < mem->dmamap->dm_nsegs; i++) { KASSERT(mem->dmamap->dm_segs[i].ds_len <= PAGE_SIZE); mem->dma[i] = mem->dmamap->dm_segs[i].ds_addr; } +#else + mem->dma = args->v0.dma; +#endif } else { #ifdef __NetBSD__ + kfree(mem); return -ENODEV; #else nvkm_memory_ctor(&nvkm_mem_sgl, &mem->memory); @@ -235,8 +245,14 @@ nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size, #endif } - if (!IS_ALIGNED(size, PAGE_SIZE)) + if (!IS_ALIGNED(size, PAGE_SIZE)) { +#ifdef __NetBSD__ + kmem_free(mem->dma, mem->dmamap->dm_nsegs * + sizeof(mem->dma[0])); +#endif + kfree(mem); return -EINVAL; + } mem->pages = size >> PAGE_SHIFT; return 0; } else @@ -259,6 +275,7 @@ nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size, mem->mem, size, &mem->nseg, BUS_DMA_WAITOK); if (ret) { fail0: kmem_free(mem->mem, size * sizeof(mem->mem[0])); + kfree(mem); return ret; } /* XXX errno NetBSD->Linux */