【发布时间】:2021-10-27 07:51:13
【问题描述】:
我正在尝试通过 ptrace 拦截和阻止系统调用。该问题发生在系统调用结果的返回期间。 errno 保持为 0,即使在系统调用返回中使用 -EPERM。
我试过运行这个EXAMPLE。结果是一样的。
$ ./xpledge ./example
fread("/dev/urandom")[1] = 0xb2ac39c4
XPledging...
fopen("/dev/urandom")[2]: Success
fread("/dev/urandom")[1] = 0x2e1bd1c4
下面是部分代码:
if (is_syscall_blocked(regs.orig_rax)) {
regs.orig_rax = -1; // set to invalid system call
if (ptrace(PTRACE_SETREGS, pid, 0, ®s) == -1)
FATAL("%s", strerror(errno));
}
/* Run system call and stop on exit */
if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1)
FATAL("%s", strerror(errno));
if (waitpid(pid, 0, 0) == -1)
FATAL("%s", strerror(errno));
switch (regs.orig_rax) {
case -1:
if (ptrace(PTRACE_POKEUSER, pid, RAX * 8, -EPERM) == -1)
FATAL("%s", strerror(errno));
break;
}
所以问题是。拒绝系统调用时如何正确设置errno?
【问题讨论】:
-
您是否阅读了您链接到的自述文件中链接的文章?它至少有一些指示这是怎么可能的。
-
@thebusybee 是的,我读过这篇文章。我在那里没有找到任何解决方案。
-
好吧,我没有时间阅读那个和链接的文章,有趣的部分似乎已经完成了一半。一般来说,我不认为一个应用程序可以更改另一个应用程序的
errno,因为它是一个静态变量。如果可以,它可以更改任何静态变量,这是一件坏事...... -
@thebusybee 但 ptracer 充当系统调用拦截器。它如何返回错误?如果我们离开 ptrace,并使用不存在的文件调用例如 openat(),内核将返回错误,并将 errno 设置为 2。如果内核可以更改 errno,为什么 ptracer 不能?
-
我只是想了解 errno 是从哪里来的。它是从哪个寄存器创建的。 Glibc 必须处理来自 syscall() 的负返回。在我阅读的 glibc 文档中,引用:“syscall() 在进行系统调用之前保存 CPU 寄存器,在从系统调用返回时恢复寄存器,并将系统调用返回的任何错误存储在 errno(3) 中。”。我尝试使用 musl 编译示例,但结果是一样的。 errno 中的成功,而不是 EPERM。