process_vm_writev无法写入我能够读取的同一地址

process_vm_writev not able to write to the same address that I was able to read from

本文关键字:读取 地址 writev vm process      更新时间:2023-10-16

我正在Ubuntu机器上编写一个C++程序。我正在使用函数调用<sys/uio.h>库中的process_vm_readvprocess_vm_writev来尝试在另一个进程的内存中搜索值,然后写入不同的值。

我能够成功搜索和查找(通过proceess_vm_readv功能)我要更改的数据。我捕获了它所在的地址,并尝试使用该process_vm_writev但返回值为 -1,errno设置为 14,代表bad address

有什么理由我不应该能够写入一些我也可以读取的内存吗?我正在寻找的数据可以在地址0x6005df处找到,但直到0x601000我才能真正开始写回数据。

我在使用FUSE 时遇到了同样的问题,其中数据的地址是使用 ioctl(... *arg) 从客户端完美提供的,因此客户端的数据可以由服务器使用process_vm_readv()读取。

但是:process_vm_writev()不会更改客户端中的相同内存位置(无错误)。但是,当客户端提供指向指针指针而不仅仅是地址指针时,您可以更改客户端的内存。内存位置是在堆中还是在堆栈中并不重要。

另外:如果您尝试写入 ioctl() 提供的地址和长度(cmd 参数代码类型、方向和数据大小)上方的地址,那么这是可以的。 似乎在 ioctl 调用内核期间以某种方式保护提供的内存区域。

另外2:如果您使要传输的结构/数据的大小为0,则可以修改所提供地址的客户端内存(ioctl(...参数)。

就我而言,发生这种情况是因为我在process_vm_writev()中错误地放置了参数的顺序:本地和远程IOV都指向堆栈VMA。由于ASLR,它们略有不同。在内核中处理系统调用期间,尝试扩展相关的 VMA -expand_stack函数。最终结果是,我的进程的堆栈地址与我正在写入的进程的 VMA 之间的偏移量大于进程堆栈限制,因此-EFAULT.