aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2015-03-31 18:52:57 +0000
committerDmitry V. Levin <ldv@altlinux.org>2015-03-31 20:52:41 +0000
commit48321344d7c6f1af5326b31131b3f57da57e4203 (patch)
tree6242010a9458900b06927464798973cf7fcb30ad
parentb2893c9e9e84e51d6e11ddae7c6908bb707ddbb2 (diff)
downloadandroid_external_strace-48321344d7c6f1af5326b31131b3f57da57e4203.tar.gz
android_external_strace-48321344d7c6f1af5326b31131b3f57da57e4203.tar.bz2
android_external_strace-48321344d7c6f1af5326b31131b3f57da57e4203.zip
umovestr: fix short read bug
* 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>
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/Makefile.am5
-rw-r--r--tests/umovestr.c26
-rw-r--r--tests/umovestr.expected2
-rwxr-xr-xtests/umovestr.test11
-rw-r--r--tests/umovestr2.c30
-rwxr-xr-xtests/umovestr2.test15
-rw-r--r--util.c2
8 files changed, 92 insertions, 1 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 38b80598..6903a5ce 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -28,6 +28,8 @@ uid
uid16
uid32
uio
+umovestr
+umovestr2
unix-pair-send-recv
*.log
*.log.*
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 62e5d667..e5dae02a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 00000000..9ad6b94d
--- /dev/null
+++ b/tests/umovestr.c
@@ -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
index 00000000..c26d877e
--- /dev/null
+++ b/tests/umovestr.expected
@@ -0,0 +1,2 @@
+chdir("////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////") = 0
++++ exited with 0 +++
diff --git a/tests/umovestr.test b/tests/umovestr.test
new file mode 100755
index 00000000..5ae8ffa9
--- /dev/null
+++ b/tests/umovestr.test
@@ -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
index 00000000..a1ca9fd1
--- /dev/null
+++ b/tests/umovestr2.c
@@ -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
index 00000000..70589387
--- /dev/null
+++ b/tests/umovestr2.test
@@ -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 1bec3c23..534e7607 100644
--- 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;