From patchwork Tue Dec 22 22:56:49 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helge Deller X-Patchwork-Id: 69339 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id nBMMurZA013477 for ; Tue, 22 Dec 2009 22:56:53 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751711AbZLVW4x (ORCPT ); Tue, 22 Dec 2009 17:56:53 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751669AbZLVW4x (ORCPT ); Tue, 22 Dec 2009 17:56:53 -0500 Received: from mail.gmx.net ([213.165.64.20]:49436 "HELO mail.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751340AbZLVW4w (ORCPT ); Tue, 22 Dec 2009 17:56:52 -0500 Received: (qmail invoked by alias); 22 Dec 2009 22:56:50 -0000 Received: from p4FDB2567.dip0.t-ipconnect.de (EHLO p100.box) [79.219.37.103] by mail.gmx.net (mp037) with SMTP; 22 Dec 2009 23:56:50 +0100 X-Authenticated: #1045983 X-Provags-ID: V01U2FsdGVkX1+VQ0QauYOVc6X+3f5VKbpCIHngFM8N26wuu00S11 LOdivoTa0SseOJ Date: Tue, 22 Dec 2009 23:56:49 +0100 From: Helge Deller To: linux-parisc@vger.kernel.org, Kyle McMartin Subject: [PATCH] parisc: add strict copy size checks Message-ID: <20091222225649.GA7050@p100.box> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-08-17) X-Y-GMX-Trusted: 0 X-FuHaFi: 0.48 Sender: linux-parisc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug --- 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 --- 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 || 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 --- 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);