[PATCH v3 1/1] drm/ttm: Fix COW check

Daniel Vetter daniel at ffwll.ch
Wed Jul 14 10:46:42 UTC 2021


On Wed, Jul 14, 2021 at 12:44:00PM +0200, Daniel Vetter wrote:
> On Mon, Jul 12, 2021 at 06:06:36PM -0400, Felix Kuehling wrote:
> > KFD Thunk maps invisible VRAM BOs with PROT_NONE, MAP_PRIVATE.
> > is_cow_mapping returns true for these mappings. Add a check for
> > vm_flags & VM_WRITE to avoid mmap failures on private read-only or
> > PROT_NONE mappings.
> > 
> > v2: protect against mprotect making a mapping writable after the fact
> > v3: update driver-specific vm_operations_structs
> > 
> > Fixes: f91142c62161 ("drm/ttm: nuke VM_MIXEDMAP on BO mappings v3")
> > Signed-off-by: Felix Kuehling <Felix.Kuehling at amd.com>
> > Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
> 
> So looking at vmf_insert_pfn_prot() and the comment there we can't have
> VM_PFNMAP and is_cow_mapping ever be true, or things break. On platforms
> without pte_special at least.
> 
> So I'm not sure this is a great idea, and definitely not for all drivers
> ...
> 
> Can we clear VM_MAYWRITE instead to force this to be a non-cow mapping
> instead?

Quick git grep says there's plenty of drivers which clear MAYWRITE, and
often with comments to block mprotect upfront. That feels like the cleaner
approach, and maybe limited to an overwrite in just amdgpu with a comment
explaining why it's needed? As in amdgpu mmap function which just clears
VM_MAYWRITE if it's a cow mapping and then calls into ttm mmap
implementation.
-Daniel

> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c  |  3 ++-
> >  drivers/gpu/drm/nouveau/nouveau_gem.c    |  3 ++-
> >  drivers/gpu/drm/radeon/radeon_gem.c      |  3 ++-
> >  drivers/gpu/drm/ttm/ttm_bo_vm.c          | 14 +++++++++++++-
> >  drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c |  1 +
> >  include/drm/ttm/ttm_bo_api.h             |  4 ++++
> >  6 files changed, 24 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> > index b3404c43a911..1aa750a6a5d2 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> > @@ -79,7 +79,8 @@ static const struct vm_operations_struct amdgpu_gem_vm_ops = {
> >  	.fault = amdgpu_gem_fault,
> >  	.open = ttm_bo_vm_open,
> >  	.close = ttm_bo_vm_close,
> > -	.access = ttm_bo_vm_access
> > +	.access = ttm_bo_vm_access,
> > +	.mprotect = ttm_bo_vm_mprotect
> >  };
> >  
> >  static void amdgpu_gem_object_free(struct drm_gem_object *gobj)
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
> > index 5b27845075a1..164ea564bb7a 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
> > +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
> > @@ -70,7 +70,8 @@ static const struct vm_operations_struct nouveau_ttm_vm_ops = {
> >  	.fault = nouveau_ttm_fault,
> >  	.open = ttm_bo_vm_open,
> >  	.close = ttm_bo_vm_close,
> > -	.access = ttm_bo_vm_access
> > +	.access = ttm_bo_vm_access,
> > +	.mprotect = ttm_bo_vm_mprotect
> >  };
> >  
> >  void
> > diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
> > index 458f92a70887..c19ad07eb7b5 100644
> > --- a/drivers/gpu/drm/radeon/radeon_gem.c
> > +++ b/drivers/gpu/drm/radeon/radeon_gem.c
> > @@ -77,7 +77,8 @@ static const struct vm_operations_struct radeon_gem_vm_ops = {
> >  	.fault = radeon_gem_fault,
> >  	.open = ttm_bo_vm_open,
> >  	.close = ttm_bo_vm_close,
> > -	.access = ttm_bo_vm_access
> > +	.access = ttm_bo_vm_access,
> > +	.mprotect = ttm_bo_vm_mprotect
> >  };
> >  
> >  static void radeon_gem_object_free(struct drm_gem_object *gobj)
> > diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
> > index f56be5bc0861..fb325bad5db6 100644
> > --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
> > +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
> > @@ -542,17 +542,29 @@ int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr,
> >  }
> >  EXPORT_SYMBOL(ttm_bo_vm_access);
> >  
> > +int ttm_bo_vm_mprotect(struct vm_area_struct *vma, unsigned long start,
> > +		       unsigned long end, unsigned long newflags)
> > +{
> > +	/* Enforce no COW since would have really strange behavior with it. */
> > +	if (is_cow_mapping(newflags) && (newflags & VM_WRITE))
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ttm_bo_vm_mprotect);
> > +
> >  static const struct vm_operations_struct ttm_bo_vm_ops = {
> >  	.fault = ttm_bo_vm_fault,
> >  	.open = ttm_bo_vm_open,
> >  	.close = ttm_bo_vm_close,
> >  	.access = ttm_bo_vm_access,
> > +	.mprotect = ttm_bo_vm_mprotect,
> >  };
> >  
> >  int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo)
> >  {
> >  	/* Enforce no COW since would have really strange behavior with it. */
> > -	if (is_cow_mapping(vma->vm_flags))
> > +	if (is_cow_mapping(vma->vm_flags) && (vma->vm_flags & VM_WRITE))
> >  		return -EINVAL;
> >  
> >  	ttm_bo_get(bo);
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
> > index e6b1f98ec99f..e4bf7dc99320 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
> > @@ -61,6 +61,7 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
> >  		.fault = vmw_bo_vm_fault,
> >  		.open = ttm_bo_vm_open,
> >  		.close = ttm_bo_vm_close,
> > +		.mprotect = ttm_bo_vm_mprotect,
> >  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> >  		.huge_fault = vmw_bo_vm_huge_fault,
> >  #endif
> > diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
> > index f681bbdbc698..40eb95875355 100644
> > --- a/include/drm/ttm/ttm_bo_api.h
> > +++ b/include/drm/ttm/ttm_bo_api.h
> > @@ -605,6 +605,10 @@ void ttm_bo_vm_close(struct vm_area_struct *vma);
> >  
> >  int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr,
> >  		     void *buf, int len, int write);
> > +
> > +int ttm_bo_vm_mprotect(struct vm_area_struct *vma, unsigned long start,
> > +		       unsigned long end, unsigned long newflags);
> > +
> >  bool ttm_bo_delayed_delete(struct ttm_device *bdev, bool remove_all);
> >  
> >  vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot);
> > -- 
> > 2.32.0
> > 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list