Add support for process_vm_readv and process_vm_writev system calls.

Patch from Lénaïc Huard to fix BZ#292995.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12374
This commit is contained in:
Tom Hughes 2012-02-10 09:39:37 +00:00
parent 7104ded0a5
commit 74eb6fb3b4
13 changed files with 270 additions and 7 deletions

View File

@ -1683,6 +1683,8 @@ AC_CHECK_FUNCS([ \
strstr \
syscall \
utimensat \
process_vm_readv \
process_vm_writev \
])
# AC_CHECK_LIB adds any library found to the variable LIBS, and links these

View File

@ -263,6 +263,10 @@ DECL_TEMPLATE(linux, sys_delete_module);
// Linux-specific (oprofile-related)
DECL_TEMPLATE(linux, sys_lookup_dcookie); // (*/32/64) L
// Linux-specific (new in Linux 3.2)
DECL_TEMPLATE(linux, sys_process_vm_readv);
DECL_TEMPLATE(linux, sys_process_vm_writev);
/* ---------------------------------------------------------------------
Wrappers for sockets and ipc-ery. These are split into standalone
procedures because x86-linux hides them inside multiplexors

View File

@ -1423,7 +1423,10 @@ static SyscallTableEntry syscall_table[] = {
// LINX_(__NR_syncfs, sys_ni_syscall), // 306
// LINX_(__NR_sendmmsg, sys_ni_syscall), // 307
// LINX_(__NR_setns, sys_ni_syscall), // 308
LINXY(__NR_getcpu, sys_getcpu) // 309
LINXY(__NR_getcpu, sys_getcpu), // 309
LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 310
LINX_(__NR_process_vm_writev, sys_process_vm_writev) // 311
};
SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )

View File

@ -3471,6 +3471,73 @@ PRE(sys_pwritev)
}
}
/* ---------------------------------------------------------------------
process_vm_{read,write}v wrappers
------------------------------------------------------------------ */
PRE(sys_process_vm_readv)
{
PRINT("sys_process_vm_readv ( %lu, %#lx, %lu, %#lx, %lu, %lu )",
ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
PRE_REG_READ6(ssize_t, "process_vm_readv",
vki_pid_t, pid,
const struct iovec *, lvec,
unsigned long, liovcnt,
const struct iovec *, rvec,
unsigned long, riovcnt,
unsigned long, flags);
PRE_MEM_READ( "process_vm_readv(lvec)",
ARG2, ARG3 * sizeof(struct vki_iovec) );
PRE_MEM_READ( "process_vm_readv(rvec)",
ARG4, ARG5 * sizeof(struct vki_iovec) );
if (ARG2 != 0) {
/* TODO: Don't do any of the following if lvec is invalid */
const struct vki_iovec *vec = (const struct vki_iovec *)ARG2;
UInt i;
for (i = 0; i < ARG3; i++)
PRE_MEM_WRITE( "process_vm_readv(lvec[...])",
(Addr)vec[i].iov_base, vec[i].iov_len );
}
}
POST(sys_process_vm_readv)
{
const struct vki_iovec *vec = (const struct vki_iovec *)ARG2;
UInt remains = RES;
UInt i;
for (i = 0; i < ARG3; i++) {
UInt nReadThisBuf = vec[i].iov_len <= remains ?
vec[i].iov_len : remains;
POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
remains -= nReadThisBuf;
}
}
PRE(sys_process_vm_writev)
{
PRINT("sys_process_vm_writev ( %lu, %#lx, %lu, %#lx, %lu, %lu )",
ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
PRE_REG_READ6(ssize_t, "process_vm_writev",
vki_pid_t, pid,
const struct iovec *, lvec,
unsigned long, liovcnt,
const struct iovec *, rvec,
unsigned long, riovcnt,
unsigned long, flags);
PRE_MEM_READ( "process_vm_writev(lvec)",
ARG2, ARG3 * sizeof(struct vki_iovec) );
PRE_MEM_READ( "process_vm_writev(rvec)",
ARG4, ARG5 * sizeof(struct vki_iovec) );
if (ARG2 != 0) {
/* TODO: Don't do any of the following if lvec is invalid */
const struct vki_iovec *vec = (const struct vki_iovec *)ARG2;
UInt i;
for (i = 0; i < ARG3; i++)
PRE_MEM_READ( "process_vm_writev(lvec[...])",
(Addr)vec[i].iov_base, vec[i].iov_len );
}
}
/* ---------------------------------------------------------------------
key retention service wrappers
------------------------------------------------------------------ */

View File

@ -1827,7 +1827,10 @@ static SyscallTableEntry syscall_table[] = {
LINXY(__NR_perf_event_open, sys_perf_event_open), // 319
LINXY(__NR_preadv, sys_preadv), // 320
LINX_(__NR_pwritev, sys_pwritev), // 321
LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) // 322
LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 322
LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 351
LINX_(__NR_process_vm_writev, sys_process_vm_writev) // 352
};
SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )

