You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译内核自定义系统调用遇struct pt_regs及raw_copy_to_user错误求助

问题解决:内核编译及自定义系统调用错误

1. 编译错误:raw_copy_to_user 类型冲突

错误原因

你手动添加的 typedef unsigned int __bitwise gfp_t; 与内核头文件中已有的 gfp_t 定义重复,导致依赖该类型的函数(如 raw_copy_to_user)类型解析混乱,触发冲突。

解决方法

直接删除代码中的这一行:

typedef unsigned int __bitwise gfp_t;

内核头文件会自动包含 gfp_t 的定义,无需手动重复声明。


2. IntelliSense错误:struct pt_regs 类型不完整

错误原因

VS Code的IntelliSense未找到内核中 struct pt_regs 的定义,因为你的 c_cpp_properties.json 仅包含了系统默认头文件路径,而内核架构相关头文件(如 pt_regs 的定义)位于内核源码目录内,不在 /usr/include 下。

解决方法

修改 c_cpp_properties.json 的 includePath,添加你的内核源码绝对路径(示例中使用 ~/linux-5.15,请替换为实际路径):

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/**",
                "~/linux-5.15/**",
                "~/linux-5.15/arch/x86/include/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "linux-gcc-x64",
            "configurationProvider": "ms-vscode.cpptools"
        }
    ],
    "version": 4
}

同时在自定义系统调用代码中添加头文件:

#include <asm/ptrace.h>

该头文件包含 struct pt_regs 的定义,可解决IntelliSense的类型识别问题。


3. 自定义系统调用代码的其他潜在问题

除上述错误外,代码还有几处逻辑问题需修正,否则编译通过后也会运行出错:

  • 禁止直接对用户空间指针调用 strlen:src 是用户空间指针,直接在内核中调用 strlen 会触发非法内存访问,需先安全计算用户空间字符串长度。
  • 冗余的手动拷贝逻辑:内核空间内拷贝字符串可直接使用 strcpy,无需手动循环。
  • 缺少内存分配失败检查:kmalloc 可能返回NULL,需添加空指针检查避免崩溃。

修正后的代码示例:

// strcpy.c: code for the new system call
#include <linux/kernel.h>
#include <linux/slab.h>    // kmalloc()
#include <asm/uaccess.h>   // copy_from_user(), copy_to_user()
#include <linux/syscalls.h>// SYSCALL_DEFINE2
#include <linux/types.h>   // 确保内核类型定义被包含
#include <asm/ptrace.h>    // struct pt_regs定义
#include <linux/string.h>  // strcpy()

SYSCALL_DEFINE2(strcpy, char __user*, dest, const char __user*, src) {
    int size = 0;
    char *tmp1, *tmp2;
    char ch;

    // 安全计算用户空间字符串长度
    while (copy_from_user(&ch, src + size, 1) == 0 && ch != '\0') {
        size++;
    }
    size++; // 加上终止符'\0'的长度

    // 分配内核内存并检查是否成功
    tmp1 = kmalloc(size, GFP_KERNEL);
    tmp2 = kmalloc(size, GFP_KERNEL);
    if (!tmp1 || !tmp2) {
        printk(KERN_ALERT "kmalloc failed\n");
        kfree(tmp1);
        kfree(tmp2);
        return -ENOMEM;
    }

    // 从用户空间拷贝字符串到内核
    if (copy_from_user(tmp1, src, size) != 0) {
        printk(KERN_ALERT "copy_from_user error\n");
        kfree(tmp1);
        kfree(tmp2);
        return -EFAULT;
    }

    // 内核空间内拷贝字符串
    strcpy(tmp2, tmp1);

    // 拷贝到用户空间
    if (copy_to_user(dest, tmp2, size) != 0) {
        printk(KERN_ALERT "copy_to_user error\n");
        kfree(tmp1);
        kfree(tmp2);
        return -EFAULT;
    }

    kfree(tmp1);
    kfree(tmp2);
    printk(KERN_ALERT "done system call strcpy...\n");
    return size; // 返回拷贝的字节数更符合系统调用规范
}

内容的提问来源于stack exchange,提问作者Mals

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 08:05:20