From owner-svn-src-head@freebsd.org Thu Aug 20 14:33:31 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2BE7C9BF4F0; Thu, 20 Aug 2015 14:33:31 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 102511084; Thu, 20 Aug 2015 14:33:31 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t7KEXUhU076279; Thu, 20 Aug 2015 14:33:30 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t7KEXUGT076278; Thu, 20 Aug 2015 14:33:30 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201508201433.t7KEXUGT076278@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Thu, 20 Aug 2015 14:33:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r286962 - head/usr.bin/truss X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Aug 2015 14:33:31 -0000 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, ", "); + break; + } + i = 0; + } } - tmp2 += sprintf(tmp2, "]"); + fputs(" ]", fp); break; } #ifdef __LP64__