copy_to_user() and copy_from_user() Explained-Free Linux Device Driver Course Online

← Previous Lecture  |  Next Lecture →

copy_to_user() and copy_from_user() Explained
Free Linux Device Drivers Course — Kernel Memory Safety for Beginners
Level: Beginner–Intermediate
Read Time: 14 min
Free Linux Kernel Programming

If you are writing your first character device driver, sooner or later you will need to move data between kernel space and user space. This is exactly where copy_to_user() and copy_from_user() come in. These two kernel routines form the backbone of safe data exchange in every Linux device driver, and understanding them properly is a core skill in any free Linux device drivers course or free Linux kernel development course. In this lesson we break the concept down from first principles, with original diagrams and original code, so that even a complete beginner to Linux kernel module programming can follow along.

Topics Covered In This Lecture
copy_to_user() copy_from_user() access_ok() KASAN EFAULT handling User space vs Kernel space Character device drivers
What You Will Learn

By the end of this lecture, you will be able to:

  • Explain why the kernel cannot simply use memcpy() on a user space pointer
  • Use copy_to_user() and copy_from_user() correctly inside a driver’s read and write methods
  • Understand what access_ok() checks and why it exists
  • Understand how KASAN helps catch out-of-bounds and invalid memory access during development
  • Recognise the common mistakes that beginners make when handling buffers in a driver
  • Apply best practices so your driver never crashes the kernel because of bad user input
Prerequisites

This lecture assumes you already know:

  • Basic C programming, including pointers and structures
  • How to build and load a kernel module (insmod/rmmod)
  • The basic skeleton of a misc character device driver (open/read/write/release)

If any of this is new to you, please complete the earlier lectures in this free Linux kernel development course first.

Why the Kernel–User Boundary Needs Protection

A running Linux system has two very different address spaces: the address space of a user application, and the address space the kernel itself operates in. When your device driver’s read() or write() method runs, it is executing inside the kernel, but the buffer the application passed in belongs to that application’s user space memory. A raw pointer dereference across this boundary is dangerous for two reasons:

  • The user space address might be completely invalid, unmapped, or belong to another process by the time the driver touches it.
  • A malicious or buggy application could pass a pointer that points into kernel memory it has no business touching, effectively tricking the driver into reading or corrupting kernel data.

This is precisely why the kernel never lets a driver use a plain memcpy() or pointer assignment to move data across this boundary. Instead, every driver must go through a small set of dedicated, checked routines.

User Space vs Kernel Space Memory Layout
User Space
Application buffer (ubuf)
Not directly trusted by the kernel
⇄ Kernel Space
Driver buffer (kbuf)
Trusted, protected memory
Every crossing must go through copy_to_user() / copy_from_user(), never a direct pointer copy

Anatomy of copy_to_user() and copy_from_user()

Both routines share the same three-argument shape. copy_to_user() sends data from the driver out to the application; copy_from_user() pulls data from the application into the driver. Both return the number of bytes that could not be copied — meaning a return value of zero is success.

/* Sending data from the driver to the application (read side) */
ssize_t my_read(struct file *filp, char __user *ubuf,
                 size_t count, loff_t *off)
{
    size_t n = min(count, (size_t)sizeof(kbuf));

    if (copy_to_user(ubuf, kbuf, n))
        return -EFAULT;   /* one or more bytes could not be copied */

    return n;
}

/* Receiving data from the application into the driver (write side) */
ssize_t my_write(struct file *filp, const char __user *ubuf,
                  size_t count, loff_t *off)
{
    size_t n = min(count, sizeof(kbuf));

    if (copy_from_user(kbuf, ubuf, n))
        return -EFAULT;

    return n;
}

Notice the pattern: clamp the size first, attempt the copy, and always check the return value. This one pattern, repeated consistently, is what keeps a driver both correct and safe.

How the Kernel Validates a User Pointer

Internally, copy_to_user() and copy_from_user() are not a single instruction — they run through a small validation pipeline before any actual byte is moved:

Check Purpose
access_ok() Confirms the address range lies within the user address space segment, not the kernel’s
KASAN instrumentation During development builds, flags out-of-bounds or use-after-free access at the exact line that caused it
Object size / overflow checks Ensures the copy length does not run past the end of the destination object
Page fault handling If the user page is not currently resident, the kernel faults it in safely rather than crashing

Only once all of these pass does the kernel invoke the low-level worker that actually moves the bytes. If any check fails, the routine returns a non-zero value instead of crashing the kernel, and a well-written driver simply reports -EFAULT (“Bad address”) back to user space.

A Common Beginner Mistake: Wrong Buffer Length

A very common bug in early driver code is copying using the caller’s requested count directly, without clamping it to the actual size of the kernel buffer. Here is a flawed version and the corrected version, side by side:

/* Flawed: no bound on count, can read past kbuf */
ssize_t bad_read(struct file *filp, char __user *ubuf,
                  size_t count, loff_t *off)
{
    if (copy_to_user(ubuf, kbuf, count))   /* count is NOT clamped */
        return -EFAULT;
    return count;
}

/* Corrected: always clamp to the smaller of the two sizes */
ssize_t good_read(struct file *filp, char __user *ubuf,
                   size_t count, loff_t *off)
{
    size_t n = min(count, (size_t)KBUF_SIZE);

    if (copy_to_user(ubuf, kbuf, n))
        return -EFAULT;
    return n;
}

In the flawed version, if the application requests more bytes than kbuf actually holds, the driver will attempt to read past the end of its own kernel buffer before handing that memory to copy_to_user(). With KASAN enabled during development, this class of bug is caught immediately and reported with an exact stack trace, which is why every driver author should test with KASAN turned on before shipping code.

Real-World Use Cases

  • Sensor drivers: copying the latest reading from a kernel-side ring buffer out to a user space monitoring application
  • Configuration interfaces: receiving a configuration struct from a user space daemon via write() or ioctl()
  • Firmware upload paths: pulling a firmware blob from user space into a kernel buffer before writing it out to a device
  • Diagnostic drivers: exporting internal counters or logs to a user space debugging tool

Common Mistakes and Troubleshooting

Symptom Likely Cause
read()/write() fails with “Bad address” User buffer pointer was invalid, unmapped, or too small for the requested count
Data appears truncated in user space Return value of copy_to_user() (remaining bytes) was ignored instead of checked
Kernel warning or KASAN report during testing Kernel-side buffer length was not clamped to the requested count

Best Practices

  • Always clamp the requested length to your actual kernel buffer size before copying
  • Always check the return value of copy_to_user()/copy_from_user() and map any non-zero result to -EFAULT
  • Never dereference a user pointer directly — always go through the copy_* routines
  • Build and test with KASAN enabled during development
  • Keep the kernel-side buffer’s lifetime and locking clearly defined before exposing it to concurrent readers/writers

Performance Considerations

copy_to_user() and copy_from_user() are optimised in the kernel and are not significantly slower than a raw memcpy() for the validation they add. The real performance cost in most drivers comes from copying large buffers in small, repeated calls. Where possible, batch data into a single, appropriately sized transfer rather than issuing many small read()/write() calls back to back.

Security Considerations

Treat every value that arrives via copy_from_user() as untrusted input, exactly as you would treat data from the network. Validate lengths, ranges, and any embedded sizes inside a received structure before acting on them. A driver that trusts its caller blindly is a driver that can be abused.

Summary — Key Takeaways
  • Never touch a user space pointer directly from kernel code
  • copy_to_user() and copy_from_user() run through access_ok() and, in debug builds, KASAN before moving any data
  • Always clamp the copy length and always check the return value
  • A failed copy should surface to user space as -EFAULT, not a kernel crash

Conclusion

copy_to_user() and copy_from_user() are small functions with an outsized responsibility: they are the only safe doorway between your driver and the application using it. Master this one pattern — clamp, copy, check — and you will have already avoided the single most common class of bug in beginner Linux device driver code. In the next lecture of this free Linux kernel development course, we will build on this foundation with ioctl() based communication.

FAQ

Q1. What does copy_to_user() return on success?
It returns 0 when every byte was copied successfully.

Q2. Can I use memcpy() instead of copy_to_user()?
No. memcpy() performs no validation of the user address and can crash the kernel or corrupt memory if the pointer is invalid.

Q3. What does -EFAULT mean to an application?
It means the system call failed because the supplied buffer address was invalid or inaccessible — reported as “Bad address” by perror().

Q4. Is access_ok() enough on its own to make a copy safe?
No, access_ok() is only one layer. The actual copy routines still perform the real page-level validation; access_ok() is a fast preliminary sanity check.

Q5. What is KASAN and do I need it in production?
KASAN (Kernel Address Sanitizer) is a compile-time instrumentation feature used to catch memory bugs during development and testing. It adds overhead, so it is normally enabled only in debug/test kernels, not production.

Q6. What happens if the requested count is larger than my kernel buffer?
If you don’t clamp it yourself, you risk reading or writing past your own buffer before the copy even happens. Always clamp count to your buffer size first.

Q7. Do I need copy_to_user()/copy_from_user() inside ioctl() handlers too?
Yes. Any time your driver code touches a pointer that originated in user space, the same rules apply, including inside ioctl().

Continue Your Free Linux Kernel Programming Journey

More free lectures on Linux device drivers, kernel internals, and embedded systems are on the way.

Browse the Free Course Join the Community

← Previous Lecture  |  Next Lecture →

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *