2005-12-02 22:40:26

by Vinay Venkataraghavan

[permalink] [raw]
Subject: copy_from_user/copy_to_user question


I have a question regarding copy_to_user and
copy_from_user, specifically the conditons and
situations when they can be used.

Firstly, I guess it is always safe to use these
funtions when making an ioctl call.

But my question is: Are there any specific
circumstances or conditions when these functions don't
have to be used, but at the same time ensure that no
page fault occurs and crashes the system.

The reason I ask is, there is some software that I am
dealing with that just don't use these functions.

Secondly, they seem to use memcpy as opposed to using
copy_to_user/copy_from_user which is also very
dangerous.

Any thoughts?

Vinay




__________________________________________
Yahoo! DSL ? Something to write home about.
Just $16.99/mo. or less.
dsl.yahoo.com


2005-12-03 01:10:04

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Fri, 2005-12-02 at 14:40 -0800, Vinay Venkataraghavan wrote:
> I have a question regarding copy_to_user and
> copy_from_user, specifically the conditons and
> situations when they can be used.
>
> Firstly, I guess it is always safe to use these
> funtions when making an ioctl call.

It's basically safe whenever you can schedule, and you are running on
behalf of a user task (as appose to a kernel thread).

>
> But my question is: Are there any specific
> circumstances or conditions when these functions don't
> have to be used, but at the same time ensure that no
> page fault occurs and crashes the system.

Sure, they don't need to be used if you don't need to get data to or
from user context.

>
> The reason I ask is, there is some software that I am
> dealing with that just don't use these functions.

What is this code and what is it doing?

>
> Secondly, they seem to use memcpy as opposed to using
> copy_to_user/copy_from_user which is also very
> dangerous.

If they are grabbing data from user context into kernel (or vise versa)
that could easily cause an oops. Not to mention it is a security risk.

-- Steve


2005-12-03 01:38:37

by Al Viro

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Fri, Dec 02, 2005 at 08:09:59PM -0500, Steven Rostedt wrote:
> > Secondly, they seem to use memcpy as opposed to using
> > copy_to_user/copy_from_user which is also very
> > dangerous.
>
> If they are grabbing data from user context into kernel (or vise versa)
> that could easily cause an oops. Not to mention it is a security risk.

Not to mention it simply won't work on a many platforms, no matter what...

2005-12-03 02:02:46

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Sat, 2005-12-03 at 01:38 +0000, Al Viro wrote:
> On Fri, Dec 02, 2005 at 08:09:59PM -0500, Steven Rostedt wrote:
> > > Secondly, they seem to use memcpy as opposed to using
> > > copy_to_user/copy_from_user which is also very
> > > dangerous.
> >
> > If they are grabbing data from user context into kernel (or vise versa)
> > that could easily cause an oops. Not to mention it is a security risk.
>
> Not to mention it simply won't work on a many platforms, no matter what...

Hmm, I've only worked with a few platforms (i386, x86_64, ppc, mips, and
a little arm but I don't remember that much). I believe that a memcpy
could work on all these platforms (error prone of course, but if the
memory is mapped its OK). When entering a system call, the kernel still
has access to the memory locations assigned to the user.

It's been a while since I had to deal with the semantics of
copy_to/from_user. So what platforms can not access a user space area
directly. Is there a special assembly command to use to copy from user?

I haven't dealt (yet) with the copy_user of x86_64. Is there a problem
when one tries to copy to/from a 32 bit address while in a 64 bit
address space?

Just curious, sorry for my ignorance here.

-- Steve


2005-12-03 02:11:55

by Vinay Venkataraghavan

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question



> > > > Secondly, they seem to use memcpy as opposed
> to using
> > > > copy_to_user/copy_from_user which is also very
> > > > dangerous.
> > >
> > > If they are grabbing data from user context into
> kernel (or vise versa)
> > > that could easily cause an oops. Not to mention
> it is a security risk.
> >
> > Not to mention it simply won't work on a many
> platforms, no matter what...
>
> Hmm, I've only worked with a few platforms (i386,
> x86_64, ppc, mips, and
> a little arm but I don't remember that much). I
> believe that a memcpy
> could work on all these platforms (error prone of
> course, but if the
> memory is mapped its OK).

