我开始开发一个带有内联汇编的内核模块,我正在尝试执行写入系统调用以写入文件。它编译得很好(此外,在 C 程序中工作正常(,但是当我加载模块时,它会丢弃分段错误,当我查看诊断消息 (dmesg( 时,我看到以下内容:
[ 672.687568] BUG: stack guard page was hit at ffffb8a601d13fa8 (stack is ffffb8a601d14000..ffffb8a601d17fff)
[ 672.687577] kernel stack overflow (double-fault): 0000 [#1] SMP
...
[ 672.777032] [<ffffffffa50fda16>] ? SYSC_finit_module+0xc6/0xf0
[ 672.777396] [<ffffffffa55ebebb>] ? system_call_fast_compare_end+0xc/0x9b
[ 672.777765] Code: 48 89 e7 48 8b 74 24 78 48 c7 44 24 78 ff ff ff ff e8 28 09 a7 ff e9 53 02 00 00 0f 1f 00 0f 1f 00 66 0f 1f 44 00 00 48 83 c4 88 <e8> 7e 01 00 00 48 89 e7 48 8b 74 24 78 48 c7 44 24 78 ff ff ff
[ 672.779059] RIP [<ffffffffa55ed27d>] page_fault+0xd/0x30
[ 672.779481] RSP <ffffb8a601d13fb8>
[ 672.779901] fbcon_switch: detected unhandled fb_set_par error, error code -16
内核模块的代码如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
int example_init(void);
void example_exit(void);
module_init(example_init);
module_exit(example_exit);
int example_init(void) {
char *file = "/root/test2";
char *msg = "AAAAAAn";
asm( "mov eax, 0x2;"
"mov rdi, %0;"
"mov rsi, 0x441;"
"xor rdx, rdx;"
"syscall;"
"mov rdi, rax;"
"mov eax, 0x1;"
"mov rsi, %1;"
"mov rdx, 7;"
"syscall;"
"mov eax, 0x3;"
"syscall;"
: "=m" (file), "=m" (msg)
);
printk("Example: module loaded.n");
return 0;
}
void example_exit(void) {
printk("Example: module removedn");
}
我知道失败出在系统调用指令中,因为我在没有系统调用指令的情况下尝试过,并且汇编代码正常工作,并且在启动系统调用时只做了分段错误。
正如@RossRidge在评论中指出的那样,Linux 内核不是为从内核代码中使用的系统调用而设计的。因此syscall
指令不应在内核代码中使用。
系统调用获得的某些功能具有内核内的替代功能。例如,对于在内核中打开文件,可以使用filp_open
,而对于写入文件-vfs_write
。有关在内核代码中使用文件的更多信息,请参阅该问题。