View File

@ -1467,7 +1467,10 @@ static SyscallTableEntry syscall_table[] = {
LINXY(__NR_perf_event_open, sys_perf_event_open), // 319
LINXY(__NR_preadv, sys_preadv), // 320
LINX_(__NR_pwritev, sys_pwritev), // 321
LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) // 322
LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 322
LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 351
LINX_(__NR_process_vm_writev, sys_process_vm_writev) // 352
};
SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )

View File

@ -2223,7 +2223,7 @@ static SyscallTableEntry syscall_table[] = {
// LINX_(__NR_fanotify_init, sys_ni_syscall), // 338
// LINX_(__NR_fanotify_mark, sys_ni_syscall), // 339
LINXY(__NR_prlimit64, sys_prlimit64) // 340
LINXY(__NR_prlimit64, sys_prlimit64), // 340
// LINX_(__NR_name_to_handle_at, sys_ni_syscall), // 341
// LINX_(__NR_open_by_handle_at, sys_ni_syscall), // 342
// LINX_(__NR_clock_adjtime, sys_ni_syscall), // 343
@ -2231,6 +2231,8 @@ static SyscallTableEntry syscall_table[] = {
// LINX_(__NR_sendmmsg, sys_ni_syscall), // 345
// LINX_(__NR_setns, sys_ni_syscall), // 346
LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 347
LINX_(__NR_process_vm_writev, sys_process_vm_writev) // 348
};
SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )

View File

@ -1257,6 +1257,14 @@ int main(void)
GO(__NR_epoll_create1, "1s 0m");
SY(__NR_epoll_create1, x0); SUCC_OR_FAIL;
// __NR_process_vm_readv 347
GO(__NR_process_vm_readv, "6s 2m");
SY(__NR_process_vm_readv, x0, x0, x0+1, x0, x0+1, x0); FAIL;
// __NR_process_vm_writev 348
GO(__NR_process_vm_writev, "6s 2m");
SY(__NR_process_vm_writev, x0, x0, x0+1, x0, x0+1, x0); FAIL;
// no such syscall...
GO(9999, "1e");
SY(9999); FAIL;

View File

@ -3977,6 +3977,80 @@ Syscall param epoll_create1(flags) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1258)
-----------------------------------------------------
347:__NR_process_vm_readv 6s 2m
-----------------------------------------------------
Syscall param process_vm_readv(pid) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1262)
Syscall param process_vm_readv(lvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1262)
Syscall param process_vm_readv(liovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1262)
Syscall param process_vm_readv(rvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1262)
Syscall param process_vm_readv(riovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1262)
Syscall param process_vm_readv(flags) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1262)
Syscall param process_vm_readv(lvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1262)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
Syscall param process_vm_readv(rvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1262)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
348:__NR_process_vm_writev 6s 2m
-----------------------------------------------------
Syscall param process_vm_writev(pid) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
Syscall param process_vm_writev(lvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
Syscall param process_vm_writev(liovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
Syscall param process_vm_writev(rvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
Syscall param process_vm_writev(riovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
Syscall param process_vm_writev(flags) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
Syscall param process_vm_writev(lvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1266)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
Syscall param process_vm_writev(rvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1266)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
9999: 9999 1e
-----------------------------------------------------
@ -3990,5 +4064,5 @@ it at http://valgrind.org/support/bug_reports.html.
-----------------------------------------------------
Syscall param exit(status) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1266)
by 0x........: main (scalar.c:1274)

View File

@ -160,7 +160,8 @@ EXTRA_DIST = \
threadederrno.vgtest \
timestamp.stderr.exp timestamp.vgtest \
tls.vgtest tls.stderr.exp tls.stdout.exp \
vgprintf.stderr.exp vgprintf.vgtest
vgprintf.stderr.exp vgprintf.vgtest \
process_vm_readv_writev.stderr.exp process_vm_readv_writev.vgtest
check_PROGRAMS = \
ansi args \
@ -198,7 +199,8 @@ check_PROGRAMS = \
valgrind_cpp_test \
vgprintf \
coolo_sigaction \
gxx304
gxx304 \
process_vm_readv_writev
# DDD:
# - manythreads and thread-exits have lots of this:

View File

@ -0,0 +1,92 @@
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/uio.h>
static int status = EXIT_SUCCESS;
#ifdef HAVE_PROCESS_VM_READV
static void test_process_vm_readv()
{
char lbuf[] = "123456";
char rbuf[] = "ABCDEF";
struct iovec lvec[2];
struct iovec rvec[2];
lvec[0].iov_base = lbuf + 1;
lvec[0].iov_len = 1;
lvec[1].iov_base = lbuf + 3;
lvec[1].iov_len = 2;
rvec[0].iov_base = rbuf + 1;
rvec[0].iov_len = 2;
rvec[1].iov_base = rbuf + 4;
rvec[1].iov_len = 1;
if (process_vm_readv(getpid(),
lvec, 2,
rvec, 2,
0 ) < 0 ) {
perror("process_vm_readv");
status = EXIT_FAILURE;
}
if (strcmp(lbuf, "1B3CE6") != 0) {
fprintf(stderr, "Expected: \"1B3CE6\"; Got: \"%s\"\n", lbuf);
status = EXIT_FAILURE;
}
}
#endif /* defined( HAVE_PROCESS_VM_READV ) */
#ifdef HAVE_PROCESS_VM_WRITEV
static void test_process_vm_writev()
{
char lbuf[] = "123456";
char rbuf[] = "ABCDEF";
struct iovec lvec[2];
struct iovec rvec[2];
lvec[0].iov_base = lbuf + 1;
lvec[0].iov_len = 1;
lvec[1].iov_base = lbuf + 3;
lvec[1].iov_len = 2;
rvec[0].iov_base = rbuf + 1;
rvec[0].iov_len = 2;
rvec[1].iov_base = rbuf + 4;
rvec[1].iov_len = 1;
if (process_vm_writev(getpid(),
lvec, 2,
rvec, 2,
0 ) < 0 ) {
perror("process_vm_writev");
status = EXIT_FAILURE;
}
if (strcmp(rbuf, "A24D5F") != 0) {
fprintf(stderr, "Expected: \"A24D5F\"; Got: \"%s\"\n", rbuf);
status = EXIT_FAILURE;
}
}
#endif /* defined( HAVE_PROCESS_VM_WRITEV ) */
int main(int argc, char *argv[])
{
#ifdef HAVE_PROCESS_VM_READV
test_process_vm_readv();
#endif
#ifdef HAVE_PROCESS_VM_WRITEV
test_process_vm_writev();
#endif
return status;
}

View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1 @@
prog: process_vm_readv_writev