When entering a system
> call, the kernel still
> has access to the memory locations assigned to the
> user.
>

But this is not always the case right. The point that
you mention above is specifically why I posted this
question. It could well be the case that the user
space page could be swapped out when the user space
process is blocked. So when the ioctl is serviced in
kernel space, there is no guarantee that the page is
still mapped. This could cause a page fault.
I think this is why we need to do a
copy_to_user/copy_from_user.

The piece of code that I am talking about is part of a
driver code. Unfortunately I am not at liberty to
divulge the name of the company. So in the driver then
are not using copy_to_user and copy_from_user. That is
what puzzles me. Moreover, where they are using these
functions they use memcpy which is a big security
risk.

Thanks once again.
Vinay




__________________________________________
Yahoo! DSL ? Something to write home about.
Just $16.99/mo. or less.
dsl.yahoo.com

2005-12-03 02:22:13

by Vinay Venkataraghavan

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question


The other point that I want to mention is that I don't
think that there is any guarantee that the user space
structure will be locked in memory. There is every
likely hood of the page being swapped out.

Correct me if I am wrong.
Thanks,
Vinay



--- Vinay Venkataraghavan <[email protected]>
wrote:

>
>
> > > > > Secondly, they seem to use memcpy as opposed
> > to using
> > > > > copy_to_user/copy_from_user which is also
> very
> > > > > dangerous.
> > > >
> > > > If they are grabbing data from user context
> into
> > kernel (or vise versa)
> > > > that could easily cause an oops. Not to
> mention
> > it is a security risk.
> > >
> > > Not to mention it simply won't work on a many
> > platforms, no matter what...
> >
> > Hmm, I've only worked with a few platforms (i386,
> > x86_64, ppc, mips, and
> > a little arm but I don't remember that much). I
> > believe that a memcpy
> > could work on all these platforms (error prone of
> > course, but if the
> > memory is mapped its OK).
>
> When entering a system
> > call, the kernel still
> > has access to the memory locations assigned to the
> > user.
> >
>
> But this is not always the case right. The point
> that
> you mention above is specifically why I posted this
> question. It could well be the case that the user
> space page could be swapped out when the user space
> process is blocked. So when the ioctl is serviced in
> kernel space, there is no guarantee that the page is
> still mapped. This could cause a page fault.
> I think this is why we need to do a
> copy_to_user/copy_from_user.
>
> The piece of code that I am talking about is part of
> a
> driver code. Unfortunately I am not at liberty to
> divulge the name of the company. So in the driver
> then
> are not using copy_to_user and copy_from_user. That
> is
> what puzzles me. Moreover, where they are using
> these
> functions they use memcpy which is a big security
> risk.
>
> Thanks once again.
> Vinay
>
>
>
>
> __________________________________________
> Yahoo! DSL ? Something to write home about.
> Just $16.99/mo. or less.
> dsl.yahoo.com
>
>




__________________________________________
Yahoo! DSL ? Something to write home about.
Just $16.99/mo. or less.
dsl.yahoo.com

2005-12-03 02:27:49

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Fri, 2005-12-02 at 18:11 -0800, Vinay Venkataraghavan wrote:

> >
> > Hmm, I've only worked with a few platforms (i386,
> > x86_64, ppc, mips, and
> > a little arm but I don't remember that much). I
> > believe that a memcpy
> > could work on all these platforms (error prone of
> > course, but if the
> > memory is mapped its OK).
>
> When entering a system
> > call, the kernel still
> > has access to the memory locations assigned to the
> > user.
> >
>
> But this is not always the case right.

Right.

> The point that
> you mention above is specifically why I posted this
> question. It could well be the case that the user
> space page could be swapped out when the user space
> process is blocked. So when the ioctl is serviced in
> kernel space, there is no guarantee that the page is
> still mapped. This could cause a page fault.
> I think this is why we need to do a
> copy_to_user/copy_from_user.

Yes that is a reason to use copy_to/from_user, and it also checks to see
if the memory being used is allowed by the user.

>
> The piece of code that I am talking about is part of a
> driver code. Unfortunately I am not at liberty to
> divulge the name of the company. So in the driver then
> are not using copy_to_user and copy_from_user. That is
> what puzzles me. Moreover, where they are using these
> functions they use memcpy which is a big security
> risk.

Sounds like the authors of this driver don't know Linux kernel
programming very well. If you want to test it, I would write a userland
program that uses this ioctl and pass in a bad pointer (NULL or better
yet, the location of schedule found in System.map). If the machine
crashes, you got your answer ;) Passing in an address of code might not
crash right away. You may need to wait till the data cache writes it
out to memory, and the instruction cache reads it. These two caches are
not always in sync on all platforms.

-- Steve


2005-12-03 02:47:18

by Robert Hancock

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

Vinay Venkataraghavan wrote:
> But this is not always the case right. The point that
> you mention above is specifically why I posted this
> question. It could well be the case that the user
> space page could be swapped out when the user space
> process is blocked. So when the ioctl is serviced in
> kernel space, there is no guarantee that the page is
> still mapped. This could cause a page fault.
> I think this is why we need to do a
> copy_to_user/copy_from_user.

I don't think this is actually the case. I'm not entirely sure, but I
believe that if memcpy from user space works at all on a platform, then
if the page is swapped out it will still get swapped in when needed. In
any case, this is not the main reason for using these functions. The
main reason is that memory addresses passed from userspace might not be
valid at all, and reading these addresses directly would cause a kernel
oops in that case. These functions set up an exception handler so that
invalid address reads/writes return failure instead of crashing the system.

--
Robert Hancock Saskatoon, SK, Canada
To email, remove "nospam" from [email protected]
Home Page: http://www.roberthancock.com/

2005-12-03 03:23:50

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

Don't strip CC's

On Fri, 2005-12-02 at 20:47 -0600, Robert Hancock wrote:
> Vinay Venkataraghavan wrote:
> > But this is not always the case right. The point that
> > you mention above is specifically why I posted this
> > question. It could well be the case that the user
> > space page could be swapped out when the user space
> > process is blocked. So when the ioctl is serviced in
> > kernel space, there is no guarantee that the page is
> > still mapped. This could cause a page fault.
> > I think this is why we need to do a
> > copy_to_user/copy_from_user.
>
> I don't think this is actually the case. I'm not entirely sure, but I
> believe that if memcpy from user space works at all on a platform, then
> if the page is swapped out it will still get swapped in when needed. In
> any case, this is not the main reason for using these functions. The
> main reason is that memory addresses passed from userspace might not be
> valid at all, and reading these addresses directly would cause a kernel
> oops in that case. These functions set up an exception handler so that
> invalid address reads/writes return failure instead of crashing the system.

Nope, the kernel is always locked into memory. If you take a page fault
from the kernel world, you will crash and burn. The kernel is never
"swapped out". So if you are in kernel mode, going into do_page_fault
in arch/i386/mm/fault.c there is no path to swap a page in. Even the
vmalloc_fault only handles a page not in the page global descriptor of
the current task. But if this page is not mapped somewhere in memory
(not swapped out), you will get a kernel oops.

Kernel memory may never be swapped out. What happens if an interrupt
tries to use such memory. How does it handle sleeping?

Just change copy_to_user into memcopy, and see how long your system
stays up and running. Do it on a machine that you don't need to worry
about rogue applications. It won't last very long.

-- Steve


2005-12-03 03:33:55

by Robert Hancock

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

Steven Rostedt wrote:
> Nope, the kernel is always locked into memory. If you take a page fault
> from the kernel world, you will crash and burn. The kernel is never
> "swapped out". So if you are in kernel mode, going into do_page_fault
> in arch/i386/mm/fault.c there is no path to swap a page in. Even the
> vmalloc_fault only handles a page not in the page global descriptor of
> the current task. But if this page is not mapped somewhere in memory
> (not swapped out), you will get a kernel oops.
>
> Kernel memory may never be swapped out. What happens if an interrupt
> tries to use such memory. How does it handle sleeping?
>
> Just change copy_to_user into memcopy, and see how long your system
> stays up and running. Do it on a machine that you don't need to worry
> about rogue applications. It won't last very long.

Yes, kernel memory is never swapped out. But my point is merely that as
far as I know there is no special handling in the copy_to/from_user
functions to handle the case where the userspace memory is swapped out,
and therefore this would not be an issue for accessing the memory
directly. Obviously this is not something that one should actually do,
since access faults are not trapped and on some architectures or
configurations it won't work at all.

