Why Linux Drivers Must Use copy_from_user Instead of memcpy – Security and Stability Explained
The article explains that kernel code must copy user‑space buffers with copy_from_user rather than using memcpy, covering the necessity of copying, the built‑in access checks, page‑fault handling, security implications, and modern hardware safeguards like PAN.
Many developers wonder why Linux kernel code is required to use copy_from_user instead of a direct memcpy. The answer can be split into two layers: the need to copy data at all, and the reasons for preferring copy_from_user over memcpy.
Why the data must be copied
Kernel objects often store persistent strings, such as the name field of a struct kobject:
struct kobject {
const char *name;
/* ... */
};When a driver sets a device name it calls dev_set_name() which ultimately copies the supplied string into newly allocated kernel memory:
int dev_set_name(struct device *dev, const char *fmt, ...);If the driver were to store a pointer to a stack‑allocated buffer (a temporary variable in user space), the pointer would become invalid as soon as the function returns, leading to use‑after‑free bugs. Therefore the kernel always allocates its own storage and copies the string.
Copying at the user‑kernel boundary
A user‑space pointer (e.g., const char __user *buf) is only valid in the address space of the calling process. After a context switch, an interrupt, a workqueue, or a kernel thread runs, that address may refer to unrelated memory, causing crashes or security breaches.
Consequently, kernel code must copy the buffer into a region that remains valid across all contexts. A typical driver example uses copy_from_user to move data into a permanent kernel buffer:
static ssize_t globalmem_write(struct file *filp,
const char __user *buf,
size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data;
/* ... */
if (copy_from_user(dev->mem + p, buf, count))
ret = -EFAULT;
else {
*ppos += count;
ret = count;
}
return ret;
}Security checks for iovec‑based system calls
System calls such as preadv and pwritev receive an array of struct iovec describing user buffers. The kernel first copies the entire iovec array with copy_from_user and then validates each entry with access_ok to ensure the buffers reside in user space.
struct iovec {
void __user *iov_base; /* buffer address */
__kernel_size_t iov_len;/* buffer length */
};Only after this verification does the kernel copy the actual data, preventing a malicious process from passing kernel‑space addresses that could corrupt kernel memory.
Why not use memcpy directly?
memcpylacks the built‑in access_ok check and the exception‑fixup mechanism that copy_from_user provides. Using memcpy with an invalid user pointer can trigger a kernel Oops or even a security vulnerability, as demonstrated by CVE‑2017‑5123 where an unsafe put_user call allowed privilege escalation.
When copy_from_user encounters a bad address it returns -EFAULT and the calling process receives a clean error message, while the kernel remains stable.
Exception handling and hardware safeguards
The kernel’s copy_from_user implementation contains page‑fault handling code that fixes up faults caused by invalid user addresses, as described in the kernel’s exception‑tables documentation. This mechanism is absent from memcpy.
Modern ARM processors introduce the Privileged Access Never (PAN) feature, which disables kernel access to user memory except in explicitly marked code regions. copy_from_user is designed to work with PAN, automatically enabling and disabling the necessary permissions, whereas raw memcpy would violate PAN and cause a fault.
Conclusion
Using copy_from_user is essential for three reasons: it guarantees that the kernel works with a stable copy of user data, it enforces security checks that prevent user‑supplied kernel addresses, and it provides robust exception handling that keeps the system alive even when user pointers are invalid. Replacing it with memcpy removes these safeguards and can lead to crashes, data corruption, or security exploits.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
