From: Andi Kleen <ak@muc.de>
To: "Arkadi E. Shishlov" <arkadi@it.lv>
Cc: Andi Kleen <ak@muc.de>, linux-mm@kvack.org
Subject: Re: IO mappings; verify_area() on SMP
Date: Tue, 9 Nov 1999 11:40:38 +0100 [thread overview]
Message-ID: <19991109114038.13044@colin.muc.de> (raw)
In-Reply-To: <19991109112732.B559@it.lv>; from Arkadi E. Shishlov on Tue, Nov 09, 1999 at 10:27:32AM +0100
On Tue, Nov 09, 1999 at 10:27:32AM +0100, Arkadi E. Shishlov wrote:
> 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.
There is no alternative. *_user can sleep, and another thread can unmap
while it is sleeping. So it has to be checking in *_user by the MMU.
>
>
> 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 don't understand. What __range_ok basically does is to check if the
address is part of the address space reserved for the user. It it wouldn't
do that the user could specify a kernel address and access internal
kernel structures, leading to a security leak. This is a bit complicated
because the kernel sometimes wants to do IO to/from internal buffers (e.g.
for NFS), so the idea of kernel and user memory can be switched (with
set_fs(KERNEL_DS) which sets current->addr_limit). The assembly magic
above is just a fancy jumpless way to implement this check. It has nothing
to do with memset.
> 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()?
See above.
-Andi
--
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/
prev parent reply other threads:[~1999-11-09 10:40 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
1999-11-08 11:43 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
1999-11-09 10:40 ` Andi Kleen [this message]
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=19991109114038.13044@colin.muc.de \
--to=ak@muc.de \
--cc=arkadi@it.lv \
--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