--
Robert Hancock Saskatoon, SK, Canada
To email, remove "nospam" from [email protected]
Home Page: http://www.roberthancock.com/

2005-12-03 04:53:50

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Fri, 2005-12-02 at 21:33 -0600, Robert Hancock wrote:
> Steven Rostedt wrote:
> > Nope, the kernel is always locked into memory. If you take a page fault
> > from the kernel world, you will crash and burn. The kernel is never
> > "swapped out". So if you are in kernel mode, going into do_page_fault
> > in arch/i386/mm/fault.c there is no path to swap a page in. Even the
> > vmalloc_fault only handles a page not in the page global descriptor of
> > the current task. But if this page is not mapped somewhere in memory
> > (not swapped out), you will get a kernel oops.
> >
> > Kernel memory may never be swapped out. What happens if an interrupt
> > tries to use such memory. How does it handle sleeping?
> >
> > Just change copy_to_user into memcopy, and see how long your system
> > stays up and running. Do it on a machine that you don't need to worry
> > about rogue applications. It won't last very long.
>
> Yes, kernel memory is never swapped out. But my point is merely that as
> far as I know there is no special handling in the copy_to/from_user
> functions to handle the case where the userspace memory is swapped out,
> and therefore this would not be an issue for accessing the memory
> directly. Obviously this is not something that one should actually do,
> since access faults are not trapped and on some architectures or
> configurations it won't work at all.

Quite the contrary, it does handle the case for swapped out memory.

Lets take a look at it, shall we?

copy_to/from_user boils down to __copy_user in arch/i386/lib/usercopy.c:

#define __copy_user(to,from,size) \
do { \
int __d0, __d1, __d2; \
__asm__ __volatile__( \
" cmp $7,%0\n" \
" jbe 1f\n" \
" movl %1,%0\n" \
" negl %0\n" \
" andl $7,%0\n" \
" subl %0,%3\n" \
"4: rep; movsb\n" \
" movl %3,%0\n" \
" shrl $2,%0\n" \
" andl $3,%3\n" \
" .align 2,0x90\n" \
"0: rep; movsl\n" \
" movl %3,%0\n" \
"1: rep; movsb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"5: addl %3,%0\n" \
" jmp 2b\n" \
"3: lea 0(%3,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 4b,5b\n" \
" .long 0b,3b\n" \
" .long 1b,2b\n" \
".previous" \
: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
: "3"(size), "0"(size), "1"(to), "2"(from) \
: "memory"); \
} while (0)


Take a look at the __ex_table. It adds the following addresses:

label 4, label 5,
label 0, label 3,
label 1, label 2.

Now lets see if we take a page fault at any of the labels 4, 0, or 1.
(where the copies actually are).

In do_page_fault in arch/i386/mm/fault.c

if (!down_read_trylock(&mm->mmap_sem)) {
if ((error_code & 4) == 0 &&
!search_exception_tables(regs->eip))
goto bad_area_nosemaphore;
down_read(&mm->mmap_sem);
}

The error_code & 4 == 0 is true when we are in the kernel (which we
are). And here's the difference between memcpy and copy_user. The
search_exception_tables! If this were to fail (as it would in memcpy)
we would just die here (jumping to bad_area_nosemaphore). But lets now
look at search_exception_tables.

search_exception_tables is defined in kernel/extable.c, and the entries
to the table are in include/asm-i386/uaccess.h:

struct exception_table_entry
{
unsigned long insn, fixup;
};

Remember those labels? Well the linker puts them into this table sorted,
by insn, so here we now have:

insn = label 4, fixup = label 5,
insn = label 0, fixup = label 3,
insn = label 1, fixup = label 2.
(but sorted with all other exceptions)

The search_exception_tables does a binary search of all these sorted
exceptions, looking for the address where the exception took place.
Which would be at either label 4, 0 or 1, any of which would be found in
this table.

Then this would continue happily along and swap back in the pages (just
as if it was in user land) and return to the point it left off and
continue.

What's the fixup for in that table?? Well lets look at do_page_fault in
the case that this actually fails and goes to bad_area. We don't want
to oops the kernel for some misbehavior of an application.

In usermode we would just SIGSEGV, but we are in kernel mode. So we
would drop down to fix_exception called by do_page_fault.

fix_exception in arch/i386/mm/extable.c has the following code.

fixup = search_exception_tables(regs->eip);
if (fixup) {
regs->eip = fixup->fixup;
return 1;
}

So it once again searches the exception table for the bad address, which
we find. And say this happened at label 4, we set our new eip to
label 5, so when we return from this exception, we jump to label 5 which
is really in the .fixup section (not actually after the code of label 4)

So lets take a look at this code again:

" cmp $7,%0\n" \
" jbe 1f\n" \
" movl %1,%0\n" \
" negl %0\n" \
" andl $7,%0\n" \
" subl %0,%3\n" \
"4: rep; movsb\n" \

We take an exception here (no page) and in fact, it is a bad
memory location! So we go to do_page_fault, that eventually calls
fixup_exception which puts the eip to label 5 (so we now jump there)


" movl %3,%0\n" \
" shrl $2,%0\n" \
" andl $3,%3\n" \
" .align 2,0x90\n" \
"0: rep; movsl\n" \
" movl %3,%0\n" \
"1: rep; movsb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \

We jump to label 5 and add what we didn't write and then jump to
label 2 above. This is really in the fixup section, so these
jumps are really jumping around in the code and they are not
as close as this looks.

label 2 above just exits, so the copy_user here now returns the
number of bytes that were not copied!

"5: addl %3,%0\n" \
" jmp 2b\n" \
"3: lea 0(%3,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 4b,5b\n" \
" .long 0b,3b\n" \
" .long 1b,2b\n" \

Pretty neat eh?

-- Steve


2005-12-03 08:33:27

by Arjan van de Ven

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question


> The piece of code that I am talking about is part of a
> driver code. Unfortunately I am not at liberty to
> divulge the name of the company. So in the driver then
> are not using copy_to_user and copy_from_user. That is
> what puzzles me. Moreover, where they are using these
> functions they use memcpy which is a big security
> risk.

I guess this is why you're not allowed to mention it... they'd be all
over bugtraq..

thank god for open source so that 1) customers can see the quality and
2) everyone can fix it....

