From: "Arkadi E. Shishlov" <arkadi@it.lv>
To: Andi Kleen <ak@muc.de>
Cc: linux-mm@kvack.org
Subject: Re: IO mappings; verify_area() on SMP
Date: Tue, 9 Nov 1999 11:27:32 +0200 [thread overview]
Message-ID: <19991109112732.B559@it.lv> (raw)
In-Reply-To: <19991108215035.A3154@fred.muc.de>; from Andi Kleen on Mon, Nov 08, 1999 at 09:50:35PM +0100
On Mon, Nov 08, 1999 at 09:50:35PM +0100, Andi Kleen wrote:
> On Mon, Nov 08, 1999 at 12:43:25PM +0100, Arkadi E. Shishlov wrote:
> >
> > Second question is about verify_area() safety. Many drivers contain
> > following sequence:
> >
> > if ((ret = verify_area(VERIFY_WRITE, buffer, count)))
> > return r;
> > ...
> > copy_to_user(buffer, driver_data_buf, count);
> >
> > Even protected by cli()/sti() pairs, why multithreaded program on
> > SMP machine can't unmap this verified buffer between calls to
> > verify_area() and copy_to_user()? Of course it can't be true, but
> > maybe somebody can write two-three words about reason that prevent
> > this situation.
>
> The verify_area is unnecessary in 2.2. The correct way to do it is:
>
> if (copy_to_user(buffer, driver_data_buf, count))
> return -EFAULT;
>
> The above sequence is because a lot of drivers were incorrectly converted
> from the 2.0 verify_area/memcpy_to_fs method to the 2.2 method. copy_from_user
> avoids the race you're describing (see Documentation/exception.txt).
Yes. I already read it. But... There is cases where verify_area() is
essential. To do copy_to_user() driver need actual data to put to user.
To get this data, driver walk through it internal structures and copy
data to buffer, then call copy_to_user(). In case of verify_area()
it was easy to do internal structures clean-up (packet is read - forget
about it) while filling this buffer. In case of copy_to_user() there is
two walk-through - first fill buffer, second - if copy_to_user() succeeds,
alter driver structures.
I can even imagine situation, when driver will be over-complicated, only
because it get data from hardware and copy_to_user() fails - driver need
to maintain additional buffer to hold this data. But it is rare case.
I understand this decision and agree. Will rewrite my driver slightly.
I look at verify_area() function. On i386 architecture it reduces to:
#define __range_ok(addr,size) ({ \
unsigned long flag,sum; \
asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
:"=&r" (flag), "=r" (sum) \
:"1" (addr),"g" (size),"g" (current->addr_limit.seg)); \
flag; })
I don't understand this magic code, but it looks somewhat different from
copy_to_user() with all it .fixup's. Why not to create function named
memset_to_user() - it will do the work of verify_area() and will be quite
cheap.
I found clear_user() function in arch/i386/lib/usercopy.c:
unsigned long
clear_user(void *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
__do_clear_user(to, n);
return n;
}
Why it is not macro and why it call access_ok()?
> verify_area() is a backwards compatibility wrapper around access_ok()
> which only does a security check for kernel mode addresses, it is done
> by copy_*_user too. The real mapping check is done by the MMU by
> handling the exception.
>
> Some early 386 don't check properly for page write protection when the CPU
> is in supervisor mode. In this case verify_area does a full walk of the
> page tables to avoid security problems. Unfortunately there is still a race
> with programs that use clone() (does not even need SMP), because when the
> user access sleeps in a page fault another thread can unmap the mapping
> inbetween and cause a kernel crash. Fortunately this only applies to some
> very early 386 steppings, later CPUs don't have this problem (and AFAIK
> no non x86 port except possibly uclinux)
>
> Hope this helps,
Yes. Thank you.
arkadi.
--
Just arms curvature radius.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/
next prev parent reply other threads:[~1999-11-09 9:27 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
1999-11-08 11:43 IO mappings; verify_area() on SMP Arkadi E. Shishlov
1999-11-08 19:25 ` Kanoj Sarcar
1999-11-09 9:26 ` Arkadi E. Shishlov
1999-11-08 20:50 ` Andi Kleen
1999-11-09 9:27 ` Arkadi E. Shishlov [this message]
1999-11-09 10:40 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=19991109112732.B559@it.lv \
--to=arkadi@it.lv \
--cc=ak@muc.de \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox