From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933134AbbGGUax (ORCPT ); Tue, 7 Jul 2015 16:30:53 -0400 Received: from userp1040.oracle.com ([156.151.31.81]:16599 "EHLO userp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757967AbbGGUUy (ORCPT ); Tue, 7 Jul 2015 16:20:54 -0400 From: Yinghai Lu To: Kees Cook , "H. Peter Anvin" , Baoquan He Cc: linux-kernel@vger.kernel.org, Yinghai Lu Subject: [PATCH 11/42] x86, boot: Add checking for memcpy Date: Tue, 7 Jul 2015 13:19:57 -0700 Message-Id: <1436300428-21163-12-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1436300428-21163-1-git-send-email-yinghai@kernel.org> References: <1436300428-21163-1-git-send-email-yinghai@kernel.org> X-Source-IP: aserv0021.oracle.com [141.146.126.233] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org parse_elf is using local memcpy to move section to running position. That memcpy actually only support no overlapping or dest < src. Add checking in memcpy to find out wrong with future use, at that time we will need to have backward memcpy for it. Also put comments in parse_elf about the fact. Signed-off-by: Yinghai Lu --- arch/x86/boot/compressed/misc.c | 14 +++++++------- arch/x86/boot/compressed/misc.h | 2 ++ arch/x86/boot/compressed/string.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 8fb74ba..83f98a5 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -106,9 +106,6 @@ #undef memset #define memzero(s, n) memset((s), 0, (n)) - -static void error(char *m); - /* * This is set up by the setup-routine at boot-time */ @@ -218,7 +215,7 @@ void __putstr(const char *s) outb(0xff & (pos >> 1), vidport+1); } -static void error(char *x) +void error(char *x) { error_putstr("\n\n"); error_putstr(x); @@ -353,9 +350,12 @@ static void parse_elf(void *output) #else dest = (void *)(phdr->p_paddr); #endif - memcpy(dest, - output + phdr->p_offset, - phdr->p_filesz); + /* + * simple version memcpy only can work when dest is + * smaller than src or no overlapping. + * Here dest is smaller than src always. + */ + memcpy(dest, output + phdr->p_offset, phdr->p_filesz); break; default: /* Ignore other PT_* */ break; } diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 0104c0be..af135b7 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -36,6 +36,8 @@ extern struct boot_params *real_mode; /* Pointer to real-mode data */ void __putstr(const char *s); #define error_putstr(__x) __putstr(__x) +void error(char *x); + #ifdef CONFIG_X86_VERBOSE_BOOTUP #define debug_putstr(__x) __putstr(__x) diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 00e788b..03805a4 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -1,7 +1,7 @@ #include "../string.c" #ifdef CONFIG_X86_32 -void *memcpy(void *dest, const void *src, size_t n) +void *__memcpy(void *dest, const void *src, size_t n) { int d0, d1, d2; asm volatile( @@ -15,7 +15,7 @@ void *memcpy(void *dest, const void *src, size_t n) return dest; } #else -void *memcpy(void *dest, const void *src, size_t n) +void *__memcpy(void *dest, const void *src, size_t n) { long d0, d1, d2; asm volatile( @@ -30,6 +30,30 @@ void *memcpy(void *dest, const void *src, size_t n) } #endif +void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned long start_dest, end_dest; + unsigned long start_src, end_src; + unsigned long max_start, min_end; + + if (dest < src) + return __memcpy(dest, src, n); + + start_dest = (unsigned long)dest; + end_dest = (unsigned long)dest + n; + start_src = (unsigned long)src; + end_src = (unsigned long)src + n; + max_start = (start_dest > start_src) ? start_dest : start_src; + min_end = (end_dest < end_src) ? end_dest : end_src; + + if (max_start >= min_end) + return __memcpy(dest, src, n); + + error("memcpy does not support overlapping with dest > src!\n"); + + return dest; +} + void *memset(void *s, int c, size_t n) { int i; -- 1.8.4.5