2005-12-03 09:43:37

by Heiko Carstens

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

> > > > Secondly, they seem to use memcpy as opposed to using
> > > > copy_to_user/copy_from_user which is also very
> > > > dangerous.
> > >
> > > If they are grabbing data from user context into kernel (or vise versa)
> > > that could easily cause an oops. Not to mention it is a security risk.
> >
> > Not to mention it simply won't work on a many platforms, no matter what...
>
> Hmm, I've only worked with a few platforms (i386, x86_64, ppc, mips, and
> a little arm but I don't remember that much). I believe that a memcpy
> could work on all these platforms (error prone of course, but if the
> memory is mapped its OK). When entering a system call, the kernel still
> has access to the memory locations assigned to the user.

Won't work at all on platforms that have distinct address spaces for user
and kernel space. E.g. on s390/s390x it wouldn't work. And yes, there are
special instructions to copy data between address spaces.

Heiko

2005-12-03 12:14:54

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Sat, 2005-12-03 at 10:43 +0100, Heiko Carstens wrote:
> > > > > Secondly, they seem to use memcpy as opposed to using
> > > > > copy_to_user/copy_from_user which is also very
> > > > > dangerous.
> > > >
> > > > If they are grabbing data from user context into kernel (or vise versa)
> > > > that could easily cause an oops. Not to mention it is a security risk.
> > >
> > > Not to mention it simply won't work on a many platforms, no matter what...
> >
> > Hmm, I've only worked with a few platforms (i386, x86_64, ppc, mips, and
> > a little arm but I don't remember that much). I believe that a memcpy
> > could work on all these platforms (error prone of course, but if the
> > memory is mapped its OK). When entering a system call, the kernel still
> > has access to the memory locations assigned to the user.
>
> Won't work at all on platforms that have distinct address spaces for user
> and kernel space. E.g. on s390/s390x it wouldn't work. And yes, there are
> special instructions to copy data between address spaces.

Thanks for the update. That's why I love working in an open
environment. You learn something new every day ;)

-- Steve


2005-12-03 18:06:24

by Andi Kleen

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

