调用 kfree 时崩溃(在内核模块内)

标签 c linux assembly free kernel-module

我有这个代码

int64_t ret;
char *fmt = "\n\n\n%s\n\n\n";
char *s;

s = kmalloc(13, GFP_KERNEL);
memcpy(s, "Hello world!\0", 13);

__asm__ __volatile__ (
    "movq %2, %%rdi;"
    "movq %1, %%rsi;"
    "movq $2, %%rax;"

    "call printk;"
    "movq %%rax, %0;"

    : "=r" (ret)
    : "r" (s), "r" (fmt)
    :
);

__asm__ __volatile__ (
    "movq %0, %%rdi;"
    "movq $1, %%rax;"
    "call kfree;"

    :
    : "r" (s)
    :
);

return ret;

kfree 调用时崩溃。这一定很愚蠢,但我无法找出它是什么。有什么问题?

编辑:“崩溃”== 内核模块触发糟糕。

编辑:如果我使用 m 而不是 r,它似乎工作得很好。但是为什么?

最佳答案

您应该查看生成的汇编代码(使用 gcc-S 选项)以准确了解发生了什么。

我猜问题是您没有为 printk block 指定正确的 clobbers。请记住,某些寄存器可以由被调用函数自由使用。编译器不处理内联 asm block 的内容,因此它不知道其中有一个 call。它期望未指定为输出或破坏的寄存器将从 asm block 中原封不动地出来。因此,我假设编译器将变量 s 缓存在一个寄存器中,该寄存器被 printk 或您对 raxrdi 的使用所破坏rsi 您也不会告诉编译器。请注意,存在特定的寄存器约束,因此您可以使用这些约束而不是在程序集中移动参数。

另请注意,rax(实际上是 al)仅用于可变参数和标准参数函数,即便如此,它也应该只包含通过 sse vector 传递的参数数量( xmm) 寄存器,而不是总数。有关详细信息,请参阅 x86-64 ABI 文档。

最后,如果你真的想写 asm 代码,你应该考虑写独立的 asm 模块,而不是 C。你可以避免让自己头疼。参见 this question举个例子。

关于调用 kfree 时崩溃(在内核模块内),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20316771/

相关文章:

c - sizeof 的错误结果

c - 为什么三元运算可能未定义

sql-server - 如何在 Linux 中通过 Perl 脚本访问 SQL Server 数据库?

linux - 如何聚合文件或合并

c - 获取64位CPUID示例代码在VS2008中编译

c++ - gdb 在检查断点处的条件时失败

c - 在不知道整数的实际个数的情况下扫描多个整数

linux - IP转发,(数据包重定向)

c++ - 汇编中的指针/内存算法

assembly - 宏替换GAS中的常数