2012-03-19 19:07:13 +00:00
|
|
|
.\" Copyright (C) 2011 Christopher Yeoh <cyeoh@au1.ibm.com>
|
|
|
|
.\" Copyright (C) 2012 Mike Frysinger <vapier@gentoo.org>
|
|
|
|
.\"
|
|
|
|
.\" Permission is granted to make and distribute verbatim copies of this
|
|
|
|
.\" manual provided the copyright notice and this permission notice are
|
|
|
|
.\" preserved on all copies.
|
|
|
|
.\"
|
|
|
|
.\" Permission is granted to copy and distribute modified versions of this
|
|
|
|
.\" manual under the conditions for verbatim copying, provided that the
|
|
|
|
.\" entire resulting derived work is distributed under the terms of a
|
|
|
|
.\" permission notice identical to this one.
|
|
|
|
.\"
|
|
|
|
.\" Since the Linux kernel and libraries are constantly changing, this
|
|
|
|
.\" manual page may be incorrect or out-of-date. The author(s) assume no
|
|
|
|
.\" responsibility for errors or omissions, or for damages resulting from
|
|
|
|
.\" the use of the information contained herein. The author(s) may not
|
|
|
|
.\" have taken the same level of care in the production of this manual,
|
|
|
|
.\" which is licensed free of charge, as they might when working
|
|
|
|
.\" professionally.
|
|
|
|
.\"
|
|
|
|
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
|
|
.\" the source, must acknowledge the copyright and authors of this work.
|
|
|
|
.\"
|
|
|
|
.TH PROCESS_VM_READV 2 2012-03-09 "Linux" "Linux Programmer's Manual"
|
|
|
|
.SH NAME
|
|
|
|
process_vm_readv, process_vm_writev \- read/write from/to another processes' address space
|
|
|
|
.SH SYNOPSIS
|
|
|
|
.B #include <sys/uio.h>
|
|
|
|
.sp
|
|
|
|
.BI "ssize_t process_vm_readv(pid_t " pid ,
|
|
|
|
.br
|
|
|
|
.BI " const struct iovec *" lvec ,
|
|
|
|
.br
|
|
|
|
.BI " unsigned long " liovcnt ,
|
|
|
|
.br
|
|
|
|
.BI " const struct iovec *" rvec ,
|
|
|
|
.br
|
|
|
|
.BI " unsigned long " riovcnt ,
|
|
|
|
.br
|
|
|
|
.BI " unsigned long " flags ");"
|
|
|
|
|
|
|
|
.BI "ssize_t process_vm_writev(pid_t " pid ,
|
|
|
|
.br
|
|
|
|
.BI " const struct iovec *" lvec ,
|
|
|
|
.br
|
|
|
|
.BI " unsigned long " liovcnt ,
|
|
|
|
.br
|
|
|
|
.BI " const struct iovec *" rvec ,
|
|
|
|
.br
|
|
|
|
.BI " unsigned long " riovcnt ,
|
|
|
|
.br
|
|
|
|
.BI " unsigned long " flags ");"
|
|
|
|
.SH DESCRIPTION
|
|
|
|
The
|
|
|
|
.BR process_vm_readv ()
|
2012-03-19 20:33:53 +00:00
|
|
|
function reads from the memory locations described by the
|
|
|
|
.I riovcnt
|
|
|
|
buffers from
|
|
|
|
.I rvec
|
|
|
|
in the process identified by
|
|
|
|
.I pid
|
|
|
|
into
|
|
|
|
.I liovcnt
|
|
|
|
buffers described by
|
|
|
|
.I lvec
|
|
|
|
in the current process.
|
2012-03-19 19:07:13 +00:00
|
|
|
|
|
|
|
The
|
|
|
|
.BR process_vm_writev ()
|
|
|
|
function is the inverse of
|
2012-03-19 20:33:53 +00:00
|
|
|
.BR process_vm_readv ()\(emit
|
|
|
|
writes into the memory locations described by
|
|
|
|
.I riovcnt
|
|
|
|
buffers
|
|
|
|
from
|
|
|
|
.I rvec
|
|
|
|
in the process identified by
|
|
|
|
.I pid
|
|
|
|
into
|
|
|
|
.I liovcnt
|
|
|
|
buffers described by
|
|
|
|
.I lvec
|
|
|
|
in the current process.
|
2012-03-19 19:07:13 +00:00
|
|
|
|
2012-03-19 20:33:53 +00:00
|
|
|
The count values might be individually capped according to
|
|
|
|
.BR UIO_MAXIOV .
|
2012-03-19 19:07:13 +00:00
|
|
|
If the Linux kernel is capped at smaller values, the C library will take care
|
|
|
|
of emulating the limit it exposes (if it is bigger) so the user only needs to
|
|
|
|
care about that (what the C library defines).
|
|
|
|
|
2012-03-19 20:33:53 +00:00
|
|
|
The pointers
|
|
|
|
.I lvec
|
|
|
|
and
|
|
|
|
.I rvec
|
|
|
|
point to an array of
|
|
|
|
.I iovec
|
|
|
|
structures, defined in
|
2012-03-19 19:07:13 +00:00
|
|
|
.IR <sys/uio.h>
|
|
|
|
as:
|
|
|
|
|
|
|
|
.in +4n
|
|
|
|
.nf
|
|
|
|
struct iovec {
|
|
|
|
void *iov_base; /* Starting address */
|
|
|
|
size_t iov_len; /* Number of bytes to transfer */
|
|
|
|
};
|
|
|
|
.fi
|
|
|
|
.in
|
|
|
|
|
|
|
|
Buffers are processed in array order. This means that
|
|
|
|
.BR process_vm_readv ()
|
2012-03-19 20:33:53 +00:00
|
|
|
completely fills
|
|
|
|
.I lvec[0]
|
|
|
|
before proceeding to
|
|
|
|
.IR lvec[1] ,
|
|
|
|
and
|
|
|
|
so on.
|
|
|
|
Along those lines,
|
|
|
|
.I rvec[0]
|
|
|
|
is completely read before proceeding to
|
|
|
|
.I rvec[1]
|
|
|
|
and so on.
|
2012-03-19 19:07:13 +00:00
|
|
|
|
|
|
|
Similarly,
|
|
|
|
.BR process_vm_writev ()
|
2012-03-19 20:33:53 +00:00
|
|
|
writes out the entire contents of
|
|
|
|
.I lvec[0]
|
|
|
|
before proceeding to
|
|
|
|
.IR lvec[1] ,
|
|
|
|
and it completely fills
|
|
|
|
.I revc[0]
|
|
|
|
before proceeding
|
|
|
|
to
|
|
|
|
.IR rvec[1] .
|
2012-03-19 19:07:13 +00:00
|
|
|
|
2012-03-19 20:33:53 +00:00
|
|
|
The lengths of
|
|
|
|
.I rvec[i]
|
|
|
|
and
|
|
|
|
.I lvec[i]
|
|
|
|
do not have to be the same.
|
2012-03-19 19:07:13 +00:00
|
|
|
This allows you to split a single local buffer into multiple remote buffers,
|
|
|
|
or vice versa.
|
|
|
|
|
|
|
|
The data transfers of
|
|
|
|
.BR process_vm_readv ()
|
|
|
|
and
|
|
|
|
.BR process_vm_writev ()
|
|
|
|
are not guaranteed to be atomic in any way.
|
|
|
|
|
|
|
|
The counts and vectors are checked before doing any transfers. So if the
|
|
|
|
counts are too big, or the vectors invalid, or the addresses refer to regions
|
|
|
|
that are inaccessible, none of the previous vectors will be processed and an
|
|
|
|
error will be returned immediately. Keep this in mind when attempting to
|
|
|
|
extract data of unknown length (such as C strings which are NULL terminated)
|
|
|
|
by avoiding spanning memory pages (typically 4KiB).
|
|
|
|
|
2012-03-19 20:33:53 +00:00
|
|
|
The
|
|
|
|
.I flags
|
|
|
|
parameter is currently unused and must be set to 0.
|
2012-03-19 19:07:13 +00:00
|
|
|
|
|
|
|
In order to read or write from or to another process you must have
|
|
|
|
the capability
|
|
|
|
.BR CAP_SYS_PTRACE
|
|
|
|
or have the same uid and gid of the target process. The permission
|
|
|
|
required is exactly the same as being able to perform a
|
|
|
|
.BR ptrace (2)
|
|
|
|
ptrace with
|
|
|
|
.BR PTRACE_ATTACH
|
|
|
|
on the target process.
|
|
|
|
.SH "RETURN VALUE"
|
|
|
|
On success,
|
|
|
|
.BR process_vm_readv ()
|
|
|
|
returns the number of bytes read while
|
|
|
|
.BR process_vm_writev ()
|
|
|
|
returns the number of bytes written.
|
|
|
|
|
|
|
|
On error, the number of bytes read or written is returned, or -1 is
|
|
|
|
returned if it was unable to read/write any bytes; in either case,
|
|
|
|
.I errno
|
|
|
|
is set appropriately.
|
|
|
|
.SH ERRORS
|
|
|
|
.TP
|
|
|
|
.B EINVAL
|
2012-03-19 20:33:53 +00:00
|
|
|
The sum of the
|
|
|
|
.I iov_len
|
|
|
|
values of either
|
|
|
|
.I lvec
|
|
|
|
or
|
|
|
|
.I rvec
|
|
|
|
overflows a
|
|
|
|
.I ssize_t
|
|
|
|
value.
|
2012-03-19 19:07:13 +00:00
|
|
|
.TP
|
|
|
|
.B EINVAL
|
2012-03-19 20:33:53 +00:00
|
|
|
The value of the
|
|
|
|
.I flags
|
|
|
|
parameter is not 0.
|
2012-03-19 19:07:13 +00:00
|
|
|
.TP
|
|
|
|
.B EFAULT
|
2012-03-19 20:33:53 +00:00
|
|
|
The memory described by
|
|
|
|
.I lvec
|
|
|
|
is outside your accessible address space.
|
2012-03-19 19:07:13 +00:00
|
|
|
.TP
|
|
|
|
.B EFAULT
|
2012-03-19 20:33:53 +00:00
|
|
|
The memory described by
|
|
|
|
.I rvec
|
|
|
|
is outside the accessible address space
|
|
|
|
of process
|
|
|
|
.IR pid .
|
2012-03-19 19:07:13 +00:00
|
|
|
.TP
|
|
|
|
.B ENOMEM
|
|
|
|
Out of memory.
|
|
|
|
.TP
|
|
|
|
.B EPERM
|
|
|
|
.RB ( process_vm_readv ())
|
2012-03-19 20:33:53 +00:00
|
|
|
You do not have permission to read from process
|
|
|
|
.IR pid .
|
|
|
|
|
2012-03-19 19:07:13 +00:00
|
|
|
.TP
|
|
|
|
.B EPERM
|
|
|
|
.RB ( process_vm_writev ())
|
2012-03-19 20:33:53 +00:00
|
|
|
You do not have permission to write to process
|
|
|
|
.IR pid .
|
2012-03-19 19:07:13 +00:00
|
|
|
.TP
|
|
|
|
.B ESRCH
|
2012-03-19 20:33:53 +00:00
|
|
|
.I pid
|
|
|
|
does not exist.
|
2012-03-19 19:07:13 +00:00
|
|
|
.SH VERSIONS
|
|
|
|
These functions are available since glibc 2.15 and Linux 3.2.
|
|
|
|
.SH "CONFORMING TO"
|
|
|
|
These functions are Linux extensions, not in C or POSIX.
|
|
|
|
.SH EXAMPLE
|
2012-03-19 20:33:53 +00:00
|
|
|
The following code sample demonstrates the use of
|
|
|
|
.BR process_vm_readv ().
|
2012-03-19 19:07:13 +00:00
|
|
|
It reads 20 bytes at the address 0x10000 from the process with PID 10
|
2012-03-19 20:33:53 +00:00
|
|
|
and writes the first 10 bytes into
|
|
|
|
.I buf1
|
|
|
|
and the second 10 bytes into
|
|
|
|
.IR buf2 .
|
2012-03-19 19:07:13 +00:00
|
|
|
.sp
|
|
|
|
.nf
|
|
|
|
#include <sys/uio.h>
|
|
|
|
|
2012-03-19 20:36:56 +00:00
|
|
|
int
|
|
|
|
main(void)
|
2012-03-19 19:07:13 +00:00
|
|
|
{
|
|
|
|
struct iovec local[2];
|
|
|
|
struct iovec remote[1];
|
|
|
|
char buf1[10];
|
|
|
|
char buf2[10];
|
|
|
|
ssize_t nread;
|
|
|
|
pid_t pid = 10; /* PID of target process */
|
|
|
|
|
|
|
|
local[0].iov_base = buf1;
|
|
|
|
local[0].iov_len = 10;
|
|
|
|
local[1].iov_base = buf2;
|
|
|
|
local[1].iov_len = 10;
|
2012-03-19 20:36:56 +00:00
|
|
|
remote[0].iov_base = (void *) 0x10000;
|
2012-03-19 19:07:13 +00:00
|
|
|
remote[1].iov_len = 20;
|
|
|
|
|
|
|
|
nread = process_vm_readv(pid, local, 2, remote, 1, 0);
|
|
|
|
if (nread != 20)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
.fi
|
|
|
|
.SH "SEE ALSO"
|
|
|
|
.BR readv (2),
|
|
|
|
.BR writev (2)
|