← Previous Lecture | Next Lecture →
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.
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()andcopy_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
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 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()orioctl() - 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.
- 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().
More free lectures on Linux device drivers, kernel internals, and embedded systems are on the way.
Browse the Free Course Join the Community
2 Comments