diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2017-11-11 20:08:29 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2017-11-11 20:08:29 +0000 |
commit | 41c9e1bb21d539d473fc53632862e5b70e2ceb08 (patch) | |
tree | ab99c2877bb95d523d66b5cd670a5386ab18b175 /src/sys | |
parent | 8f2468ca1e3dc1a5c6c8372e47443b262e03cba5 (diff) | |
parent | 3f5de94ab02250f7d56b6039648f5b8dcb65a81e (diff) | |
download | nix-41c9e1bb21d539d473fc53632862e5b70e2ceb08.zip |
Merge #568
568: Add process_vm_readv and process_vm_writev r=asomers a=geofft
Diffstat (limited to 'src/sys')
-rw-r--r-- | src/sys/uio.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/sys/uio.rs b/src/sys/uio.rs index edca8cb4..16426ab9 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -56,6 +56,85 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{ Errno::result(res).map(|r| r as usize) } +/// A slice of memory in a remote process, starting at address `base` +/// and consisting of `len` bytes. +/// +/// This is the same underlying C structure as [`IoVec`](struct.IoVec.html), +/// except that it refers to memory in some other process, and is +/// therefore not represented in Rust by an actual slice as IoVec is. It +/// is used with [`process_vm_readv`](fn.process_vm_readv.html) +/// and [`process_vm_writev`](fn.process_vm_writev.html). +#[cfg(target_os = "linux")] +#[repr(C)] +pub struct RemoteIoVec { + /// The starting address of this slice (`iov_base`). + pub base: usize, + /// The number of bytes in this slice (`iov_len`). + pub len: usize, +} + +/// Write data directly to another process's virtual memory +/// (see [`process_vm_writev`(2)]). +/// +/// `local_iov` is a list of [`IoVec`]s containing the data to be written, +/// and `remote_iov` is a list of [`RemoteIoVec`]s identifying where the +/// data should be written in the target process. On success, returns the +/// number of bytes written, which will always be a whole +/// number of remote_iov chunks. +/// +/// This requires the same permissions as debugging the process using +/// [ptrace]: you must either be a privileged process (with +/// `CAP_SYS_PTRACE`), or you must be running as the same user as the +/// target process and the OS must have unprivileged debugging enabled. +/// +/// This function is only available on Linux. +/// +/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html +/// [ptrace]: ../ptrace/index.html +/// [`IoVec`]: struct.IoVec.html +/// [`RemoteIoVec`]: struct.RemoteIoVec.html +#[cfg(target_os = "linux")] +pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> { + let res = unsafe { + libc::process_vm_writev(pid.into(), + local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong, + remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0) + }; + + Errno::result(res).map(|r| r as usize) +} + +/// Read data directly from another process's virtual memory +/// (see [`process_vm_readv`(2)]). +/// +/// `local_iov` is a list of [`IoVec`]s containing the buffer to copy +/// data into, and `remote_iov` is a list of [`RemoteIoVec`]s identifying +/// where the source data is in the target process. On success, +/// returns the number of bytes written, which will always be a whole +/// number of remote_iov chunks. +/// +/// This requires the same permissions as debugging the process using +/// [ptrace]: you must either be a privileged process (with +/// `CAP_SYS_PTRACE`), or you must be running as the same user as the +/// target process and the OS must have unprivileged debugging enabled. +/// +/// This function is only available on Linux. +/// +/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html +/// [ptrace]: ../ptrace/index.html +/// [`IoVec`]: struct.IoVec.html +/// [`RemoteIoVec`]: struct.RemoteIoVec.html +#[cfg(any(target_os = "linux"))] +pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> { + let res = unsafe { + libc::process_vm_readv(pid.into(), + local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong, + remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0) + }; + + Errno::result(res).map(|r| r as usize) +} + #[repr(C)] pub struct IoVec<T>(libc::iovec, PhantomData<T>); |