Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Aug 2015 14:33:30 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286962 - head/usr.bin/truss
Message-ID:  <201508201433.t7KEXUGT076278@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Aug 20 14:33:30 2015
New Revision: 286962
URL: https://svnweb.freebsd.org/changeset/base/286962

Log:
  Rework the argv and env string fetching for execve to be more robust.
  Before truss would fetch 100 string pointers and happily walk off the end
  of the array if it never found a NULL.  This also means for a short argv
  list it could fail entirely if the 100 string pointers spanned into an
  unmapped page.
  
  Instead, fetch page-aligned blocks of string pointers in a loop fetching
  each string until a NULL is found.
  
  While here, make use of the open memstream file descriptor instead of
  allocating a temporary array.  This allows us to fetch each string once
  instead of twice.

Modified:
  head/usr.bin/truss/syscalls.c

Modified: head/usr.bin/truss/syscalls.c
==============================================================================
--- head/usr.bin/truss/syscalls.c	Thu Aug 20 14:03:03 2015	(r286961)
+++ head/usr.bin/truss/syscalls.c	Thu Aug 20 14:33:30 2015	(r286962)
@@ -913,36 +913,54 @@ print_arg(struct syscall_args *sc, unsig
 		break;
 	}
 	case StringArray: {
-		int num, size, i;
-		char *tmp2;
+		uintptr_t addr;
+		union {
+			char *strarray[0];
+			char buf[PAGE_SIZE];
+		} u;
 		char *string;
-		char *strarray[100];	/* XXX This is ugly. */
+		size_t len;
+		int first, i;
 
-		if (get_struct(pid, (void *)args[sc->offset],
-		    (void *)&strarray, sizeof(strarray)) == -1)
-			err(1, "get_struct %p", (void *)args[sc->offset]);
-		num = 0;
-		size = 0;
-
-		/* Find out how large of a buffer we'll need. */
-		while (strarray[num] != NULL) {
-			string = get_string(pid, (void*)strarray[num], 0);
-			size += strlen(string);
-			free(string);
-			num++;
+		/*
+		 * Read a page of pointers at a time.  Punt if the top-level
+		 * pointer is not aligned.  Note that the first read is of
+		 * a partial page.
+		 */
+		addr = args[sc->offset];
+		if (addr % sizeof(char *) != 0) {
+			fprintf(fp, "0x%lx", args[sc->offset]);
+			break;
+		}
+
+		len = PAGE_SIZE - (addr & PAGE_MASK);
+		if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
+			fprintf(fp, "0x%lx", args[sc->offset]);
+			break;
 		}
-		size += 4 + (num * 4);
-		tmp = (char *)malloc(size);
-		tmp2 = tmp;
-
-		tmp2 += sprintf(tmp2, " [");
-		for (i = 0; i < num; i++) {
-			string = get_string(pid, (void*)strarray[i], 0);
-			tmp2 += sprintf(tmp2, " \"%s\"%c", string,
-			    (i + 1 == num) ? ' ' : ',');
+
+		fputc('[', fp);
+		first = 1;
+		i = 0;
+		while (u.strarray[i] != NULL) {
+			string = get_string(pid, u.strarray[i], 0);
+			fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
 			free(string);
+			first = 0;
+
+			i++;
+			if (i == len / sizeof(char *)) {
+				addr += len;
+				len = PAGE_SIZE;
+				if (get_struct(pid, (void *)addr, u.buf, len) ==
+				    -1) {
+					fprintf(fp, ", <inval>");
+					break;
+				}
+				i = 0;
+			}
 		}
-		tmp2 += sprintf(tmp2, "]");
+		fputs(" ]", fp);
 		break;
 	}
 #ifdef __LP64__



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508201433.t7KEXUGT076278>