summaryrefslogtreecommitdiff
path: root/system.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2013-02-08 19:10:07 -0500
committerDmitry V. Levin <ldv@altlinux.org>2013-02-09 01:39:43 +0000
commit0cf04b6595a951df7671eafef5f9e7a114a6c691 (patch)
treea0d7cab133e269b2ccdb5f2f85a6cde58e749571 /system.c
parent99aa181ebcee3f6ae4f8eb83c719cc64cc5a09ec (diff)
downloadstrace-0cf04b6595a951df7671eafef5f9e7a114a6c691.tar.gz
strace-0cf04b6595a951df7671eafef5f9e7a114a6c691.tar.bz2
strace-0cf04b6595a951df7671eafef5f9e7a114a6c691.tar.xz
Fix decoding of sysctl() when oldval fields are NULL
If you call glibc's syscall wrapper like so: static int name[] = { CTL_NET, NET_IPV4, NET_IPV4_LOCAL_PORT_RANGE }; int buffer[2] = { 32768, 61000 }; size_t size = sizeof(buffer); sysctl(name, 3, 0, 0, buffer, size); (note that oldval/oldlenp are NULL). The current strace code complains like so: _sysctl({{CTL_NET, NET_IPV4, NET_IPV4_LOCAL_PORT_RANGE, 38}, 3, process_vm_readv: Bad address (nil), 0, 0x7fffe23c3960, 8}) = -1 EACCES (Permission denied) Since passing NULL for the old values is valid, handle that explicitly. This also simplifies the code a bit by splitting up the handling of the new and old args so that we only handle the new args once. Now the output looks like: _sysctl({{CTL_NET, NET_IPV4, NET_IPV4_LOCAL_PORT_RANGE, 38}, 3, NULL, 0, 0x7fff8c0c91b0, 8) = -1 EACCES (Permission denied) * system.c (sys_sysctl): Check if info.oldval is NULL first. Move the processing of oldlen/info.newval/info.newlen out so they always get executed. Fix the format strings so we use %lu for unsigned long rather than a mix of %ld and %lu. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'system.c')
-rw-r--r--system.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/system.c b/system.c
index bc284aa..3d41006 100644
--- a/system.c
+++ b/system.c
@@ -954,32 +954,32 @@ sys_sysctl(struct tcb *tcp)
tprintf("}, %d, ", info.nlen);
} else {
size_t oldlen = 0;
- if (umove(tcp, (long)info.oldlenp, &oldlen) >= 0
- && info.nlen >= 2
- && ((name[0] == CTL_KERN
- && (name[1] == KERN_OSRELEASE
- || name[1] == KERN_OSTYPE
+ if (info.oldval == NULL) {
+ tprints("NULL");
+ } else if (umove(tcp, (long)info.oldlenp, &oldlen) >= 0
+ && info.nlen >= 2
+ && ((name[0] == CTL_KERN
+ && (name[1] == KERN_OSRELEASE
+ || name[1] == KERN_OSTYPE
#ifdef KERN_JAVA_INTERPRETER
- || name[1] == KERN_JAVA_INTERPRETER
+ || name[1] == KERN_JAVA_INTERPRETER
#endif
#ifdef KERN_JAVA_APPLETVIEWER
- || name[1] == KERN_JAVA_APPLETVIEWER
+ || name[1] == KERN_JAVA_APPLETVIEWER
#endif
- )))) {
+ )))) {
printpath(tcp, (size_t)info.oldval);
- tprintf(", %lu, ", (unsigned long)oldlen);
- if (info.newval == 0)
- tprints("NULL");
- else if (syserror(tcp))
- tprintf("%p", info.newval);
- else
- printpath(tcp, (size_t)info.newval);
- tprintf(", %ld}", (unsigned long)info.newlen);
} else {
- tprintf("%p, %ld, %p, %ld}",
- info.oldval, (unsigned long)oldlen,
- info.newval, (unsigned long)info.newlen);
+ tprintf("%p", info.oldval);
}
+ tprintf(", %lu, ", (unsigned long)oldlen);
+ if (info.newval == NULL)
+ tprints("NULL");
+ else if (syserror(tcp))
+ tprintf("%p", info.newval);
+ else
+ printpath(tcp, (size_t)info.newval);
+ tprintf(", %lu", (unsigned long)info.newlen);
}
free(name);