微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

内核崩溃导致的Linux系统调用奇怪的偏移量

我试图调用一个内核模块的系统调用我有这样的代码

set_fs( get_ds() ); // lets our module do the system-calls // Save everything before systemcalling asm (" push %rax "); asm (" push %rdi "); asm (" push %rcx "); asm (" push %rsi "); asm (" push %rdx "); asm (" push %r10 "); asm (" push %r8 "); asm (" push %r9 "); asm (" push %r11 "); asm (" push %r12 "); asm (" push %r15 "); asm (" push %rbp "); asm (" push %rbx "); // Invoke the long sys_mknod(const char __user *filename,int mode,unsigned dev); asm volatile (" movq $133,%rax "); // system call number asm volatile (" lea path(%rip),%rdi "); // path is char path[] = ".." asm volatile (" movq mode,%rsi "); // mode is S_IFCHR | ... asm volatile (" movq dev,%rdx "); // dev is 70 >> 8 asm volatile (" syscall "); // POP EVERYTHING asm (" pop %rbx "); asm (" pop %rbp "); asm (" pop %r15 "); asm (" pop %r12 "); asm (" pop %r11 "); asm (" pop %r9 "); asm (" pop %r8 "); asm (" pop %r10 "); asm (" pop %rdx "); asm (" pop %rsi "); asm (" pop %rcx "); asm (" pop %rdi "); asm (" pop %rax "); set_fs( savedFS ); // restore the former address-limit value

这段代码不工作,正在崩溃系统(这是一个内核模块)。

这段代码的重定位信息的转储是:

2c: 50 push %rax 2d: 57 push %rdi 2e: 51 push %rcx 2f: 56 push %rsi 30: 52 push %rdx 31: 41 52 push %r10 33: 41 50 push %r8 35: 41 51 push %r9 37: 41 53 push %r11 39: 41 54 push %r12 3b: 41 57 push %r15 3d: 55 push %rbp 3e: 53 push %rbx 3f: 48 c7 c0 85 00 00 00 mov $0x85,%rax 46: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 4d <init_module+0x4d> 49: R_X86_64_PC32 path-0x4 4d: 48 83 c7 04 add $0x4,%rdi 51: 48 8b 34 25 00 00 00 mov 0x0,%rsi 58: 00 55: R_X86_64_32S mode 59: 48 8b 14 25 00 00 00 mov 0x0,%rdx 60: 00 5d: R_X86_64_32S dev 61: 0f 05 syscall 63: 5b pop %rbx 64: 5d pop %rbp 65: 41 5f pop %r15 67: 41 5c pop %r12 69: 41 5b pop %r11 6b: 41 59 pop %r9 6d: 41 58 pop %r8 6f: 41 5a pop %r10 71: 5a pop %rdx 72: 5e pop %rsi 73: 59 pop %rcx 74: 5f pop %rdi 75: 58 pop %rax

我想知道..为什么49:R_X86_64_PC32path-0x4中有-0x4偏移?

如何在DOS中显示汇编中的字符?

将Linux x86-64程序集hello world程序与ld链接失败

在Linux上混合syscall写与printf

Linux内核中的FPU使用

如何在汇编中正确调用64位Windows API

我的意思是:模式和开发应该自动解决没有问题,但path呢? 为什么-0x4抵消?

我试图“补偿”

lea 0x0(%rip),%rdi //这个以某种方式增加一个-0x4偏移量加$ 0x4,%rdi ….

代码仍然崩溃。

我哪里错了?

尝试在Ubuntu上的NASM上运行.asm文件时出错

来自用户间的int指令

我如何find使用NASM的string的长度?

为什么不能从调用c库printf在标准输出到其他程序?

如何将C代码转换为程序集的hex表示?

我猜这是怎么回事,是一个堆栈问题。 与int $0x80不同, syscall指令不会为内核设置堆栈。 如果你看看system_call:的实际代码,你会看到类似SWAPGS_UNSAFE_STACK东西。 这个宏的肉是SwapGS指令 – 见这里的第152页。 当进入内核模式时,内核需要一种方法来将指针拉到它的数据结构上,而这个指令可以让它做到这一点。 它通过将用户%gs寄存器与保存在特定于模型的寄存器中的值进行交换,然后从中取出内核模式堆栈。

你可以想象,一旦syscall入口点被调用,这个交换就产生了错误的值,因为你已经处于内核模式,内核开始尝试使用一个虚拟栈。 您可以尝试手动调用SwapGS,使内核的SwapGS结果符合要求,并查看是否可行。

看来你不能这样做。 请参阅system_call之前的注释 :

/* * Register setup: * rax system call number * rdi arg0 * rcx return address for syscall/sysret,C arg3 * rsi arg1 * rdx arg2 * r10 arg3 (--> moved to rcx for C) * r8 arg4 * r9 arg5 * r11 eflags for syscall/sysret,temporary for C * r12-r15,rbp,rbx saved by C code,not touched. * * Interrupts are off on entry. * Only called from user space. * * XXX if we had a free scratch register we Could save the RSP into the stack frame * and report it properly in ps. Unfortunately we haven't. * * When user can change the frames always force IRET. That is because * it deals with uncanonical addresses better. SYSRET has trouble * with them due to bugs in both AMD and Intel cpus. */

所以,你不能从内核syscall 。 但是你可以尝试使用int $0x80来达到这个目的。 正如我所看到的, kernel_execve存根使用这个技巧

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