LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (http://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   memcpy and copy_to/from_user (http://www.linuxquestions.org/questions/linux-kernel-70/memcpy-and-copy_to-from_user-930170/)

rbhsrh 02-19-2012 06:54 AM

memcpy and copy_to/from_user
 
hi everyone,

I just want to know, what is the importance of copy_to/from_user w.r.to memcpy?

I went through the some definitions which explain to avoid illegal handling of memory from the user. But, I didn't understand, while read/write also refers to the user buffer while copying the data (memcpy).
When should exactly we have to use copy_to/from_user and when memcpy.


thanks in advance,

ravi

tronayne 02-19-2012 09:14 AM

Best I can tell you is to offer an example of how to use memcpy in a C program:
Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void    main    (void)
{
        static  char    buf1 [] = { "I am to be copied" };
        char            buf2 [25], *strptr;
        static  int    data1 [5] = { 1, 2, 3, 4, 5 };
        int            data2 [5], i, compare;

        /*      copy characters from buf1 to buf2      */
        (void) memcpy ((void *) buf2, (void *) buf1, sizeof (buf1));
        (void) fprintf (stdout, "%s\n", buf2);
        /*      copy data1 array to data2              */
        (void) memcpy ((void *) data2, (void *) data1, sizeof (data1));
        for (i = 0; i < 5; i++)
                (void) fprintf (stdout, "%d ", data2 [i]);
        (void) fprintf (stdout, "\n");
        /*      scan buf1 for charcter 't'              */
        strptr = memchr ((void *) buf1, 't', sizeof (buf1));
        (void) fprintf (stdout, "%s\n", strptr);
        /*      compare buf1 to buf2                    */
        compare = memcmp ((void *) buf1, (void *) buf2, sizeof (buf1));
        (void) fprintf (stdout, "%d\n", compare);
        /*      set buf2 array to all 'x' characters    */
        (void) memset ((void *) buf2, 'x', sizeof (buf2));
        for (i = 0; i < sizeof (buf2); ++i)
                (void) fprintf (stdout, "%c", buf2 [i]);
        (void) fprintf (stdout, "\n");
        exit (EXIT_SUCCESS);
}

The above demonstrates memcpy, memchr, memcmp and memset -- read the manual pages for each for descriptions.

The important thing to keep in mind is that you must allocate sufficient memory to use these functions.

In the above, the buffers are declared: buf1 will be the size of the string (I am to be copied) and buf2 is given a size (25 byte) and is a string pointer. You can, typically, use the token BUFSIZ for buffer size declaration (it's 8192 on my system, yours may vary); BUFSIZ is defined in stdio.h. On modern systems with gigabytes of RAM it's not going to hurt anything to set aside 8K for buffers.

The real reason for using the mem functions is that they're fast; copying stuff is usually done in some sort of a loop (for, while) and that's slower, more overhead. Now, "slower" is a relative term when you have a fast processor and wads of memory but you get the idea; every microsecond counts sometimes.

And, like any other copying into buffers (or arrays), if you try to copy more than you've allocated you'll get a crash (or maybe even a core dump but those don't happen too often anymore).

Hope this helps some.

Nominal Animal 02-19-2012 11:02 AM

Quote:

Originally Posted by rbhsrh (Post 4606461)
I just want to know, what is the importance of copy_to/from_user w.r.to memcpy?

copy_to_user() and copy_from_user() do a bit of magic to ensure that it only copies from/to userspace, and then only from valid address ranges. If the userspace provided an invalid pointer and/or length, the functions will return the number of bytes that could not be copied. In real life, you check if they return zero, and if not, you return -EFAULT to indicate the pointer/length was bogus.

memcpy() does nothing of that sort. If the user provides a cleverly crafted pointer, memcpy() will happily copy kernel data; it does absolutely no sanity checks. copy_to_user() and copy_from_user() do all the necessary checks and preparations.

In kernel sources, pointers received from userspace are usually annotated __user. This is just make sure you (the kernel programmer) remembers to use copy_to_user()/copy_from_user() to reference the data pointed at.

The simple rule is: Whenever the pointer is specified by the userspace process, either indirectly or directly, you use copy_to_user()/copy_from_user(). You only use memcpy() with pointers internal to the kernel that are never supplied to userspace.

There are certain exceptions and more complex cases, but those are best described in Linux Device Drivers, Third Edition.


All times are GMT -5. The time now is 10:13 PM.