]> granicus.if.org Git - strace/commitdiff
umovestr: detect invalid addresses
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 26 Dec 2016 12:16:38 +0000 (12:16 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 26 Dec 2016 12:16:38 +0000 (12:16 +0000)
Do not silently truncate tracee addresses to current_wordsize.
After transition from long to kernel_ulong_t there should be no sign
extension issues with tracee addresses, and invalid addresses should
be printed properly.

* util.c (umovestr): Check [SIZEOF_KERNEL_LONG_T > 4] instead
of [SIZEOF_LONG > 4], reject addresses that do not fit into
current_wordsize.
* tests/umovestr-illptr.c: New file.
* tests/umovestr-illptr.test: New test.
* tests/.gitignore: Add umovestr-illptr.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(DECODER_TESTS): Add umovestr-illptr.test.

tests/.gitignore
tests/Makefile.am
tests/umovestr-illptr.c [new file with mode: 0644]
tests/umovestr-illptr.test [new file with mode: 0755]
util.c

index abc26bea295a9cea9f23e750862371c70b652a2a..9e8d3c9afbe9eb1c3c92261c59c06264303e9de5 100644 (file)
@@ -339,6 +339,7 @@ umask
 umount
 umount2
 umovestr
+umovestr-illptr
 umovestr2
 umovestr3
 uname
index d1c2670a4d93f0b388fee25c623b023f7d9dc47f..a9d32e3e107402f7d833b08b8965a9a4d45d2f4a 100644 (file)
@@ -399,6 +399,7 @@ check_PROGRAMS = \
        umount \
        umount2 \
        umovestr \
+       umovestr-illptr \
        umovestr2 \
        umovestr3 \
        uname \
@@ -778,6 +779,7 @@ DECODER_TESTS = \
        umount.test \
        umount2.test \
        umovestr.test \
+       umovestr-illptr.test \
        umovestr2.test \
        umovestr3.test \
        uname.test \
diff --git a/tests/umovestr-illptr.c b/tests/umovestr-illptr.c
new file mode 100644 (file)
index 0000000..dea6885
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Check decoding of invalid pointer by umovestr.
+ *
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+
+int
+main(void)
+{
+       if (F8ILL_KULONG_SUPPORTED) {
+               const void *const p = tail_memdup(".", 2);
+               long rc = syscall(__NR_chdir, p);
+               printf("chdir(\".\") = %s\n", sprintrc(rc));
+
+               const kernel_ulong_t ill = f8ill_ptr_to_kulong(p);
+               rc = syscall(__NR_chdir, ill);
+               printf("chdir(%#llx) = %s\n",
+                      (unsigned long long) ill, sprintrc(rc));
+
+               puts("+++ exited with 0 +++");
+               return 0;
+       } else {
+               return 77;
+       }
+}
diff --git a/tests/umovestr-illptr.test b/tests/umovestr-illptr.test
new file mode 100755 (executable)
index 0000000..6f1cc86
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Check decoding of invalid pointer by umovestr.
+. "${srcdir=.}/init.sh"
+
+run_strace_match_diff -a11 -e trace=chdir
diff --git a/util.c b/util.c
index 73c8fd491aec71f390d99c9d57a872600c8d737f..345363858938e1e76781eeaeb70d5b1668e30322 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1263,9 +1263,12 @@ umovestr(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, char *lad
                char x[sizeof(long)];
        } u;
 
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-       if (current_wordsize < sizeof(addr))
-               addr &= (1ul << 8 * current_wordsize) - 1;
+#if SIZEOF_KERNEL_LONG_T > 4 \
+ && (SIZEOF_LONG < SIZEOF_KERNEL_LONG_T || !defined current_wordsize)
+       if (current_wordsize < sizeof(addr)
+           && (addr & (~ (kernel_ulong_t) -1U))) {
+               return -1;
+       }
 #endif
 
        nread = 0;