【问题标题】:How to set child`s errno by ptrace?如何通过 ptrace 设置孩子的 errno?
【发布时间】: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, &regs) == -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。

标签: c linux ptrace


【解决方案1】:

实际上示例中的代码看起来不正确。在本教程中有一些不一样的代码片段。如果您尝试一下,它似乎提供了正确的输出

switch (regs.orig_rax) {
    case -1:
        regs.rax = -E2BIG;
        if (ptrace(PTRACE_SETREGS, pid, 0, &regs) == -1)
            FATAL("%s", strerror(errno));
        break;

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多