[PATCH 1/2] drm/amdgpu: fix race in GEM VA map IOCTL

Nicolai Hähnle nhaehnle at gmail.com
Mon Jan 30 17:41:58 UTC 2017


On 30.01.2017 10:45, Christian König wrote:
> From: Christian König <christian.koenig at amd.com>
>
> Somebody could try to free the bo_va between mapping and updating it.
>
> Signed-off-by: Christian König <christian.koenig at amd.com>

Nice catch! Both patches:

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 45 ++++++++++-----------------------
>  1 file changed, 14 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index 7a265d9..ec5b184 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -489,67 +489,50 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
>   *
>   * @adev: amdgpu_device pointer
>   * @bo_va: bo_va to update
> + * @list: validation list
> + * opration: map or unmap
>   *
>   * Update the bo_va directly after setting it's address. Errors are not
>   * vital here, so they are not reported back to userspace.
>   */
>  static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
>  				    struct amdgpu_bo_va *bo_va,
> +				    struct list_head *list,
>  				    uint32_t operation)
>  {
> -	struct ttm_validate_buffer tv, *entry;
> -	struct amdgpu_bo_list_entry vm_pd;
> -	struct ww_acquire_ctx ticket;
> -	struct list_head list, duplicates;
> -	int r;
> -
> -	INIT_LIST_HEAD(&list);
> -	INIT_LIST_HEAD(&duplicates);
> -
> -	tv.bo = &bo_va->bo->tbo;
> -	tv.shared = true;
> -	list_add(&tv.head, &list);
> -
> -	amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd);
> -
> -	/* Provide duplicates to avoid -EALREADY */
> -	r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
> -	if (r)
> -		goto error_print;
> +	struct ttm_validate_buffer *entry;
> +	int r = -ERESTARTSYS;
>
> -	list_for_each_entry(entry, &list, head) {
> +	list_for_each_entry(entry, list, head) {
>  		struct amdgpu_bo *bo =
>  			container_of(entry->bo, struct amdgpu_bo, tbo);
>
>  		/* if anything is swapped out don't swap it in here,
>  		   just abort and wait for the next CS */
>  		if (!amdgpu_bo_gpu_accessible(bo))
> -			goto error_unreserve;
> +			goto error;
>
>  		if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
> -			goto error_unreserve;
> +			goto error;
>  	}
>
>  	r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
>  				      NULL);
>  	if (r)
> -		goto error_unreserve;
> +		goto error;
>
>  	r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
>  	if (r)
> -		goto error_unreserve;
> +		goto error;
>
>  	r = amdgpu_vm_clear_freed(adev, bo_va->vm);
>  	if (r)
> -		goto error_unreserve;
> +		goto error;
>
>  	if (operation == AMDGPU_VA_OP_MAP)
>  		r = amdgpu_vm_bo_update(adev, bo_va, false);
>
> -error_unreserve:
> -	ttm_eu_backoff_reservation(&ticket, &list);
> -
> -error_print:
> +error:
>  	if (r && r != -ERESTARTSYS)
>  		DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
>  }
> @@ -642,10 +625,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
>  	default:
>  		break;
>  	}
> -	ttm_eu_backoff_reservation(&ticket, &list);
>  	if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
>  	    !amdgpu_vm_debug)
> -		amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
> +		amdgpu_gem_va_update_vm(adev, bo_va, &list, args->operation);
> +	ttm_eu_backoff_reservation(&ticket, &list);
>
>  	drm_gem_object_unreference_unlocked(gobj);
>  	return r;
>



More information about the amd-gfx mailing list