简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址: 多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🌻1. 前言

本篇目的:Linux 内核深度解析之 copy_from_user 全路径调用流程与实战。


🌻2. 用法与应用场景

copy_from_user 是内核态安全访问用户态地址空间的标准化接口。

  • 用法:unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);
  • 返回值:成功返回 0;失败返回 剩余未拷贝字节数。
  • 应用场景:
  1. 系统调用数据载入:如 write、ioctl 等系统调用将用户配置或数据下发至内核。
  2. 网络协议栈:应用层数据包拷贝至内核缓冲区进行封装。
  3. 设备驱动控制:用户态通过 write 向驱动下发控制指令。

🌻3. 调用流程剖析

copy_from_user 的调用链路贯穿了通用逻辑层、安全校验层和硬件架构汇编层,每一个层级都承载了关键职责。

3.1 核心调用栈深度解析(以 ARM64 为例)
  1. copy_from_user(to, from, n) [Macro]
  • 定义在 include/linux/uaccess.h。
  • 职责:作为统一入口,首先进行 access_ok(from, n) 校验。检查用户指针是否位于用户空间范围(),防止用户程序诱导内核访问内核空间。
  1. _copy_from_user(to, from, n)
  • 职责:中间分发层。
  • might_fault():触发内核调试检测,确认当前上下文是否允许阻塞(因为用户态页可能不在内存,拷贝可能导致缺页中断并引起进程睡眠)。
  1. check_object_size(to, n, true)
  • 职责:如果内核开启了 CONFIG_HARDENED_USERCOPY,此步会校验 to(内核目标地址)是否属于合法的 slab 或堆栈对象,防止缓冲区溢出攻击。
  1. instrument_copy_from_user(to, from, n)
  • 职责:为 KASAN(内核地址分析器)提供桩函数,用于检测潜在的内存访问违规。
  1. raw_copy_from_user(to, from, n)
  • 职责:进入具体的架构抽象层。
  1. arch_copy_from_user(to, from, n)
  • 职责:在 arch/arm64/include/asm/uaccess.h 中定义,跳转至汇编实现。
  1. __arch_copy_from_user [Assembly]
  • 源文件:arch/arm64/lib/copy_from_user.S。
  • 职责:使用 ldp/stp 指令进行高性能搬运。
  1. Exception Table & Fixup Logic
  • 职责:如果在汇编搬运期间触发 Page Fault(如地址非法或页在 swap 中),内核会捕获该异常。

异常表机制详解:
内核在编译时会将 __arch_copy_from_user 的指令地址记录在 .section __ex_table 中。当硬件报错时,内核异常处理函数 do_page_fault 会查找此表。如果是来自该函数的异常,内核不会 Panic,而是将 PC 指针跳转到修复段(Fixup code),该段代码负责清理现场并返回未拷贝的字节数。


🌻4. 涉及核心时序图

Exception Table / Fixup ASM (__arch_copy_from_user) raw_copy_from_user check_object_size _copy_from_user (Safety) copy_from_user (Macro) 用户态应用 Exception Table / Fixup ASM (__arch_copy_from_user) raw_copy_from_user check_object_size _copy_from_user (Safety) copy_from_user (Macro) 用户态应用 alt [发生页错误 (Page Fault)] [拷贝成功] 触发系统调用 (buf, len) access_ok() 校验地址范围 转发拷贝请求 might_fault() 检查是否可睡眠 check_object_size() 检查目标合法性 进入架构抽象层 调用平台汇编代码 执行 ldp/stp 指令拷贝 触发 CPU 异常 查找异常表修复项 跳转至 Fixup 段 返回剩余字节数 n > 0 返回 0 返回拷贝状态 返回结果 返回系统调用结果

🌻5. 驱动实战 Demo

此 Demo 演示了在字符设备驱动中,如何通过上述全路径接收用户数据。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h> // 包含核心调用栈头文件
#include <linux/slab.h>

#define DRV_NAME "full_stack_copy"
static char *k_mem;

static ssize_t my_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
    unsigned long res;
    
    // 1. 动态限速/限容
    if (count > 2048) count = 2048;

    // 2. 内核空间准备
    if (k_mem) kfree(k_mem);
    k_mem = kzalloc(count + 1, GFP_KERNEL);
    if (!k_mem) return -ENOMEM;

    /*
     * 3. 核心调用:依次通过 access_ok -> might_fault -> 
     * check_object_size -> raw_copy_from_user -> 汇编
     */
    res = copy_from_user(k_buffer, buf, count);

    if (res == 0) {
        pr_info("%s: Successfully copied %zu bytes\n", DRV_NAME, count);
        return count;
    } else {
        // 如果 res > 0,说明在 A 层触发了异常表跳转
        pr_err("%s: Partial copy! %lu bytes failed. Potential bad address.\n", DRV_NAME, res);
        return -EFAULT;
    }
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .write = my_drv_write,
};

static int __init my_init(void) {
    register_chrdev(242, DRV_NAME, &fops);
    return 0;
}

static void __exit my_exit(void) {
    unregister_chrdev(242, DRV_NAME);
    kfree(k_mem);
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");


🌻6. 用法总结

调用层级核心职责关键报错/结果
通用层 (Macro)access_ok 地址合法性检查若不合法直接返回 n
内核安全层check_object_size 溢出检查可能触发 BUG() 或告警
调试层might_fault 睡眠检查在不可睡眠处调用会触发 Kernel Dump
架构层 (ASM)指令级拷贝与异常锚点通过 CPU 异常机制捕获非法访问
异常表层Fixup 代码恢复现场确保内核不崩溃,仅返回错误
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