Re: verify_area(...) possible problem.

Andi Kleen (ak@muc.de)
13 Apr 1999 21:41:37 +0200


douglas.gilbert@rbcds.com (Gilbert, Douglas) writes:

> Linus Thorvalds wrote:
>
> > ... you can do
> >
> > error = access_ok(VERIFY_READ, p, 3*sizeof(*p));
> > if (!error) {
> > __put_user(a, p);
> > __put_user(b, p+1);
> > __put_user(c, p+2);
> > }
> >
> > where the __xxx versions are faster but "unsafe" unless you have
> > verified the area by hand first.
>
> Can this be extended to:
>
> error = access_ok(VERIFY_READ, p, 3*sizeof(*p));
> if (! error) {
> interruptible_sleep_on(&some_wait_queue);
> ...
> __put_user(a, p);
> __put_user(b, p+1);
> __put_user(c, p+2);
> }

In theory not, because early i386 with broken supervisor write
protection checking depend on on verify_area/access_ok to actually
check the page tables. The page tables could change while you sleep.

But, the concept is really broken, because e.g. when a user access
crosses two vm areas, and the user access faults (=sleeps) in the
first, and the goes on to write to the second, while that has been
already unmapped by another thread, it overwrites innoncent
memory.

On later Intel cpus (and AFAIK on all ports) access_ok/verify_area
only check if the address isn't in kernel memory to avoid security
holes and depends on the MMU to detect bad addresses in user space.

Best practice is probably to avoid the sleeps or use always non
"__" versions of the _*user functions, just to have some additional
protection against such bugs and to be conservative.

-Andi

-- 
This is like TV. I don't like TV.

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/