Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp1174015pxb; Fri, 20 Nov 2020 03:08:46 -0800 (PST) X-Google-Smtp-Source: ABdhPJyJLjacK3vebSyYjTODBiT58+vgR1oId/6cxghVNDqjZ628sVVgvDDinJ314ellcLz9DXRY X-Received: by 2002:a17:906:757:: with SMTP id z23mr9973320ejb.259.1605870526331; Fri, 20 Nov 2020 03:08:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605870526; cv=none; d=google.com; s=arc-20160816; b=Hf5+Q8zTOeM6R/Gen2f9g5ZOGGKeu6OBNDPxBd1DSBJkO+npcOzYrRNxYgqCvVjBJd 6friOs15NEFzYXYJgraiGXGRFE4JW7PxRqZIcHx1GpoStCPZv4rODgPFVS0X5XFUPuRF jwrgD9pf23dsuzNPkv+8X2cGThdap8m8g98ypgsf2VaYQ6+RSwrva94Ji92q7TlpuGFN SU/Wdt6Cr4VxvgOsG1JOfyrmbSG+X54LO1g3IJrMHCZxDruR9NDoQK3q5c/X6ajpAod3 6eSIpk42GNeTH7/VI4O+7/6Q0mK82oIgvm9n11CaRwVXAptTJT2Xwzu/cnGTCemtvvBP 5OqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Ijfhsn9VbCVVon63CJefOO4f2CT7fYzwpGTRO53T4wU=; b=sXKXjM0ZBfdsI5y+IXLlywoX6ZSf5SxGw/SYN63vMRI9RKAUj5oagO2tBquB6yskEN PpqfyWAKTWvellDAW5BzOI06gRd42aUgdBG3lZaFjK4/CqoxE7SVjJw3uFGKGWNlu4Ul EsjX2xxvVvB93N4JXZaV4Dtk1N7K5lUZ6kSrttW8dPw93Izz+XZJjtUfv0jIpZLSSW26 EMLAiE2rQNZk2SyP6a+KGz6wIoKsHpf97m77jmb6hSH8ZNgYNiXH0YHOdwALLVRiV8Wl klIPBFuDsPLpbtr76cz84xESjR0gtXKpSjwsKclc6QJ9Opiqx16IYIOisl3HZnpk22p6 MMmQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=iUIPGh06; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e9si1526023ejk.493.2020.11.20.03.08.18; Fri, 20 Nov 2020 03:08:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=iUIPGh06; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727987AbgKTLEe (ORCPT + 99 others); Fri, 20 Nov 2020 06:04:34 -0500 Received: from mail.kernel.org ([198.145.29.99]:52048 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727973AbgKTLEc (ORCPT ); Fri, 20 Nov 2020 06:04:32 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A4596206E3; Fri, 20 Nov 2020 11:04:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1605870271; bh=iIm/zTG25a4+AjfBGOKSunF46YRxDd+azgdtBOiJf40=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iUIPGh06hV6w6voaQlHeUj+yOA2PneyGMvwiWqUo/0uNIUMlcjDTC/5bnJ1X+A2/F MMBXmb77euANuD7HR7dEtpIKavSmbjEUeX4BKQbolwB/Vxq0+qJky3b3t/Y+j9NpMG dgP+vPf5M0zqIUbZL31sOpBKR8gGR06r/yB63g4E= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Greg Kroah-Hartman , dja@axtens.net, Christophe Leroy , Russell Currey , Michael Ellerman Subject: [PATCH 4.9 04/16] powerpc: Add a framework for user access tracking Date: Fri, 20 Nov 2020 12:03:09 +0100 Message-Id: <20201120104539.940454331@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201120104539.706905067@linuxfoundation.org> References: <20201120104539.706905067@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Christophe Leroy Backported from commit de78a9c42a79 ("powerpc: Add a framework for Kernel Userspace Access Protection"). Here we don't try to add the KUAP framework, we just want the helper functions because we want to put uaccess flush helpers in them. In terms of fixes, we don't need commit 1d8f739b07bd ("powerpc/kuap: Fix set direction in allow/prevent_user_access()") as we don't have real KUAP. Likewise as all our allows are noops and all our prevents are just flushes, we don't need commit 9dc086f1e9ef ("powerpc/futex: Fix incorrect user access blocking") The other 2 fixes we do need. The original description is: This patch implements a framework for Kernel Userspace Access Protection. Then subarches will have the possibility to provide their own implementation by providing setup_kuap() and allow/prevent_user_access(). Some platforms will need to know the area accessed and whether it is accessed from read, write or both. Therefore source, destination and size and handed over to the two functions. mpe: Rename to allow/prevent rather than unlock/lock, and add read/write wrappers. Drop the 32-bit code for now until we have an implementation for it. Add kuap to pt_regs for 64-bit as well as 32-bit. Don't split strings, use pr_crit_ratelimited(). Signed-off-by: Christophe Leroy Signed-off-by: Russell Currey Signed-off-by: Michael Ellerman Signed-off-by: Daniel Axtens Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/futex.h | 4 +++ arch/powerpc/include/asm/kup.h | 36 ++++++++++++++++++++++++++++++++ arch/powerpc/include/asm/uaccess.h | 39 ++++++++++++++++++++++++++--------- arch/powerpc/lib/checksum_wrappers.c | 4 +++ 4 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 arch/powerpc/include/asm/kup.h --- a/arch/powerpc/include/asm/futex.h +++ b/arch/powerpc/include/asm/futex.h @@ -36,6 +36,7 @@ static inline int arch_futex_atomic_op_i { int oldval = 0, ret; + allow_write_to_user(uaddr, sizeof(*uaddr)); pagefault_disable(); switch (op) { @@ -62,6 +63,7 @@ static inline int arch_futex_atomic_op_i *oval = oldval; + prevent_write_to_user(uaddr, sizeof(*uaddr)); return ret; } @@ -75,6 +77,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; + allow_write_to_user(uaddr, sizeof(*uaddr)); __asm__ __volatile__ ( PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\ @@ -97,6 +100,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, : "cc", "memory"); *uval = prev; + prevent_write_to_user(uaddr, sizeof(*uaddr)); return ret; } --- /dev/null +++ b/arch/powerpc/include/asm/kup.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_KUP_H_ +#define _ASM_POWERPC_KUP_H_ + +#ifndef __ASSEMBLY__ + +#include + +static inline void allow_user_access(void __user *to, const void __user *from, + unsigned long size) { } +static inline void prevent_user_access(void __user *to, const void __user *from, + unsigned long size) { } + +static inline void allow_read_from_user(const void __user *from, unsigned long size) +{ + allow_user_access(NULL, from, size); +} + +static inline void allow_write_to_user(void __user *to, unsigned long size) +{ + allow_user_access(to, NULL, size); +} + +static inline void prevent_read_from_user(const void __user *from, unsigned long size) +{ + prevent_user_access(NULL, from, size); +} + +static inline void prevent_write_to_user(void __user *to, unsigned long size) +{ + prevent_user_access(to, NULL, size); +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_KUP_H_ */ --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -9,6 +9,7 @@ #include #include #include +#include #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -164,6 +165,7 @@ extern long __put_user_bad(void); #define __put_user_size(x, ptr, size, retval) \ do { \ retval = 0; \ + allow_write_to_user(ptr, size); \ switch (size) { \ case 1: __put_user_asm(x, ptr, retval, "stb"); break; \ case 2: __put_user_asm(x, ptr, retval, "sth"); break; \ @@ -171,6 +173,7 @@ do { \ case 8: __put_user_asm2(x, ptr, retval); break; \ default: __put_user_bad(); \ } \ + prevent_write_to_user(ptr, size); \ } while (0) #define __put_user_nocheck(x, ptr, size) \ @@ -252,6 +255,7 @@ do { \ __chk_user_ptr(ptr); \ if (size > sizeof(x)) \ (x) = __get_user_bad(); \ + allow_read_from_user(ptr, size); \ switch (size) { \ case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \ case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \ @@ -259,6 +263,7 @@ do { \ case 8: __get_user_asm2(x, ptr, retval); break; \ default: (x) = __get_user_bad(); \ } \ + prevent_read_from_user(ptr, size); \ } while (0) #define __get_user_nocheck(x, ptr, size) \ @@ -312,9 +317,14 @@ extern unsigned long __copy_tofrom_user( static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { + unsigned long ret; + if (likely(access_ok(VERIFY_READ, from, n))) { check_object_size(to, n, false); - return __copy_tofrom_user((__force void __user *)to, from, n); + allow_user_access(to, from, n); + ret = __copy_tofrom_user((__force void __user *)to, from, n); + prevent_user_access(to, from, n); + return ret; } memset(to, 0, n); return n; @@ -347,8 +357,9 @@ extern unsigned long copy_in_user(void _ static inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { + unsigned long ret; if (__builtin_constant_p(n) && (n <= 8)) { - unsigned long ret = 1; + ret = 1; switch (n) { case 1: @@ -375,14 +386,18 @@ static inline unsigned long __copy_from_ check_object_size(to, n, false); barrier_nospec(); - return __copy_tofrom_user((__force void __user *)to, from, n); + allow_read_from_user(from, n); + ret = __copy_tofrom_user((__force void __user *)to, from, n); + prevent_read_from_user(from, n); + return ret; } static inline unsigned long __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { + unsigned long ret; if (__builtin_constant_p(n) && (n <= 8)) { - unsigned long ret = 1; + ret = 1; switch (n) { case 1: @@ -403,8 +418,10 @@ static inline unsigned long __copy_to_us } check_object_size(from, n, true); - - return __copy_tofrom_user(to, (__force const void __user *)from, n); + allow_write_to_user(to, n); + ret = __copy_tofrom_user(to, (__force const void __user *)from, n); + prevent_write_to_user(to, n); + return ret; } static inline unsigned long __copy_from_user(void *to, @@ -425,10 +442,14 @@ extern unsigned long __clear_user(void _ static inline unsigned long clear_user(void __user *addr, unsigned long size) { + unsigned long ret = size; might_fault(); - if (likely(access_ok(VERIFY_WRITE, addr, size))) - return __clear_user(addr, size); - return size; + if (likely(access_ok(VERIFY_WRITE, addr, size))) { + allow_write_to_user(addr, size); + ret = __clear_user(addr, size); + prevent_write_to_user(addr, size); + } + return ret; } extern long strncpy_from_user(char *dst, const char __user *src, long count); --- a/arch/powerpc/lib/checksum_wrappers.c +++ b/arch/powerpc/lib/checksum_wrappers.c @@ -29,6 +29,7 @@ __wsum csum_and_copy_from_user(const voi unsigned int csum; might_sleep(); + allow_read_from_user(src, len); *err_ptr = 0; @@ -60,6 +61,7 @@ __wsum csum_and_copy_from_user(const voi } out: + prevent_read_from_user(src, len); return (__force __wsum)csum; } EXPORT_SYMBOL(csum_and_copy_from_user); @@ -70,6 +72,7 @@ __wsum csum_and_copy_to_user(const void unsigned int csum; might_sleep(); + allow_write_to_user(dst, len); *err_ptr = 0; @@ -97,6 +100,7 @@ __wsum csum_and_copy_to_user(const void } out: + prevent_write_to_user(dst, len); return (__force __wsum)csum; } EXPORT_SYMBOL(csum_and_copy_to_user);