x86/boot: Warn on future overlapping memcpy() use
authorKees Cook <keescook@chromium.org>
Mon, 2 May 2016 22:51:01 +0000 (15:51 -0700)
committerIngo Molnar <mingo@kernel.org>
Tue, 3 May 2016 06:15:58 +0000 (08:15 +0200)
If an overlapping memcpy() is ever attempted, we should at least report
it, in case it might lead to problems, so it could be changed to a
memmove() call instead.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Lasse Collin <lasse.collin@tukaani.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1462229461-3370-3-git-send-email-keescook@chromium.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/boot/compressed/string.c

index faa4dc7..cea140c 100644 (file)
@@ -10,7 +10,7 @@
 #include "../string.c"
 
 #ifdef CONFIG_X86_32
-void *memcpy(void *dest, const void *src, size_t n)
+static void *__memcpy(void *dest, const void *src, size_t n)
 {
        int d0, d1, d2;
        asm volatile(
@@ -24,7 +24,7 @@ void *memcpy(void *dest, const void *src, size_t n)
        return dest;
 }
 #else
-void *memcpy(void *dest, const void *src, size_t n)
+static void *__memcpy(void *dest, const void *src, size_t n)
 {
        long d0, d1, d2;
        asm volatile(
@@ -55,10 +55,20 @@ void *memmove(void *dest, const void *src, size_t n)
        const unsigned char *s = src;
 
        if (d <= s || d - s >= n)
-               return memcpy(dest, src, n);
+               return __memcpy(dest, src, n);
 
        while (n-- > 0)
                d[n] = s[n];
 
        return dest;
 }
+
+/* Detect and warn about potential overlaps, but handle them with memmove. */
+void *memcpy(void *dest, const void *src, size_t n)
+{
+       if (dest > src && dest - src < n) {
+               warn("Avoiding potentially unsafe overlapping memcpy()!");
+               return memmove(dest, src, n);
+       }
+       return __memcpy(dest, src, n);
+}