AFAICS, videobuf-vmalloc use of mem->vma and mem->vmalloc is
bogus.
You obtain the latter with vmalloc_user(); so far, so good. Then you have
retval=remap_vmalloc_range(vma, mem->vmalloc,0);
where vma is given to you by mmap(); again, fine - we get the memory
pointed to be mem->vmalloc() mapped at vma->vm_start.
Now we get the trouble: things like
static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
{
...
void *vbuf=videobuf_to_vmalloc (&buf->vb);
...
copy_to_user(vbuf + ..., ..., ...)
get vbuf equal to ->vmalloc of buf->vp.priv and that is _not_ a userland
address. Giving it to copy_to_user() is not going to do anything good.
On some targets it'll fail, on some - write to unrelated user memory.
What is going on there? If that's an attempt to copy into that buffer
allocated by vmalloc_user(), why are we doing copy_to_user() at all?
But there's more; we have made a copy of vma (kmalloc+memcpy), stored it in
mem->vma and later we cheerfully do remap_vmalloc_range(mem->vma,....).
And kfree that mem->vma immediately afterwards. What the hell? It might
not break now, but that seems to be playing very fast and loose with the
warranties provided by VM.
On Monday 15 October 2007 12:01, Al Viro wrote:
> AFAICS, videobuf-vmalloc use of mem->vma and mem->vmalloc is
> bogus.
>
> You obtain the latter with vmalloc_user(); so far, so good. Then you have
> retval=remap_vmalloc_range(vma, mem->vmalloc,0);
> where vma is given to you by mmap(); again, fine - we get the memory
> pointed to be mem->vmalloc() mapped at vma->vm_start.
>
> Now we get the trouble: things like
>
> static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
> {
> ...
> void *vbuf=videobuf_to_vmalloc (&buf->vb);
> ...
> copy_to_user(vbuf + ..., ..., ...)
>
> get vbuf equal to ->vmalloc of buf->vp.priv and that is _not_ a userland
> address. Giving it to copy_to_user() is not going to do anything good.
> On some targets it'll fail, on some - write to unrelated user memory.
> What is going on there? If that's an attempt to copy into that buffer
> allocated by vmalloc_user(), why are we doing copy_to_user() at all?
Right you are. remap_vmalloc_range doesn't turn the passed vmalloc
area into user memory (it creates a completely new mapping).
Presumably it either wants to copy_to_user to that new mapping, or
memcpy to ->vmalloc? Would the former be an attempt to avoid some
virtual aliasing issues?
> But there's more; we have made a copy of vma (kmalloc+memcpy), stored it in
> mem->vma and later we cheerfully do remap_vmalloc_range(mem->vma,....).
> And kfree that mem->vma immediately afterwards. What the hell? It might
> not break now, but that seems to be playing very fast and loose with the
> warranties provided by VM.
I don't know why one would be finding remap_vmalloc_range to fail
it mmap time but not later? Should just do it at mmap time and if
that is failing, then work out why (or ask linux-mm for help).
Actually there is probably a window where we can get subsequent
anonymous pages faulted into the empty vma there if we haven't
remapped it, then the subsequent attempt to remap will hit the
BUG_ON in remap_pte_range.
(that's aside from the big conceptual problem with passing in an
"invented" vma... don't do that! (: )