From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932288AbcEBWvL (ORCPT ); Mon, 2 May 2016 18:51:11 -0400 Received: from mail-pa0-f53.google.com ([209.85.220.53]:33006 "EHLO mail-pa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932260AbcEBWvG (ORCPT ); Mon, 2 May 2016 18:51:06 -0400 From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Lasse Collin , One Thousand Gnomes , "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , Yinghai Lu , Baoquan He , Borislav Petkov , "x86@kernel.org" , LKML Subject: [PATCH v5 2/2] x86/boot: Warn on future overlapping memcpy() use Date: Mon, 2 May 2016 15:51:01 -0700 Message-Id: <1462229461-3370-3-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.6.3 In-Reply-To: <1462229461-3370-1-git-send-email-keescook@chromium.org> References: <1462229461-3370-1-git-send-email-keescook@chromium.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Signed-off-by: Kees Cook --- arch/x86/boot/compressed/string.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index faa4dc7dc66b..cea140ce6b42 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -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); +} -- 2.6.3