Steven Rostedt <[email protected]> writes:
>
> Nope, the kernel is always locked into memory. If you take a page fault
> from the kernel world, you will crash and burn. The kernel is never
> "swapped out". So if you are in kernel mode, going into do_page_fault
> in arch/i386/mm/fault.c there is no path to swap a page in.

Actually there is - when the page fault was caused by *_user.

-Andi

2005-12-03 18:03:49

by Andi Kleen

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

Steven Rostedt <[email protected]> writes:
>
> I haven't dealt (yet) with the copy_user of x86_64. Is there a problem
> when one tries to copy to/from a 32 bit address while in a 64 bit
> address space?

No problem, except on UML/x86-64 which has fully separate address spaces.

Architectures where it doesn't work include s390,m68k,pa-risc,sparc64,
i386 with 4/4 patches among others.

-Andi

2005-12-03 18:26:29

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Sat, 2005-12-03 at 15:35 -0700, Andi Kleen wrote:
> Steven Rostedt <[email protected]> writes:
> >
> > Nope, the kernel is always locked into memory. If you take a page fault
> > from the kernel world, you will crash and burn. The kernel is never
> > "swapped out". So if you are in kernel mode, going into do_page_fault
> > in arch/i386/mm/fault.c there is no path to swap a page in.
>
> Actually there is - when the page fault was caused by *_user.

Sorry I wasn't clearer. I know the copy_user case (and explained it in
detail earlier in this thread). I was talking about what happens in the
memcpy case. So that should have said "outside of copy_user and
friends, there is no path to swap a page in".

-- Steve


2005-12-05 13:31:22

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question


On Fri, 2 Dec 2005, Steven Rostedt wrote:

> On Fri, 2005-12-02 at 14:40 -0800, Vinay Venkataraghavan wrote:
>> I have a question regarding copy_to_user and
>> copy_from_user, specifically the conditons and
>> situations when they can be used.
>>
>> Firstly, I guess it is always safe to use these
>> funtions when making an ioctl call.
>
> It's basically safe whenever you can schedule, and you are running on
> behalf of a user task (as appose to a kernel thread).
>
>>
>> But my question is: Are there any specific
>> circumstances or conditions when these functions don't
>> have to be used, but at the same time ensure that no
>> page fault occurs and crashes the system.
>
> Sure, they don't need to be used if you don't need to get data to or
> from user context.
>
>>
>> The reason I ask is, there is some software that I am
>> dealing with that just don't use these functions.
>
> What is this code and what is it doing?
>
>>
>> Secondly, they seem to use memcpy as opposed to using
>> copy_to_user/copy_from_user which is also very
>> dangerous.
>
> If they are grabbing data from user context into kernel (or vise versa)
> that could easily cause an oops. Not to mention it is a security risk.
>
> -- Steve
>

The kernel has the privileges to trash anything from kernel-space.
This means that an incorrect pointer or length-variable, passed
from user-mode code could trash everything including the kernel
if the kernel code just used memcpy().

So, copy_to/from_user was developed so that the user's privs and
page ownership would be used during the copy operation. This means
that if the user provides the wrong location or byte-count, the
improper operation is trapped and the kernel code can return
an error code, usually -EFAULT.

Drivers that use memcpy() when accessing user-provided space
(such as in read(), write(), ioctl(), etc.) are simply broken
and should not be used. They can cause other modules and/or
kernel functions to fail in mysterious ways.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.44 BogoMips).
Warning : 98.36% of all statistics are fiction.
.

****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2005-12-06 17:53:04

by Vinay Venkataraghavan

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question


Thanks to Steve and everybody who sent such detailed
and timely responses to my question.

The motivation for the copy to user question is due to
the handling of ioctl calls in the driver for a chip
that is widely used. I just could not beleive that
they would/could commit such a mistake.

It looks like the old driver code still seems to work
even without performing copy_to_user and
copy_from_user.

But this brings about another scenario. What if the
case statement in the ioctl call only needs to have
access to the members of the structure passed in
through the arg pointer but does not need to modify
these values and return values.

Is this still a problem if copy_to_user and
copy_from_user is not used?

Thanks,
Vinay


--- Steven Rostedt <[email protected]> wrote:

