summaryrefslogtreecommitdiffstats
path: root/usr.bin/truss
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2015-08-05 18:14:01 +0000
committerjhb <jhb@FreeBSD.org>2015-08-05 18:14:01 +0000
commit59e4fce94f13614783df7909d79d03d912a6ed53 (patch)
tree2d33d92664418fd6bf47d7fe345d494d0471b77f /usr.bin/truss
parentb62aca35b9a9c7ec66ca358ddb923a71913dd30c (diff)
downloadFreeBSD-src-59e4fce94f13614783df7909d79d03d912a6ed53.zip
FreeBSD-src-59e4fce94f13614783df7909d79d03d912a6ed53.tar.gz
Rework get_string() to make it more robust when fetching strings of unknown
length. In particular, instead of blinding fetching 1k blocks, do an initial fetch up to the end of the current page followed by page-sized fetches up to the maximum size. Previously if the 1k buffer crossed a page boundary and the second page was not valid, the entire operation would fail.
Diffstat (limited to 'usr.bin/truss')
-rw-r--r--usr.bin/truss/syscalls.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index aa4bac5..b758ddb 100644
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -539,44 +539,56 @@ get_struct(pid_t pid, void *offset, void *buf, int len)
}
#define MAXSIZE 4096
-#define BLOCKSIZE 1024
+
/*
* get_string
* Copy a string from the process. Note that it is
* expected to be a C string, but if max is set, it will
* only get that much.
*/
-
static char *
-get_string(pid_t pid, void *offset, int max)
+get_string(pid_t pid, void *addr, int max)
{
struct ptrace_io_desc iorequest;
- char *buf;
- int diff, i, size, totalsize;
+ char *buf, *nbuf;
+ size_t offset, size, totalsize;
- diff = 0;
- totalsize = size = max ? (max + 1) : BLOCKSIZE;
+ offset = 0;
+ if (max)
+ size = max + 1;
+ else {
+ /* Read up to the end of the current page. */
+ size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
+ if (size > MAXSIZE)
+ size = MAXSIZE;
+ }
+ totalsize = size;
buf = malloc(totalsize);
if (buf == NULL)
return (NULL);
for (;;) {
- diff = totalsize - size;
iorequest.piod_op = PIOD_READ_D;
- iorequest.piod_offs = (char *)offset + diff;
- iorequest.piod_addr = buf + diff;
+ iorequest.piod_offs = (char *)addr + offset;
+ iorequest.piod_addr = buf + offset;
iorequest.piod_len = size;
if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
free(buf);
return (NULL);
}
- for (i = 0 ; i < size; i++) {
- if (buf[diff + i] == '\0')
+ if (memchr(buf + offset, '\0', size) != NULL)
+ return (buf);
+ offset += size;
+ if (totalsize < MAXSIZE && max == 0) {
+ size = MAXSIZE - totalsize;
+ if (size > PAGE_SIZE)
+ size = PAGE_SIZE;
+ nbuf = realloc(buf, totalsize + size);
+ if (nbuf == NULL) {
+ buf[totalsize - 1] = '\0';
return (buf);
- }
- if (totalsize < MAXSIZE - BLOCKSIZE && max == 0) {
- totalsize += BLOCKSIZE;
- buf = realloc(buf, totalsize);
- size = BLOCKSIZE;
+ }
+ buf = nbuf;
+ totalsize += size;
} else {
buf[totalsize - 1] = '\0';
return (buf);
OpenPOWER on IntegriCloud