Re: How does get_user()/put_user() work in kernel 2.2.x?

From: Jamie Lokier (lk@tantalophile.demon.co.uk)
Date: Mon Feb 28 2000 - 07:05:02 EST


simba wrote:
> Before kerenl 2.2.x, I knew get_user()/put_user() could access user
> space using fs segment register.
>
> But in case of kernel 2.2.x the code was changed and I can't understand
> how does get_user()/put_user() can access the user space!

User space is mapped from address 0x00000000 to 0xbfffffff, just like in
the 2.0 kernels.

In 2.2, those addresses are used from kernel space too, and the kernel
is mapped from 0xc0000000 onwards. There is no need to use a segment
register because the same addresses are used from user space and kernel
space.

In 2.2, user space access first calls access_ok() to check the address
is in the user space range, and then it just does a normal memory read
or write. get_user and put_user do this -- you can skip the address
range check with __get_user and __put_user.

Page faults can occur and so can scheduling due to paging I/O. If the
access fails, the page fault fixup code looks uses the address of the
instruction doing the access, searches ex_table for corresponding fixup
code, and jumps to that. The fixup code does the appropriate thing to
return -EFAULT from the get_user or put_user call. The fixup code goes
in the .fixup section so that it doesn't take any space or time in the
fast path: -EFAULT cases are rare.

set_fs and get_fs still exist, even on non-x86 ports. All they do now
is control the address range check. Access checks are done entirely by
the paging system.

There is an exception: most 386s allow ring 0 (kernel) code to write to
read-only pages. Linux requires a page fault in those cases just like a
user space write, so that copy on write and the other mechanisms work
just like user space. So on those 386s, boot_cpu_data.wp_works_ok is
not set, and page by page write verification is done by the
__verify_write library function.

I think these are the most common bugs in uses of get_user/put_user:

  - In driver ioctls especially, to ignore the return value of
    get_user/put_user, which says if the access faulted or not.
    Especially get_user -- it can result in ioctl assuming bogus
    arguments.

  - Calling __get_user/__put_user without an appropriate access_ok call
    to verify the address or, on a 386, to write-fault the pages.

  - Assuming that user space access cannot block.

have a nice day,
-- Jamie

-
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/



This archive was generated by hypermail 2b29 : Tue Feb 29 2000 - 21:00:19 EST