> On Sat, 2005-12-03 at 15:35 -0700, Andi Kleen wrote:
> > Steven Rostedt <[email protected]> writes:
> > >
> > > Nope, the kernel is always locked into memory.
> If you take a page fault
> > > from the kernel world, you will crash and burn.
> The kernel is never
> > > "swapped out". So if you are in kernel mode,
> going into do_page_fault
> > > in arch/i386/mm/fault.c there is no path to swap
> a page in.
> >
> > Actually there is - when the page fault was caused
> by *_user.
>
> Sorry I wasn't clearer. I know the copy_user case
> (and explained it in
> detail earlier in this thread). I was talking about
> what happens in the
> memcpy case. So that should have said "outside of
> copy_user and
> friends, there is no path to swap a page in".
>
> -- Steve
>
>
>




__________________________________________
Yahoo! DSL ? Something to write home about.
Just $16.99/mo. or less.
dsl.yahoo.com

2005-12-06 17:57:07

by Arjan van de Ven

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Tue, 2005-12-06 at 09:53 -0800, Vinay Venkataraghavan wrote:
>
>
> The motivation for the copy to user question is due to
> the handling of ioctl calls in the driver for a chip
> that is widely used. I just could not beleive that
> they would/could commit such a mistake.

maybe it's time to give us the URL to the code...
your questions are getting detailed to the point that people who help
you should be able to see what the code is really doing..

2005-12-06 18:23:23

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Tue, 2005-12-06 at 09:53 -0800, Vinay Venkataraghavan wrote:
> Thanks to Steve and everybody who sent such detailed
> and timely responses to my question.
>
> The motivation for the copy to user question is due to
> the handling of ioctl calls in the driver for a chip
> that is widely used. I just could not beleive that
> they would/could commit such a mistake.
>
> It looks like the old driver code still seems to work
> even without performing copy_to_user and
> copy_from_user.

How old is this driver? The old days, we had memcpy_fromfs, which I
believe was replaced with copy_from_user in 2.2 (and thus would no
longer work).

>
> But this brings about another scenario. What if the
> case statement in the ioctl call only needs to have
> access to the members of the structure passed in
> through the arg pointer but does not need to modify
> these values and return values.
>
> Is this still a problem if copy_to_user and
> copy_from_user is not used?
>

If what it is looking at is just a standard type (char, short, int,
long) within the struct, it can use get_user, and not the bigger cousin
copy_from_user. The arg value passed in for the ioctl is OK to read
itself. That is if you are just reading the arg as unsigned long. But
if this arg is dereferenced as a pointer, then you must use one of the
*_user functions.

If it isn't using any of the *_user functions then most likely this
works with just plain luck. The chance of having the page swap out from
the time the user updates the struct to the time the kernel reads it is
very slim. So memcpy would unfortunately work. (I say unfortunately
because if it didn't work, the author of this crap would not have done
so). It also seems to trust the user application to work properly.

So instead of asking these questions, I would suggest writing a user
application that passes in a bad pointer for one of these arguments and
seeing if the machine crashes. If/When it does, then go blame the
vendor of this crap.

-- Steve


2005-12-06 18:23:35

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question


On Tue, 6 Dec 2005, Vinay Venkataraghavan wrote:

>
> Thanks to Steve and everybody who sent such detailed
> and timely responses to my question.
>
> The motivation for the copy to user question is due to
> the handling of ioctl calls in the driver for a chip
> that is widely used. I just could not beleive that
> they would/could commit such a mistake.
>
> It looks like the old driver code still seems to work
> even without performing copy_to_user and
> copy_from_user.
>
> But this brings about another scenario. What if the
> case statement in the ioctl call only needs to have
> access to the members of the structure passed in
> through the arg pointer but does not need to modify
> these values and return values.
>
> Is this still a problem if copy_to_user and
> copy_from_user is not used?
>
> Thanks,
> Vinay

If you __access__(note) user-mode data from the kernel, you __must__
use the appropriate /copy/to/from/get/put/user functions and/or
macros. And, you __must__ not be in a spin-lock, or otherwise have
the interrupts disabled, while doing it. There are no exceptions.

(note)__assess__ means even "peek at".

FYI, there should never even be such a question.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.55 BogoMips).
Warning : 98.36% of all statistics are fiction.
.

