Andy Walls wrote:
(Sorry, I've probably screwed up the threading on this)
> Dr. David Alan Gilbert wrote:
> > Hi,
> > Sparse pointed me at the following line in ivtv-fileops.c's
> > ivtv_v4l2_write:
> >
> > ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data
> > *)user_buf, elems);
> >
> > Now user_buf is a parameter:
> > const char __user *user_buf,
> >
> > so that is losing the __user, and I don't see what else protects
> > the accesses that ivtv_write_vbi performs.
>
> Ummm, "__user" and similar attributes like "__iomem", don't protect
> anything -- do they? I thought they were there to help tools like
> sparse to detect type problems.
That's right; hence the question.
> It looks like the patch that added "__user" attributes in the ivtv
> driver missed or deliberately ignored this function.
>
> > Is there something that makes this safe?
>
> Not from what I can see in a few minutes worth of looking.
Same here.
> >From include/linux/compiler.h"
>
> #ifdef __CHECKER__
> # define __user __attribute__((noderef, address_space(1)))
> # define __kernel __attribute__((address_space(0)))
> ...
> # define __iomem __attribute__((noderef, address_space(2)))
>
> It would appear that directly dereferencing the user pointer is not a
> good thing to do. However, as you note, that's exactly what
> ivtv_write_vbi() does.
>
> v4l2_write() and ivtv_v4l2_write() are wrappers that don't do any
> copy_from_user() calls before passing the data along.
>
> Why does the call not induce faults for people? I'm not sure. Without
> looking too hard through all the copy_from_user() checks, I'm guessing:
Well as long as the page is mapped I think the access will just work without
the copy_from_user, the problem is mainly when someone puts a dodgy pointer in.
>
> a. the user_buf for the VBI data is likely allocated properly aligned on
> a writeable page.
>
> b. 23 lines of VBI data for two fields only takes up 64*23*2 = 2944
> bytes which likely does not cross a 4096 byte page boundary
>
> c. Not many people have PVR-350's and even less use it to send out VBI
> data to their TV.
>
> Patches welcome. :)
I'm uncomfortable patching that code since I don't really know how it's
supposed to work and don't have any of the hardware to test it with.
However, I think what it needs is:
*) Since ivtv_write_vbi takes an array of those structures it's not
easy to copy it at the point of the call in ivtv_v4l2_write, so I think
the right thing is to change ivtv_write_vbi to take a __user pointer and
return an int as an error code.
*) Then change the call above to
if (ivtv_write_vbi(itv, (const __user struct v4l2_sliced_vbi_data
*)user_buf, elems)<0) {
ivtv_release_stream(s);
return -EFAULT;
}
*) Then in ivtv_write_vbi I think the start of it's main loop could become
something
like:
for (i = 0; i < cnt; i++) {
const struct v4l2_sliced_vbi_data d;
if (copy_from_user(&d, sliced+i, sizeof(struct
v4l2_sliced_vbi_data))
return -EPERM;
then all the d-> to d.
and make sure it returns 0 in the other cases.
That leaves one bit I'm a bit more unsure about which is in
ivtv_process_vbi_data there
is also a call to ivtv_write_vbi and I don't think that's using a __user
pointer, so if
we change ivtv_write_vbi to take a __user pointer what happens? It doesn't
seem to be
too unusual to pass kernel pointers to things that take __user pointers - but
I don't
know enough about it to know whether that's the right thing to do (it'll
generate a sparse
warning, but if it's actually secure unlike the current code it would be better
I guess).
Dave
--
-----Open up your eyes, open up your mind, open up your code -------
/ Dr. David Alan Gilbert | Running GNU/Linux | Happy \
\ gro.gilbert @ treblig.org | | In Hex /
\ _________________________|_____ http://www.treblig.org |_______/
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel