From: Dmitry V. Levin Date: Fri, 29 Jan 2016 01:51:54 +0000 (+0000) Subject: Fixed decoding of mincore syscall's last argument X-Git-Tag: v4.12~614 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dfea1da0e6361e80b66a9ef7d9e0f35518a7629c;p=strace Fixed decoding of mincore syscall's last argument * mem.c (SYS_FUNC(mincore)): Print only those bytes of the vector that were written by the kernel. * NEWS: Mention this fix. * tests/mincore.c: New file. * tests/mincore.test: New test. * tests/Makefile.am (check_PROGRAMS): Add mincore. (TESTS): Add mincore.test. * tests/.gitignore: Add mincore. --- diff --git a/NEWS b/NEWS index a7520d66..b9ed032b 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ Noteworthy changes in release ?.?? (????-??-??) (addresses Debian bug #485979 and Fedora bug #1298294). * Fixed decoding and dumping of readv syscall in case of short read. * Fixed dumping of recvmsg and recvmmsg syscalls in case of short read. + * Fixed decoding of mincore syscall's last argument. Noteworthy changes in release 4.11 (2015-12-21) =============================================== diff --git a/mem.c b/mem.c index 37c7daba..28b49c97 100644 --- a/mem.c +++ b/mem.c @@ -264,15 +264,18 @@ SYS_FUNC(mincore) printaddr(tcp->u_arg[0]); tprintf(", %lu, ", tcp->u_arg[1]); } else { - unsigned long i, len; - char *vec = NULL; + const unsigned long page_size = get_pagesize(); + const unsigned long page_mask = page_size - 1; + unsigned long len = tcp->u_arg[1]; + unsigned char *vec = NULL; - len = tcp->u_arg[1]; + len = len / page_size + (len & page_mask ? 1 : 0); if (syserror(tcp) || !verbose(tcp) || !tcp->u_arg[2] || !(vec = malloc(len)) || umoven(tcp, tcp->u_arg[2], len, vec) < 0) printaddr(tcp->u_arg[2]); else { + unsigned long i; tprints("["); for (i = 0; i < len; i++) { if (abbrev(tcp) && i >= max_strlen) { diff --git a/tests/.gitignore b/tests/.gitignore index 207a9b2e..10214d35 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -50,6 +50,7 @@ lstat lstat64 membarrier memfd_create +mincore mlock2 mmap mmap64 diff --git a/tests/Makefile.am b/tests/Makefile.am index f6345836..e31be34e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -96,6 +96,7 @@ check_PROGRAMS = \ lstat64 \ membarrier \ memfd_create \ + mincore \ mlock2 \ mmap \ mmap64 \ @@ -235,6 +236,7 @@ TESTS = \ lstat64.test \ membarrier.test \ memfd_create.test \ + mincore.test \ mlock2.test \ mmap.test \ mmap64.test \ diff --git a/tests/mincore.c b/tests/mincore.c new file mode 100644 index 00000000..d9cbbd4c --- /dev/null +++ b/tests/mincore.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" +#include +#include + +#define DEFAULT_STRLEN 32 + +static void +test_mincore(const unsigned int pages) +{ + const size_t size = pages * get_page_size(); + char *addr = tail_alloc(size); + unsigned char *vec = tail_alloc(pages); + unsigned int i; + + if (mincore(addr, size, vec)) + perror_msg_and_skip("mincore"); + printf("mincore(%p, %zu, [", addr, size); + for (i = 0; i < pages; ++i) { + if (i >= DEFAULT_STRLEN) { + printf("..."); + break; + } + printf("%u", vec[i] & 1); + } + puts("]) = 0"); +} + +int main(void) +{ + test_mincore(1); + test_mincore(2); + test_mincore(DEFAULT_STRLEN + 1); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/mincore.test b/tests/mincore.test new file mode 100755 index 00000000..9a6a6865 --- /dev/null +++ b/tests/mincore.test @@ -0,0 +1,11 @@ +#!/bin/sh + +# Check mincore syscall decoding. + +. "${srcdir=.}/init.sh" + +run_prog > /dev/null +OUT="$LOG.out" +run_strace -a22 -emincore $args > "$OUT" +match_diff "$LOG" "$OUT" +rm -f "$OUT"