****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2005-12-06 18:42:28

by Steven Rostedt

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

On Tue, 2005-12-06 at 13:23 -0500, linux-os (Dick Johnson) wrote:

>
> (note)__assess__ means even "peek at".
>
> FYI, there should never even be such a question.

Dick, be nice. I get the impression that Vinay is just looking at some
code that he can't disclose because of some policy of the company he
works for. He's curiously looking at the code of some non-mainstream
driver (either GPL or some NDA version) and is questioning what he sees.
Not everyone that does this is a kernel hacker. This is the way I
started, and these questions, which may seem so obvious to a veteran
kernel hacker, is not so to a novice.

-- Steve


2005-12-06 19:58:12

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question


On Tue, 6 Dec 2005, Steven Rostedt wrote:

> On Tue, 2005-12-06 at 13:23 -0500, linux-os (Dick Johnson) wrote:
>
>>
>> (note)__assess__ means even "peek at".
>>
>> FYI, there should never even be such a question.
>
> Dick, be nice. I get the impression that Vinay is just looking at some
> code that he can't disclose because of some policy of the company he
> works for. He's curiously looking at the code of some non-mainstream
> driver (either GPL or some NDA version) and is questioning what he sees.
> Not everyone that does this is a kernel hacker. This is the way I
> started, and these questions, which may seem so obvious to a veteran
> kernel hacker, is not so to a novice.
>
> -- Steve

Yes. You are correct. But he already asked the same questions yesterday
and was answered by many, including me, in many nice ways. So, sorry
for not being nice.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.55 BogoMips).
Warning : 98.36% of all statistics are fiction.
.

****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2005-12-06 20:06:06

by Vinay Venkataraghavan

[permalink] [raw]
Subject: Re: copy_from_user/copy_to_user question

Well, sorry for all the questions. I really appreciate
everybody's help and especially Steve for standing up
for me!! All the reasons you cited are true and that
is why I am afraid I cannot post the actual code etc.

There was never a question in my mind that we have to
use the *_user functions. I was just trying to
understand all the corner cases and the semantics of
how things worked when it has not been used.

Thanks once again.
Signing off this thread.
Vinay


--- "linux-os (Dick Johnson)" <[email protected]>
wrote:

>
> On Tue, 6 Dec 2005, Vinay Venkataraghavan wrote:
>
> >
> > Thanks to Steve and everybody who sent such
> detailed
> > and timely responses to my question.
> >
> > The motivation for the copy to user question is
> due to
> > the handling of ioctl calls in the driver for a
> chip
> > that is widely used. I just could not beleive that
> > they would/could commit such a mistake.
> >
> > It looks like the old driver code still seems to
> work
> > even without performing copy_to_user and
> > copy_from_user.
> >
> > But this brings about another scenario. What if
> the
> > case statement in the ioctl call only needs to
> have
> > access to the members of the structure passed in
> > through the arg pointer but does not need to
> modify
> > these values and return values.
> >
> > Is this still a problem if copy_to_user and
> > copy_from_user is not used?
> >
> > Thanks,
> > Vinay
>
> If you __access__(note) user-mode data from the
> kernel, you __must__
> use the appropriate /copy/to/from/get/put/user
> functions and/or
> macros. And, you __must__ not be in a spin-lock, or
> otherwise have
> the interrupts disabled, while doing it. There are
> no exceptions.
>
> (note)__assess__ means even "peek at".
>
> FYI, there should never even be such a question.
>
> Cheers,
> Dick Johnson
> Penguin : Linux version 2.6.13.4 on an i686 machine
> (5589.55 BogoMips).
> Warning : 98.36% of all statistics are fiction.
> .
>
>
****************************************************************
> The information transmitted in this message is
> confidential and may be privileged. Any review,
> retransmission, dissemination, or other use of this
> information by persons or entities other than the
> intended recipient is prohibited. If you are not
> the intended recipient, please notify Analogic
> Corporation immediately - by replying to this
> message or by sending an email to
> [email protected] - and destroy all copies
> of this information, including any attachments,
> without reading or disclosing them.
>
> Thank you.
>




__________________________________________
Yahoo! DSL ? Something to write home about.
Just $16.99/mo. or less.
dsl.yahoo.com