【问题标题】:Linux Kernel systemcall call with an "int 0x80"带有“int 0x80”的 Linux 内核系统调用调用
【发布时间】:2012-10-09 09:05:43
【问题描述】:

我正在研究 Linux 内核,目前我正在尝试实现自己的系统调用。

在内核代码中如下所示:

asmlinkage long sys_my_syscall()
{
     printk("My system call\n");
     return 0;
}

如果我用 systemcall() 函数调用它,它可以正常工作,但我找到了另一种方法:

int my_syscall(void)
{
    long __res;
    __asm__ volatile (
    "movl $312, %%eax;"
    "int $0x80;"
    "movl %%eax, %0;"
    : "=m" (__res)
    :
    : "%eax"
    );
    if ((unsigned long) (__res) >= (unsigned long) (-125)) {
       errno = -(__res);
       __res = -1;
    }
    return (int)(__res);
}

但它返回值-14EFAULT

我做错了什么?

设置: Linux 内核 3.4,ARCH x86_64

【问题讨论】:

  • 我建议在 glibc 源代码中查找 systemcall() 源代码 - 它可能会显示出差异。
  • 你的系统是 64 位的吗?如果是这样,也许您需要使用 %rax 寄存器?您的 sn-p 是 32 位汇编语言。
  • stackoverflow.com/questions/3730064/…,对于64位应用程序你不能使用int 0x80

标签: c linux assembly linux-kernel system-calls


【解决方案1】:

对于 64 位系统,Linux 系统调用 ABI 与 i*86 完全不同,除非有一层兼容性。 这可能会有所帮助: http://callumscode.com/blog/3

我还在 eglibc 中找到了系统调用源,它看起来确实不同: http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/libc/sysdeps/unix/sysv/linux/x86_64/syscall.S?view=markup

所以看起来int $0x80 不适用于x86_64 Linux 内核,您需要改用syscall

【讨论】:

  • 它确实“工作”,但前提是可以将输入截断为 32 位(并且如果启用了 CONFIG_IA32_EMULATION)。
【解决方案2】:

我有两个想法。

  1. 您是否更新了系统调用表?

对于内核 4.14,它是 arch/x86/entry/syscalls/syscall_64.tbl

  1. 您是否启用了 COMPAT_32 内核选项?

如果没有,int 0x80 将不起作用。 您的系统似乎已启用此选项,否则您会遇到 #GP 异常。

【讨论】:

  • 他们得到的是-EFAULT,而不是-ENOSYS,所以我们知道系统调用表不是问题。 -EFAULT 是 32 位 int 0x80 ABI 截断 64 位指针的典型症状。我使用的 dup 目标的许多其他副本是新手调用 readwriteint 0x80 并在 64 位模式下使用堆栈参数。 (我们现在可能会在 PIE 可执行文件中看到更多的静态数据。)
  • 哦,实际上,这个系统调用没有任何输入,所以这很奇怪。哦,不,不是,你是对的:unistd_32.h 中有一个现有的 32 位系统调用 312.#define __NR_get_robust_list 312,它返回 -EFAULT 以及 EBX/ECX/EDX/ 中的任何垃圾也就不足为奇了...(毕竟可能不是 What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? 的确切副本。)
猜你喜欢
  • 2015-06-09
  • 2010-09-20
  • 1970-01-01
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 2013-04-25
相关资源
最近更新 更多