From 5354ba1853e575e15692865c77e7379ce3560936 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 | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 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..ab3a8a97b991 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,19 @@ 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->dmamap->dm_nsegs * 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 @@ -228,6 +234,7 @@ nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size, } } else { #ifdef __NetBSD__ + kfree(mem); return -ENODEV; #else nvkm_memory_ctor(&nvkm_mem_sgl, &mem->memory); @@ -235,8 +242,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 +272,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 */