On Wed, Aug 06, 2014 at 11:45:48PM -0400, Jerome Glisse wrote:
> On Wed, Aug 06, 2014 at 10:24:31PM +0200, Daniel Vetter wrote:
> > On Wed, Aug 06, 2014 at 02:34:16PM -0400, Jerome Glisse wrote:
> > > On Wed, Aug 06, 2014 at 07:17:25PM +0200, Christian K?nig wrote:
> > > > Am 06.08.2014 um 18:08 schrieb Jerome Glisse:
> > > > >On Wed, Aug 06, 2014 at 08:55:28AM +0200, Christian K?nig wrote:
> > > > >>Am 06.08.2014 um 00:13 schrieb Jerome Glisse:
> > > > >>>On Tue, Aug 05, 2014 at 07:45:21PM +0200, Christian K?nig wrote:
> > > > >>>>Am 05.08.2014 um 19:39 schrieb Jerome Glisse:
> > > > >>>>>On Tue, Aug 05, 2014 at 06:05:29PM +0200, Christian K?nig wrote:
> > > > >>>>>>From: Christian K?nig <christian.koenig at amd.com>
> > > > >>>>>>
> > > > >>>>>>Avoid problems with writeback by limiting userptr to anonymous 
> > > > >>>>>>memory.
> > > > >>>>>>
> > > > >>>>>>v2: add commit and code comments
> > > > >>>>>I guess, i have not expressed myself clearly. This is bogus, you 
> > > > >>>>>pretend
> > > > >>>>>you want to avoid writeback issue but you still allow userspace to 
> > > > >>>>>map
> > > > >>>>>file backed pages (which by the way might be a regular bo object 
> > > > >>>>>from
> > > > >>>>>another device for instance and that would be fun).
> > > > >>>>>
> > > > >>>>>So this patch is a no go and i would rather see that this userptr 
> > > > >>>>>to
> > > > >>>>>be restricted to anon vma only no matter what. No flags here.
> > > > >>>>Mapping of non anonymous memory (e.g. everything get_user_pages 
> > > > >>>>won't fail
> > > > >>>>with) is restricted to read only access by the GPU.
> > > > >>>>
> > > > >>>>I'm fine with making it a hard requirement for all mappings if you 
> > > > >>>>say it's
> > > > >>>>a must have.
> > > > >>>>
> > > > >>>Well for time being you should force read only. The way you 
> > > > >>>implement write
> > > > >>>is broken. Here is how it can abuse to allow write to a file backed 
> > > > >>>mmap.
> > > > >>>
> > > > >>>mmap(fixaddress,fixedsize,NOFD)
> > > > >>>userptr_ioctl(fixedaddress, RADEON_GEM_USERPTR_ANONONLY)
> > > > >>>// bo is created successfully because fixedaddress is part of anonvma
> > > > >>>munmap(fixedaddress,fixedsize)
> > > > >>>// radeon get mmu_notifier_range_start callback and unbind page from 
> > > > >>>the
> > > > >>>// bo but radeon does not know there was an unmap.
> > > > >>>mmap(fixaddress,fixedsize,fd_to_this_read_only_file_i_want_to_write_to)
> > > > >>>radeon_ioctl_use_my_userptrbo
> > > > >>>// bo is bind again by radeon and because all flag are set at 
> > > > >>>creation
> > > > >>>// it is map with write permission allowing someone to write to a 
> > > > >>>file
> > > > >>>// that might be read only for the user.
> > > > >>>//
> > > > >>>// Script kiddies it's time to learn about gpu ...
> > > > >>>
> > > > >>>Of course if you this patch (kind of selling my own junk here) :
> > > > >>>
> > > > >>>http://www.spinics.net/lists/linux-mm/msg75878.html
> > > > >>>
> > > > >>>then you could know inside the range_start that you should remove the
> > > > >>>write permission and that it should be rechecked on next bind.
> > > > >>>
> > > > >>>Note that i have not read much of your code so maybe you handle this
> > > > >>>case somehow.
> > > > >>I've stumbled over this attack vector as well and it's the reason why 
> > > > >>I've
> > > > >>moved checking the access rights to the bind callback instead of BO 
> > > > >>creation
> > > > >>time with V5 of the patch.
> > > > >>
> > > > >>This way you get an -EFAULT if you try something like this on command
> > > > >>submission time.
> > > > >So you seem immune to that issue but you are still not checking if the 
> > > > >anon
> > > > >vma is writeable which you should again security concern here.
> > > > 
> > > > We check the access rights of the pointer using:
> > > > >        if (!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
> > > > >(long)gtt->userptr,
> > > > >                       ttm->num_pages * PAGE_SIZE))
> > > > >                return -EFAULT;
> > > > 
> > > > Shouldn't that be enough?
> > > 
> > > No, access_ok only check against special area on some architecture and i 
> > > am
> > > pretty sure on x86 the VERIFY_WRITE or VERIFY_READ is just flat out 
> > > ignored.
> > > 
> > > What you need to test is the vma vm_flags somethings like
> > > 
> > > if (write && !(vma->vm_flags VM_WRITE))
> > >    return -EPERM;
> > > 
> > > Which need to happen on all bind.
> > 
> > access_ok is _only_ valid in combination with copy_from/to_user and
> > friends and is an optimization of the access checks depending upon
> > architecture. You always need them both, one alone is useless.
> 
> ENOPARSE, access_ok will always return the same value for a given address at 
> least
> on x86 so if address supplied at ioctl time is a valid userspace address then 
> it
> will still be a valid userspace address at buffer object bind time (note that 
> the
> user address is immutable here). So access_ok can be done once and only once 
> inside
> the ioctl and then for the write permission you need to recheck the vma each 
> time
> you bind the object (or rather each time the previous bind was invalidated by 
> some
> mmu_notifier call).
> 
> That being said access_ok is kind of useless given that get_user_page will 
> fail on
> kernel address and i assume for any special address any architecture might 
> have. So
> strictly speaking the access_ok is just a way to fail early and flatout 
> instead of
> delaying the failure to bind time.

Well that's what I've tried to say. For gup you don't need access_ok,
that's really just one part of copy_from/to_user machinery. And afaik it's
not specified what exactly access_ok checks (on x86 it only checks for the
kernel address limit) so I don't think there's a lot of use in it for gup.

Maybe I should have done an s/valid/useful/ in my short comment.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

Reply via email to