[PATCH] drm/i915/gvt: Convert from atomic_t to refcount_t on intel_vgpu_ppgtt_spt->refcount
refcount_t type and corresponding API can protect refcounters from accidental underflow and overflow and further use-after-free situations Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/i915/gvt/gtt.c | 11 ++- drivers/gpu/drm/i915/gvt/gtt.h | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index cc2c05e18206..62f3daff5a36 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -841,7 +841,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt( } spt->vgpu = vgpu; - atomic_set(&spt->refcount, 1); + refcount_set(&spt->refcount, 1); INIT_LIST_HEAD(&spt->post_shadow_list); /* @@ -927,18 +927,19 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn( static inline void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt) { - int v = atomic_read(&spt->refcount); + int v = refcount_read(&spt->refcount); trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1)); - atomic_inc(&spt->refcount); + refcount_inc(&spt->refcount); } static inline int ppgtt_put_spt(struct intel_vgpu_ppgtt_spt *spt) { - int v = atomic_read(&spt->refcount); + int v = refcount_read(&spt->refcount); trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1)); - return atomic_dec_return(&spt->refcount); + refcount_dec(&spt->refcount); + return refcount_read(&spt->refcount); } static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt); diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index 3bf45672ef98..944c2d0739df 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.h +++ b/drivers/gpu/drm/i915/gvt/gtt.h @@ -38,6 +38,7 @@ #include #include #include +#include #include "gt/intel_gtt.h" @@ -243,7 +244,7 @@ struct intel_vgpu_oos_page { /* Represent a vgpu shadow page table. */ struct intel_vgpu_ppgtt_spt { - atomic_t refcount; + refcount_t refcount; struct intel_vgpu *vgpu; struct { -- 2.7.4
[PATCH] fbmem: Convert from atomic_t to refcount_t on fb_info->count
refcount_t type and corresponding API can protect refcounters from accidental underflow and overflow and further use-after-free situations. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/video/fbdev/core/fbmem.c | 6 +++--- include/linux/fb.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 98f193078c05..b7d26b928e1d 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -67,7 +67,7 @@ static struct fb_info *get_fb_info(unsigned int idx) mutex_lock(®istration_lock); fb_info = registered_fb[idx]; if (fb_info) - atomic_inc(&fb_info->count); + refcount_inc(&fb_info->count); mutex_unlock(®istration_lock); return fb_info; @@ -75,7 +75,7 @@ static struct fb_info *get_fb_info(unsigned int idx) static void put_fb_info(struct fb_info *fb_info) { - if (!atomic_dec_and_test(&fb_info->count)) + if (!refcount_dec_and_test(&fb_info->count)) return; if (fb_info->fbops->fb_destroy) fb_info->fbops->fb_destroy(fb_info); @@ -1594,7 +1594,7 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) break; fb_info->node = i; - atomic_set(&fb_info->count, 1); + refcount_set(&fb_info->count, 1); mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); diff --git a/include/linux/fb.h b/include/linux/fb.h index ecfbcc0553a5..5950f8f5dc74 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -2,6 +2,7 @@ #ifndef _LINUX_FB_H #define _LINUX_FB_H +#include #include #include @@ -435,7 +436,7 @@ struct fb_tile_ops { struct fb_info { - atomic_t count; + refcount_t count; int node; int flags; /* -- 2.7.4
[PATCH] drm/exynos: Convert from atomic_t to refcount_t on g2d_cmdlist_userptr->refcount
refcount_t type and corresponding API can protect refcounters from accidental underflow and overflow and further use-after-free situations. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index cab4d2c370a7..4921e84c374d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -4,6 +4,7 @@ * Authors: Joonyoung Shim */ +#include #include #include #include @@ -208,7 +209,7 @@ struct g2d_cmdlist_userptr { struct page **pages; unsigned intnpages; struct sg_table *sgt; - atomic_trefcount; + refcount_t refcount; boolin_pool; boolout_of_list; }; @@ -386,9 +387,9 @@ static void g2d_userptr_put_dma_addr(struct g2d_data *g2d, if (force) goto out; - atomic_dec(&g2d_userptr->refcount); + refcount_dec(&g2d_userptr->refcount); - if (atomic_read(&g2d_userptr->refcount) > 0) + if (refcount_read(&g2d_userptr->refcount) > 0) return; if (g2d_userptr->in_pool) @@ -436,7 +437,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d, * and different size. */ if (g2d_userptr->size == size) { - atomic_inc(&g2d_userptr->refcount); + refcount_inc(&g2d_userptr->refcount); *obj = g2d_userptr; return &g2d_userptr->dma_addr; @@ -461,7 +462,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d, if (!g2d_userptr) return ERR_PTR(-ENOMEM); - atomic_set(&g2d_userptr->refcount, 1); + refcount_set(&g2d_userptr->refcount, 1); g2d_userptr->size = size; start = userptr & PAGE_MASK; -- 2.7.4
[PATCH] drm/amd/amdkfd: fix possible memory leak in svm_range_restore_pages
The memory leak issue may take place in an error handling path. When p->xnack_enabled is NULL, the function simply returns with -EFAULT and forgets to decrement the reference count of a kfd_process object bumped by kfd_lookup_process_by_pasid, which may incur memory leaks. Fix it by jumping to label "out", in which kfd_unref_process() decreases the refcount. Signed-off-by: Xiyu Yang Signed-off-by: Xin Xiong Signed-off-by: Xin Tan --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index e883731c3f8f..0f7f1e5621ea 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -2426,7 +2426,8 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, } if (!p->xnack_enabled) { pr_debug("XNACK not enabled for pasid 0x%x\n", pasid); - return -EFAULT; + r = -EFAULT; + goto out; } svms = &p->svms; -- 2.7.4
[PATCH] drm/amdgpu/display: Fix dc_sink refcnt leak when detecting link
emulated_link_detect() invokes dc_sink_retain(), which increases the refcount of the "prev_sink". When emulated_link_detect() returns, local variable "prev_sink" becomes invalid, so the refcount should be decreased to keep refcount balanced. The reference counting issue happens in all paths of emulated_link_detect(), which forgets to decrease the refcnt increased by dc_sink_retain(), causing a refcnt leak. Fix this issue by adding a "err_sink_put" label and calling dc_sink_release() before emulated_link_detect() returns. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e997251a8b57..1b0c4f11b9b1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1633,7 +1633,7 @@ static void emulated_link_detect(struct dc_link *link) default: DC_ERROR("Invalid connector type! signal:%d\n", link->connector_signal); - return; + goto err_sink_put; } sink_init_data.link = link; @@ -1642,7 +1642,7 @@ static void emulated_link_detect(struct dc_link *link) sink = dc_sink_create(&sink_init_data); if (!sink) { DC_ERROR("Failed to create sink!\n"); - return; + goto err_sink_put; } /* dc_sink_create returns a new reference */ @@ -1655,6 +1655,9 @@ static void emulated_link_detect(struct dc_link *link) if (edid_status != EDID_OK) DC_ERROR("Failed to read EDID"); +err_sink_put: + if (prev_sink != NULL) + dc_sink_release(prev_sink); } -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/amdgpu/display: Fix dc_sink refcnt leak in dc_link_detect_helper
dc_link_detect_helper() invokes dc_sink_retain(), which increases the refcount of the "prev_sink". When dc_link_detect_helper() returns, local variable "prev_sink" becomes invalid, so the refcount should be decreased to keep refcount balanced. The reference counting issue happens in one exception handling path of dc_link_detect_helper(). When alt mode times out, the function forgets to decrease the refcnt increased by dc_sink_retain(), causing a refcnt leak. Fix this issue by calling dc_sink_release() when alt mode times out. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a09119c10d7c..91550d9a1abb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -832,6 +832,8 @@ static bool dc_link_detect_helper(struct dc_link *link, /* if alt mode times out, return false */ if (wait_for_alt_mode(link) == false) { + if (prev_sink != NULL) + dc_sink_release(prev_sink); return false; } } -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/ttm: Fix dma_fence refcnt leak when adding move fence
ttm_bo_add_move_fence() invokes dma_fence_get(), which returns a reference of the specified dma_fence object to "fence" with increased refcnt. When ttm_bo_add_move_fence() returns, local variable "fence" becomes invalid, so the refcount should be decreased to keep refcount balanced. The reference counting issue happens in one exception handling path of ttm_bo_add_move_fence(). When no_wait_gpu flag is equals to true, the function forgets to decrease the refcnt increased by dma_fence_get(), causing a refcnt leak. Fix this issue by calling dma_fence_put() when no_wait_gpu flag is equals to true. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/ttm/ttm_bo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index f73b81c2576e..0f20e14a4cfd 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -883,8 +883,10 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, if (!fence) return 0; - if (no_wait_gpu) + if (no_wait_gpu) { + dma_fence_put(fence); return -EBUSY; + } dma_resv_add_shared_fence(bo->base.resv, fence); -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/ttm: Fix dma_fence refcnt leak in ttm_bo_vm_fault_reserved
ttm_bo_vm_fault_reserved() invokes dma_fence_get(), which returns a reference of the specified dma_fence object to "moving" with increased refcnt. When ttm_bo_vm_fault_reserved() returns, local variable "moving" becomes invalid, so the refcount should be decreased to keep refcount balanced. The reference counting issue happens in several exception handling paths of ttm_bo_vm_fault_reserved(). When those error scenarios occur such as "err" equals to -EBUSY, the function forgets to decrease the refcnt increased by dma_fence_get(), causing a refcnt leak. Fix this issue by calling dma_fence_put() when no_wait_gpu flag is equals to true. Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index a43aa7275f12..fa03fab02076 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -300,8 +300,10 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, break; case -EBUSY: case -ERESTARTSYS: + dma_fence_put(moving); return VM_FAULT_NOPAGE; default: + dma_fence_put(moving); return VM_FAULT_SIGBUS; } -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/i915/selftests: Fix i915_address_space refcnt leak
igt_ppgtt_pin_update() invokes i915_gem_context_get_vm_rcu(), which returns a reference of the i915_address_space object to "vm" with increased refcount. When igt_ppgtt_pin_update() returns, "vm" becomes invalid, so the refcount should be decreased to keep refcount balanced. The reference counting issue happens in two exception handling paths of igt_ppgtt_pin_update(). When i915_gem_object_create_internal() returns IS_ERR, the refcnt increased by i915_gem_context_get_vm_rcu() is not decreased, causing a refcnt leak. Fix this issue by jumping to "out_vm" label when i915_gem_object_create_internal() returns IS_ERR. Fixes: 4049866f0913 ("drm/i915/selftests: huge page tests") Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan --- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 9311250d7d6f..7a7763be6b2e 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1578,8 +1578,10 @@ static int igt_ppgtt_pin_update(void *arg) unsigned int page_size = BIT(first); obj = i915_gem_object_create_internal(dev_priv, page_size); - if (IS_ERR(obj)) - return PTR_ERR(obj); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out_vm; + } vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { @@ -1632,8 +1634,10 @@ static int igt_ppgtt_pin_update(void *arg) } obj = i915_gem_object_create_internal(dev_priv, PAGE_SIZE); - if (IS_ERR(obj)) - return PTR_ERR(obj); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out_vm; + } vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel