]> granicus.if.org Git - strace/commitdiff
umovestr: fix short read bug
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 31 Mar 2015 18:52:57 +0000 (18:52 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 31 Mar 2015 20:52:41 +0000 (20:52 +0000)
* util.c (umovestr): Check the right address.
* tests/umovestr.c: New file.
* tests/umovestr2.c: Likewise.
* tests/umovestr.expected: Likewise.
* tests/umovestr.test: New test.
* tests/umovestr2.test: Likewise.
* tests/Makefile.am (check_PROGRAMS): Add umovestr and umovestr2.
(TESTS): Add umovestr.test and umovestr2.test.
(EXTRA_DIST): Add umovestr.expected.
* tests/.gitignore: Add umovestr and umovestr2.

Reported-by: Josef T. Burger <bolo@cs.wisc.edu>
tests/.gitignore
tests/Makefile.am
tests/umovestr.c [new file with mode: 0644]
tests/umovestr.expected [new file with mode: 0644]
tests/umovestr.test [new file with mode: 0755]
tests/umovestr2.c [new file with mode: 0644]
tests/umovestr2.test [new file with mode: 0755]
util.c

index 38b805988d14d35a41300e0fc14f047720a83bd1..6903a5cef7959fca31529a9a351189e32c867642 100644 (file)
@@ -28,6 +28,8 @@ uid
 uid16
 uid32
 uio
+umovestr
+umovestr2
 unix-pair-send-recv
 *.log
 *.log.*
index 62e5d667c91ba31b94347f5e31031e465ba6e9aa..e5dae02a8740733d198ed9cd1e9be8f74d716771 100644 (file)
@@ -37,6 +37,8 @@ check_PROGRAMS = \
        uid16 \
        uid32 \
        uio \
+       umovestr \
+       umovestr2 \
        unix-pair-send-recv
 
 mmap64_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
@@ -78,6 +80,8 @@ TESTS = \
        pipe.test \
        pc.test \
        sun_path.test \
+       umovestr.test \
+       umovestr2.test \
        unix-yy.test \
        uid.test \
        uid16.test \
@@ -114,6 +118,7 @@ EXTRA_DIST = init.sh run.sh match.awk \
             sun_path.expected \
             uid.awk \
             uio.expected \
+            umovestr.expected \
             unix-yy-accept.awk \
             unix-yy-connect.awk \
             $(TESTS)
diff --git a/tests/umovestr.c b/tests/umovestr.c
new file mode 100644 (file)
index 0000000..9ad6b94
--- /dev/null
@@ -0,0 +1,26 @@
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int
+main(void)
+{
+       const size_t page_len = sysconf(_SC_PAGESIZE);
+       const size_t tail_len = 257;
+
+       if (tail_len >= page_len)
+               return 77;
+
+       void *p = mmap(NULL, page_len * 2, PROT_READ | PROT_WRITE,
+                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+       if (p == MAP_FAILED || mprotect(p + page_len, page_len, PROT_NONE))
+               return 77;
+
+       memset(p, 0, page_len);
+       char *addr = p + page_len - tail_len;
+       memset(addr, '/', tail_len - 1);
+       if (chdir(addr))
+               return 77;
+
+       return 0;
+}
diff --git a/tests/umovestr.expected b/tests/umovestr.expected
new file mode 100644 (file)
index 0000000..c26d877
--- /dev/null
@@ -0,0 +1,2 @@
+chdir("////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////") = 0
++++ exited with 0 +++
diff --git a/tests/umovestr.test b/tests/umovestr.test
new file mode 100755 (executable)
index 0000000..5ae8ffa
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# umovestr short read regression test
+
+. "${srcdir=.}/init.sh"
+
+run_prog
+run_strace -e chdir $args
+match_diff
+
+exit 0
diff --git a/tests/umovestr2.c b/tests/umovestr2.c
new file mode 100644 (file)
index 0000000..a1ca9fd
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int
+main(void)
+{
+       const size_t page_len = sysconf(_SC_PAGESIZE);
+       const size_t work_len = page_len * 2;
+       const size_t tail_len = work_len - 1;
+
+       void *p = mmap(NULL, page_len * 3, PROT_READ | PROT_WRITE,
+                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+       if (p == MAP_FAILED || mprotect(p + work_len, page_len, PROT_NONE))
+               return 77;
+
+       memset(p, 0, work_len);
+       char *addr = p + work_len - tail_len;
+       memset(addr, '0', tail_len - 1);
+
+       char *argv[] = { NULL };
+       char *envp[] = { addr, NULL };
+       execve("", argv, envp);
+
+       printf("execve\\(\"\", \\[\\], \\[\"%0*u\"\\]\\) = -1 .*\n",
+              (int) tail_len - 1, 0);
+
+       return 0;
+}
diff --git a/tests/umovestr2.test b/tests/umovestr2.test
new file mode 100755 (executable)
index 0000000..7058938
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# umovestr short read regression test
+
+. "${srcdir=.}/init.sh"
+
+OUT="$LOG.out"
+
+run_prog > /dev/null
+run_strace -veexecve -s262144 $args > "$OUT"
+match_grep "$LOG" "$OUT"
+
+rm -f "$OUT"
+
+exit 0
diff --git a/util.c b/util.c
index 1bec3c23cda1064ceeb8d63ea6e86c13c1fa9f4e..534e76079e961528f56d5a444042661a8fa7d09a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1139,7 +1139,7 @@ umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
                         * in the existing (first) page.
                         * (I hope there aren't arches with pages < 4K)
                         */
-                       end_in_page = ((addr + chunk_len) & 4095);
+                       end_in_page = ((long) remote[0].iov_base + chunk_len) & 4095;
                        if (chunk_len > end_in_page) /* crosses to the next page */
                                chunk_len -= end_in_page;