Received: by 10.192.165.148 with SMTP id m20csp1427866imm; Wed, 2 May 2018 22:10:51 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpB4U+4mqNNUtww0U+QqZfhO6ErlCePfIW9OkkWJT726mMdGUI68oePcCPysUA/YiW2KfsL X-Received: by 2002:a17:902:8606:: with SMTP id f6-v6mr22506973plo.258.1525324251671; Wed, 02 May 2018 22:10:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525324251; cv=none; d=google.com; s=arc-20160816; b=lFJ4BFt9hso2XlQeW2jvYCCK5GK+I4ekmtwCAdm7A+5c+kbRmbxHaVtlIFUQ/MeP/8 K0ImDVTxlIssMKnSMwHwsiJhVwPAQXsfMHEWBrMHe1V/Dqqcg28FrlQpTVuJnUT60Ihj 53QeL4LpdCXpb+Q2vq05K2KEp4QzJBp6IvY2PP3EYQ0EbPXwXSGQZI0Z4n3yDVRykt4D QVRnQmqblIpTEU6sXKjTDrDfUpdr5Aqu2WjOLtDTLF0IMEDZZ42vtOv1BjkkNlMVmbDg mjD0mq51ypkjBNgG2Av/hBma9vxhfsV7hv4Wnpdo61p2FtzPnAqn7c9q0TYpOD5jJ67Q AMOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:arc-authentication-results; bh=MAJnxSgkeC4TqdwV5EIf4x3bIAZTaGFPk3DAmcM1vb8=; b=NxXI0IcsvAqyvZOW1BfG3sB3bXkXpPbK028Td3elKuosehB9LxDEBaN1I2zO69Svlh 4xyK04yUxRL+GXf4bll1LYLDFj/CKulJDGavmezgO/UkOUus8rvu1EnN45sVKnrU8YUs rIFUzJ+f5wLpe9kCf57YIeBPNiZPWc7sxMu9ulGIxd56TIyyamJCttJa22uX+943o7RH adKpq9T+Cxk2vujha7otHNwUHqEDzWq4mU4U8bzmD2hJTry6heVQzVhWISCX0ZnqtBEK Xy2oU2aXm8H5BghgNi/ioKFJnMf30oUVzG9utxRGjwaW/22mE4mKQ/JVVEKOj93ApGmM 71Sw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m3-v6si12925984pld.296.2018.05.02.22.10.37; Wed, 02 May 2018 22:10:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752279AbeECFJQ (ORCPT + 99 others); Thu, 3 May 2018 01:09:16 -0400 Received: from mga18.intel.com ([134.134.136.126]:57747 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751624AbeECFJJ (ORCPT ); Thu, 3 May 2018 01:09:09 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 May 2018 22:09:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,356,1520924400"; d="scan'208";a="38046275" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.54.39.16]) by orsmga007.jf.intel.com with ESMTP; 02 May 2018 22:09:09 -0700 Subject: [PATCH v2 5/9] x86, memcpy_mcsafe: define copy_to_iter_mcsafe() From: Dan Williams To: linux-nvdimm@lists.01.org Cc: x86@kernel.org, Ingo Molnar , Borislav Petkov , Tony Luck , Al Viro , Thomas Gleixner , Andy Lutomirski , Peter Zijlstra , Andrew Morton , Linus Torvalds , hch@lst.de, linux-kernel@vger.kernel.org, tony.luck@intel.com, linux-fsdevel@vger.kernel.org Date: Wed, 02 May 2018 21:59:07 -0700 Message-ID: <152532354781.17218.7424857107546723514.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <152532351517.17218.3583455156840230837.stgit@dwillia2-desk3.amr.corp.intel.com> References: <152532351517.17218.3583455156840230837.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.18-2-gc94f MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Use the updated memcpy_mcsafe() implementation to define copy_user_mcsafe() and copy_to_iter_mcsafe(). The most significant difference from typical copy_to_iter() is that the ITER_KVEC and ITER_BVEC iterator types can fail to complete a full transfer. Cc: Cc: Ingo Molnar Cc: Borislav Petkov Cc: Tony Luck Cc: Al Viro Cc: Thomas Gleixner Cc: Andy Lutomirski Cc: Peter Zijlstra Cc: Andrew Morton Cc: Linus Torvalds Signed-off-by: Dan Williams --- arch/x86/Kconfig | 1 + arch/x86/include/asm/uaccess_64.h | 11 +++++++ include/linux/uio.h | 15 +++++++++ lib/iov_iter.c | 61 +++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c07f492b871a..6ca22706cd64 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -60,6 +60,7 @@ config X86 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_REFCOUNT select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 + select ARCH_HAS_UACCESS_MCSAFE if X86_64 select ARCH_HAS_SET_MEMORY select ARCH_HAS_SG_CHAIN select ARCH_HAS_STRICT_KERNEL_RWX diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index c63efc07891f..62acb613114b 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -47,6 +47,17 @@ copy_user_generic(void *to, const void *from, unsigned len) } static __always_inline __must_check unsigned long +copy_to_user_mcsafe(void *to, const void *from, unsigned len) +{ + unsigned long ret; + + __uaccess_begin(); + ret = memcpy_mcsafe(to, from, len); + __uaccess_end(); + return ret; +} + +static __always_inline __must_check unsigned long raw_copy_from_user(void *dst, const void __user *src, unsigned long size) { int ret = 0; diff --git a/include/linux/uio.h b/include/linux/uio.h index e67e12adb136..f5766e853a77 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -154,6 +154,12 @@ size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i); #define _copy_from_iter_flushcache _copy_from_iter_nocache #endif +#ifdef CONFIG_ARCH_HAS_UACCESS_MCSAFE +size_t _copy_to_iter_mcsafe(void *addr, size_t bytes, struct iov_iter *i); +#else +#define _copy_to_iter_mcsafe _copy_to_iter +#endif + static __always_inline __must_check size_t copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) { @@ -163,6 +169,15 @@ size_t copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) return _copy_from_iter_flushcache(addr, bytes, i); } +static __always_inline __must_check +size_t copy_to_iter_mcsafe(void *addr, size_t bytes, struct iov_iter *i) +{ + if (unlikely(!check_copy_size(addr, bytes, false))) + return 0; + else + return _copy_to_iter_mcsafe(addr, bytes, i); +} + size_t iov_iter_zero(size_t bytes, struct iov_iter *); unsigned long iov_iter_alignment(const struct iov_iter *i); unsigned long iov_iter_gap_alignment(const struct iov_iter *i); diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 970212670b6a..70ebc8ede143 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -573,6 +573,67 @@ size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) } EXPORT_SYMBOL(_copy_to_iter); +#ifdef CONFIG_ARCH_HAS_UACCESS_MCSAFE +static int copyout_mcsafe(void __user *to, const void *from, size_t n) +{ + if (access_ok(VERIFY_WRITE, to, n)) { + kasan_check_read(from, n); + n = copy_to_user_mcsafe((__force void *) to, from, n); + } + return n; +} + +static unsigned long memcpy_mcsafe_to_page(struct page *page, size_t offset, + const char *from, size_t len) +{ + unsigned long ret; + char *to; + + to = kmap_atomic(page); + ret = memcpy_mcsafe(to + offset, from, len); + kunmap_atomic(to); + + return ret; +} + +size_t _copy_to_iter_mcsafe(const void *addr, size_t bytes, struct iov_iter *i) +{ + const char *from = addr; + unsigned long rem, curr_addr, s_addr = (unsigned long) addr; + + if (unlikely(i->type & ITER_PIPE)) { + WARN_ON(1); + return 0; + } + if (iter_is_iovec(i)) + might_fault(); + iterate_and_advance(i, bytes, v, + copyout_mcsafe(v.iov_base, (from += v.iov_len) - v.iov_len, v.iov_len), + ({ + rem = memcpy_mcsafe_to_page(v.bv_page, v.bv_offset, + (from += v.bv_len) - v.bv_len, v.bv_len); + if (rem) { + curr_addr = (unsigned long) from; + bytes = curr_addr - s_addr - rem; + return bytes; + } + }), + ({ + rem = memcpy_mcsafe(v.iov_base, (from += v.iov_len) - v.iov_len, + v.iov_len); + if (rem) { + curr_addr = (unsigned long) from; + bytes = curr_addr - s_addr - rem; + return bytes; + } + }) + ) + + return bytes; +} +EXPORT_SYMBOL_GPL(_copy_to_iter_mcsafe); +#endif /* CONFIG_ARCH_HAS_UACCESS_MCSAFE */ + size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) { char *to = addr;