When using mmap() on a prime imported buffer allocated by a different driver (such as imx-drm) the later munmap() does not correctly decrement the refcount of the original enaviv_gem_object, leading to a leak. Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group> Cc: stable@xxxxxxxxxxxxxxx --- drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index f24dd21..28a01b8 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -93,7 +93,25 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj) static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj, struct vm_area_struct *vma) { - return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0); + int ret; + + ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0); + + /* drm_gem_mmap_obj() has already been called before this function + * and has incremented our refcount, expecting it to be decremented + * on unmap() via drm_gem_vm_close(). + * However dma_buf_mmap() invokes drm_gem_cma_prime_mmap() + * that ends up updating the vma->vma_private_data to point to the + * dma_buf's gem object. + * Hence our gem object here will not have its refcount decremented + * when userspace does unmap(). + * So decrement the refcount here to avoid a memory leak if the dma + * buf mapping was successful. + */ + if (!ret) + drm_gem_object_put_unlocked(&etnaviv_obj->base); + + return ret; } static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = { -- 1.9.1