【问题标题】:RUST error ENOMEM in call of posix_memalign into attached program将 posix_memalign 调用到附加程序中时出现 RUST 错误 ENOMEM
【发布时间】:2022-01-05 18:51:57
【问题描述】:

我会试着总结一下,但这会很复杂。

我在我的大学里有操作系统课程,我有一个实验室工作要做。 我在 Rust 工作(据说实验室工作可以用任何编译语言完成,但最初主要是为 C 设计的)。

所以我有一个tracer程序和一个traced程序。

实验室工作这一步的目标是使用 ptrace 将 tracer 附加到 traced,然后在以下位置注入“trap-call-trap”指令用 traced 中的函数 posix_memalign(来自 libc)替换现有无用函数的好地方,通过寄存器间接调用(使用 rax)。目标是分配内存以便以后能够将缓存代码从另一个文件调用到被跟踪的程序中。

我遇到的问题是我实现了在跟踪器中执行 posix memalign 所以我知道该函数有效,但是当我在跟踪器中调用它时(通过跟踪器),并在寄存器 rax 中查找返回的函数,我总是得到一个对应于 ENOMEM 的“12”(ENOMEM 没有足够的空间/无法分配内存)。

我有 2 个独立的货物项目,以便能够与货物分开启动每个程序。 一切都在这个 git 上:https://github.com/Carrybooo/TP_SEL

很抱歉,所有的印刷品和输出都是法语,(一些 cmets 也是,我正在上法语课程),我认为我不必与任何人分享。里面也有很多没用的代码,之前的实验步骤,我留着以防万一,所以我的代码不是很干净。

这是我附加和修改 regs 以调用函数的部分(我缩短了代码并且没有向您显示辅助函数声明,因为它会太长):


    ptrace::attach(pid_ptrace) //attaching to process

    wait(); //wait after attaching

    inject(pid_trace, offset_fct_to_replace, false); //injecting trap-call-trap
    ptrace::cont(pid_ptrace, Signal::SIGCONT);

    wait(); //wait for 1st trap

    let mut regs =
        ptrace::getregs(pid_ptrace);

    let ptr_to_ptr: *mut *mut c_void = ptr::null_mut();

    regs.rax = get_libc_address(pid_trace).unwrap() + get_libc_offset("posix_memalign").unwrap();
    regs.rsp = regs.rsp - (size_of::<*mut *mut c_void>() as u64);
    regs.rdi = ptr_to_ptr as u64;
    regs.rsi = size_of::<usize>() as u64;
    regs.rdx = size_of::<usize>() as u64;

    ptrace::setregs(pid_ptrace, regs); //set regs with modification

    ptrace::cont(pid_ptrace, Signal::SIGCONT);

    wait();

    let regs = ptrace::getregs(pid_ptrace);

    ptrace::detach(pid_ptrace, Signal::SIGCONT) //detaching

在终端中运行程序会得到这样的结果:

before modification of regs:
rax = 6
rip = 55e6c932ddc1
rsp = 7ffcee0b7fb8

before function execution:
rax = 7f59b935ded0
rdi = 0
rip = 55e6c932ddc1
rsp = 7ffcee0b7fb0

after function execution:
rax = 12                                   <------//RESULT OF THE CALL IS HERE
rdi = 55e6cac6aba0
rip = 7f59b935df20
rsp = 7ffcee0b7f90

//end of program

所以是的,我不知道为什么我在这个调用中不断收到错误,我认为这是因为它违反了 rust 内存安全,因为编译器在 traced 程序中从来不知道它会分配内存,但我不确定,也不确定如何绕过它。 我希望我已经足够清楚了,如果您需要更多详细信息,请告诉我,我真的提前感谢任何可以帮助我的人。欢迎任何建议。

【问题讨论】:

  • 为什么是regs.rdx = 0; //size_of::&lt;usize&gt;() as u64;?你不想分配一些东西吗?
  • 我尝试了许多不同的参数,看看大小或对齐是否有问题,这里是 0,因为它是我测试的最后一个值,但对于 4096 或其他任何值,结果相同我试过了。我将对其进行编辑以放回最后一个值。
  • 我问是因为 glibc mem_align 调用 malloc 以获得小于或等于系统 ptr 大小的对齐,而 malloc 为 0 大小返回 NULL,mem_align 将其解释为分配失败(甚至没有检查errno) 并返回 ENOMEM。
  • 好的,我明白你的意思。我已将size_of::&lt;usize&gt;() 放回原处,因为代码中的上部(问题中未显示)我已经使用这些参数在本地程序中测试了该函数并且它运行良好。现在我使用相同的参数,因为我知道它至少在本地工作。

标签: memory rust libc ptrace enomem


【解决方案1】:

所以我使用 libc memalign 而不是使用 posix_memalign。它不受限制,并且在跟踪程序中使用寄存器调用时效果很好。

仍然不知道为什么 posix_memalign 在 rust 程序中从 regs 调用时不起作用。

【讨论】: