diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2015-03-31 18:52:57 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2015-03-31 20:52:41 +0000 |
commit | 48321344d7c6f1af5326b31131b3f57da57e4203 (patch) | |
tree | 6242010a9458900b06927464798973cf7fcb30ad | |
parent | b2893c9e9e84e51d6e11ddae7c6908bb707ddbb2 (diff) | |
download | android_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/.gitignore | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 5 | ||||
-rw-r--r-- | tests/umovestr.c | 26 | ||||
-rw-r--r-- | tests/umovestr.expected | 2 | ||||
-rwxr-xr-x | tests/umovestr.test | 11 | ||||
-rw-r--r-- | tests/umovestr2.c | 30 | ||||
-rwxr-xr-x | tests/umovestr2.test | 15 | ||||
-rw-r--r-- | util.c | 2 |
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 @@ -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; |