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.

ITPUB
ITPUB
ITPUB
Why Linux Drivers Must Use copy_from_user Instead of memcpy – Security and Stability Explained

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?

memcpy

lacks 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KernelLinuxSecuritycopy_from_userdriver
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.