From patchwork Mon Feb 1 19:56:33 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helge Deller X-Patchwork-Id: 76154 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o11JuuBs012915 for ; Mon, 1 Feb 2010 19:56:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755997Ab0BAT4s (ORCPT ); Mon, 1 Feb 2010 14:56:48 -0500 Received: from mail.gmx.net ([213.165.64.20]:37952 "HELO mail.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1756038Ab0BAT4s (ORCPT ); Mon, 1 Feb 2010 14:56:48 -0500 Received: (qmail invoked by alias); 01 Feb 2010 19:56:40 -0000 Received: from p54AD35A0.dip0.t-ipconnect.de (EHLO p100.box) [84.173.53.160] by mail.gmx.net (mp005) with SMTP; 01 Feb 2010 20:56:40 +0100 X-Authenticated: #1045983 X-Provags-ID: V01U2FsdGVkX1/EuaAfN5zEJa1psEX6eH+iLx3WXtH9qFCzcAX/5U sFtUAea1n3BWV9 Date: Mon, 1 Feb 2010 20:56:33 +0100 From: Helge Deller To: Helge Deller , linux-parisc@vger.kernel.org, Kyle McMartin Subject: [PATCH] parisc: add strict copy size checks (v2) Message-ID: <20100201195633.GA14680@p100.box> References: <20091222225649.GA7050@p100.box> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20091222225649.GA7050@p100.box> User-Agent: Mutt/1.5.20 (2009-08-17) X-Y-GMX-Trusted: 0 X-FuHaFi: 0.46000000000000002 Sender: linux-parisc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 01 Feb 2010 19:56:57 +0000 (UTC) diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index bc989e5..7305ac8 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -12,4 +12,18 @@ config DEBUG_RODATA portion of the kernel code won't be covered by a TLB anymore. If in doubt, say "N". +config DEBUG_STRICT_USER_COPY_CHECKS + bool "Strict copy size checks" + depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING + ---help--- + Enabling this option turns a certain set of sanity checks for user + copy operations into compile time failures. + + The copy_from_user() etc checks are there to help test if there + are sufficient security checks on the length argument of + the copy operation, by having gcc prove that the argument is + within bounds. + + If unsure, or if you run an older (pre 4.4) gcc, say N. + endmenu diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 7cf799d..ff4cf9d 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #define VERIFY_READ 0 @@ -234,13 +235,35 @@ extern long lstrnlen_user(const char __user *,long); unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); #define __copy_to_user copy_to_user -unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len); -#define __copy_from_user copy_from_user +unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len); unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); #define __copy_in_user copy_in_user #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user +extern void copy_from_user_overflow(void) +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS + __compiletime_error("copy_from_user() buffer size is not provably correct") +#else + __compiletime_warning("copy_from_user() buffer size is not provably correct") +#endif +; + +static inline unsigned long __must_check copy_from_user(void *to, + const void __user *from, + unsigned long n) +{ + int sz = __compiletime_object_size(to); + int ret = -EFAULT; + + if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n)) + ret = __copy_from_user(to, from, n); + else + copy_from_user_overflow(); + + return ret; +} + struct pt_regs; int fixup_exception(struct pt_regs *regs); diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index abf41f4..1dbca5c 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -475,7 +475,8 @@ unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len) return pa_memcpy((void __force *)dst, src, len); } -unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len) +EXPORT_SYMBOL(__copy_from_user); +unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len) { mtsp(get_user_space(), 1); mtsp(get_kernel_space(), 2);