使用“int 0x80”调用Linux内核系统调用

3

我正在学习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


1
жҲ‘е»әи®®жҹҘжүҫglibcжәҗд»Јз Ғдёӯзҡ„systemcall()жәҗд»Јз Ғ - иҝҷеҸҜиғҪдјҡжҳҫзӨәе·®ејӮгҖӮ - Dmytro Sirenko
你的系统是64位的吗?如果是,也许你需要使用%rax寄存器?你的代码片段是32位汇编语言。 - Dmytro Sirenko
2
请参见https://dev59.com/xlDTa4cB1Zd3GeqPJ4ZA,对于64位应用程序,您不能使用 int 0x80 - nos
2个回答

5

1
它确实“工作”,但只有在截断输入为32位(并且启用了CONFIG_IA32_EMULATION)的情况下才可以。 - Peter Cordes

2

我有两个想法。

  1. 你更新了系统调用表吗?

对于内核4.14,它在arch/x86/entry/syscalls/syscall_64.tbl中。

  1. 你启用了COMPAT_32内核选项吗?

如果没有,int 0x80不会工作。 看起来你的系统已经启用了这个选项,否则你会遇到#GP异常。


他们得到的是-EFAULT,而不是-ENOSYS,因此我们知道系统调用表不是问题所在。 -EFAULT是将64位指针截断为32位int 0x80 ABI的经典症状。 我使用的许多dup目标的其他副本都是新手在64位模式下使用堆栈参数调用readwrite。 (现在我们也可能会看到更多静态数据在PIE可执行文件中。) - Peter Cordes
1
哦,实际上,这个系统调用没有任何输入,所以很奇怪。哦,不,你是对的:存在一个现有的32位syscall 312。在unistd_32.h中定义了#define __NR_get_robust_list 312,并且它返回-EFAULT和EBX / ECX / EDX / ...中的任何垃圾一样(也许并不完全是如果您在64位代码中使用32位int 0x80 Linux ABI会发生什么?的副本)。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接