From patchwork Wed Oct 21 08:56:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 11848625 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 44BD814B2 for ; Wed, 21 Oct 2020 08:57:27 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id DB3412242E for ; Wed, 21 Oct 2020 08:57:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=ffwll.ch header.i=@ffwll.ch header.b="T/wziZBv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DB3412242E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ffwll.ch Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 123266B0074; Wed, 21 Oct 2020 04:57:18 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 0D4646B0075; Wed, 21 Oct 2020 04:57:18 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id EDFA06B0078; Wed, 21 Oct 2020 04:57:17 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0219.hostedemail.com [216.40.44.219]) by kanga.kvack.org (Postfix) with ESMTP id BEFC16B0074 for ; Wed, 21 Oct 2020 04:57:17 -0400 (EDT) Received: from smtpin22.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 683214DA6 for ; Wed, 21 Oct 2020 08:57:17 +0000 (UTC) X-FDA: 77395328514.22.swing43_340201927247 Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin22.hostedemail.com (Postfix) with ESMTP id 46F5D18038E60 for ; Wed, 21 Oct 2020 08:57:17 +0000 (UTC) X-Spam-Summary: 1,0,0,ae2dfaadde0dda11,d41d8cd98f00b204,daniel.vetter@ffwll.ch,,RULES_HIT:2:41:152:355:379:541:800:960:966:973:988:989:1260:1277:1311:1313:1314:1345:1359:1431:1437:1515:1516:1518:1535:1593:1594:1605:1730:1747:1777:1792:2194:2196:2198:2199:2200:2201:2393:2553:2559:2562:2693:2894:2901:2903:3138:3139:3140:3141:3142:3743:3865:3866:3867:3868:3870:3871:3872:3873:3874:4049:4120:4250:4321:4385:4605:5007:6117:6119:6261:6653:6742:7875:7903:8784:9165:10004:11026:11473:11658:11914:12043:12050:12291:12296:12297:12438:12517:12519:12555:12683:12895:12986:13161:13229:13846:13894:14096:14097:14394:14659:21080:21324:21444:21451:21627:21740:21795:21939:21966:21990:30003:30025:30051:30054:30064:30070:30090,0,RBL:209.85.221.67:@ffwll.ch:.lbl8.mailshell.net-66.201.201.201 62.8.0.100;04yrjscu61pyqks55jd6ab84o91n7ocpk9jqqrm89ubyt746xxgi8i49feodqs6.qtib8zhubx9687qjtuiyxbnir695xbe1z59d3wqzdwfgqeqfa1ep5h1gxt1seda.e-lbl8.mailshell.net-223.238.255.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Net check:no X-HE-Tag: swing43_340201927247 X-Filterd-Recvd-Size: 9408 Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by imf06.hostedemail.com (Postfix) with ESMTP for ; Wed, 21 Oct 2020 08:57:16 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id x7so2156016wrl.3 for ; Wed, 21 Oct 2020 01:57:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6FXNrAQVDv1GTk8GGIBMBQb/Z7TasoUYfJDj34pJUVI=; b=T/wziZBvTeYdpgXtCKfWeTCOgG6ZxQR1iNX7ttAqm5X7cINbcDOihlyivfIStE4ANr 0qrqTjm8QE7XBP58Kl+sS22BQ+9w8LYcHgu8lltEf/ygHjiE7VPVTCnywJMpDHX3sgzA Ygc4PLFqiL0ZtCsDJT7/VAACIReSV3eUwGPjQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6FXNrAQVDv1GTk8GGIBMBQb/Z7TasoUYfJDj34pJUVI=; b=qalp5RkwrOkLe5Kcu3l0JmWyspld+FWZri4ACF44mO205KOtP9n7EFYg4kUPjBbyXC F2eShwjt3VCmpRj0o4XlkZUvXwBczsw275qTkjjkEy20mY7pPrwhTrsuMZ7h/kMKTFeD z+YMcGmjKv8Ua80TYq1MvrC5mbA5SBz10/646MBFMVqDOgF+BDIQhHeq/iohcFb38tWz qNp8ivXBq05DF7KYMbUfiPr3Cb3uLQtcsXoT+eOS2bNZPTxqcz4pKcWlbipMZSWYRAQ7 HPfSYbNbB67c/lREWo91IxH8YWXMN4s+uR2NY/D0EitaGj/ZLFiC2zKyinTGEcvaWe+e 6Bzw== X-Gm-Message-State: AOAM531SCXb7fD10bgwsUe7AJWC0hQ2sXDpP34ZChSVvGsqixGfCXRGs zYTbfsx8Q92z1Em0BHMYWnI/xg== X-Google-Smtp-Source: ABdhPJw8jFUGdXy3ZpYF3vCPjAT9o/iNmVHD7rY86u4NG9L79ReYww5XLftER1AdoF7j6wSADq055Q== X-Received: by 2002:adf:94e3:: with SMTP id 90mr3176123wrr.380.1603270635628; Wed, 21 Oct 2020 01:57:15 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:57f4:0:efd0:b9e5:5ae6:c2fa]) by smtp.gmail.com with ESMTPSA id q8sm2675939wro.32.2020.10.21.01.57.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Oct 2020 01:57:14 -0700 (PDT) From: Daniel Vetter To: DRI Development , LKML Cc: kvm@vger.kernel.org, linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-media@vger.kernel.org, linux-s390@vger.kernel.org, Daniel Vetter , Daniel Vetter , Jason Gunthorpe , Kees Cook , Dan Williams , Andrew Morton , John Hubbard , =?utf-8?b?SsOpcsO0bWUgR2xpc3Nl?= , Jan Kara , Daniel Vetter Subject: [PATCH v3 09/16] mm: Add unsafe_follow_pfn Date: Wed, 21 Oct 2020 10:56:48 +0200 Message-Id: <20201021085655.1192025-10-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201021085655.1192025-1-daniel.vetter@ffwll.ch> References: <20201021085655.1192025-1-daniel.vetter@ffwll.ch> MIME-Version: 1.0 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Way back it was a reasonable assumptions that iomem mappings never change the pfn range they point at. But this has changed: - gpu drivers dynamically manage their memory nowadays, invalidating ptes with unmap_mapping_range when buffers get moved - contiguous dma allocations have moved from dedicated carvetouts to cma regions. This means if we miss the unmap the pfn might contain pagecache or anon memory (well anything allocated with GFP_MOVEABLE) - even /dev/mem now invalidates mappings when the kernel requests that iomem region when CONFIG_IO_STRICT_DEVMEM is set, see 3234ac664a87 ("/dev/mem: Revoke mappings when a driver claims the region") Accessing pfns obtained from ptes without holding all the locks is therefore no longer a good idea. Unfortunately there's some users where this is not fixable (like v4l userptr of iomem mappings) or involves a pile of work (vfio type1 iommu). For now annotate these as unsafe and splat appropriately. This patch adds an unsafe_follow_pfn, which later patches will then roll out to all appropriate places. Signed-off-by: Daniel Vetter Cc: Jason Gunthorpe Cc: Kees Cook Cc: Dan Williams Cc: Andrew Morton Cc: John Hubbard Cc: Jérôme Glisse Cc: Jan Kara Cc: Dan Williams Cc: linux-mm@kvack.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: linux-media@vger.kernel.org Cc: kvm@vger.kernel.org Signed-off-by: Daniel Vetter --- include/linux/mm.h | 2 ++ mm/memory.c | 32 +++++++++++++++++++++++++++++++- mm/nommu.c | 17 +++++++++++++++++ security/Kconfig | 13 +++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 2a16631c1fda..ec8c90928fc9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1653,6 +1653,8 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address, pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp); int follow_pfn(struct vm_area_struct *vma, unsigned long address, unsigned long *pfn); +int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address, + unsigned long *pfn); int follow_phys(struct vm_area_struct *vma, unsigned long address, unsigned int flags, unsigned long *prot, resource_size_t *phys); int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, diff --git a/mm/memory.c b/mm/memory.c index fff817608eb4..bcba4e8f1501 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4788,7 +4788,12 @@ EXPORT_SYMBOL(follow_pte_pmd); * @address: user virtual address * @pfn: location to store found PFN * - * Only IO mappings and raw PFN mappings are allowed. + * Only IO mappings and raw PFN mappings are allowed. Note that callers must + * ensure coherency with pte updates by using a &mmu_notifier to follow updates. + * If this is not feasible, or the access to the @pfn is only very short term, + * use follow_pte_pmd() instead and hold the pagetable lock for the duration of + * the access instead. Any caller not following these requirements must use + * unsafe_follow_pfn() instead. * * Return: zero and the pfn at @pfn on success, -ve otherwise. */ @@ -4811,6 +4816,31 @@ int follow_pfn(struct vm_area_struct *vma, unsigned long address, } EXPORT_SYMBOL(follow_pfn); +/** + * unsafe_follow_pfn - look up PFN at a user virtual address + * @vma: memory mapping + * @address: user virtual address + * @pfn: location to store found PFN + * + * Only IO mappings and raw PFN mappings are allowed. + * + * Returns zero and the pfn at @pfn on success, -ve otherwise. + */ +int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address, + unsigned long *pfn) +{ +#ifdef CONFIG_STRICT_FOLLOW_PFN + pr_info("unsafe follow_pfn usage rejected, see CONFIG_STRICT_FOLLOW_PFN\n"); + return -EINVAL; +#else + WARN_ONCE(1, "unsafe follow_pfn usage\n"); + add_taint(TAINT_USER, LOCKDEP_STILL_OK); + + return follow_pfn(vma, address, pfn); +#endif +} +EXPORT_SYMBOL(unsafe_follow_pfn); + #ifdef CONFIG_HAVE_IOREMAP_PROT int follow_phys(struct vm_area_struct *vma, unsigned long address, unsigned int flags, diff --git a/mm/nommu.c b/mm/nommu.c index 75a327149af1..3db2910f0d64 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -132,6 +132,23 @@ int follow_pfn(struct vm_area_struct *vma, unsigned long address, } EXPORT_SYMBOL(follow_pfn); +/** + * unsafe_follow_pfn - look up PFN at a user virtual address + * @vma: memory mapping + * @address: user virtual address + * @pfn: location to store found PFN + * + * Only IO mappings and raw PFN mappings are allowed. + * + * Returns zero and the pfn at @pfn on success, -ve otherwise. + */ +int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address, + unsigned long *pfn) +{ + return follow_pfn(vma, address, pfn); +} +EXPORT_SYMBOL(unsafe_follow_pfn); + LIST_HEAD(vmap_area_list); void vfree(const void *addr) diff --git a/security/Kconfig b/security/Kconfig index 7561f6f99f1d..48945402e103 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -230,6 +230,19 @@ config STATIC_USERMODEHELPER_PATH If you wish for all usermode helper programs to be disabled, specify an empty string here (i.e. ""). +config STRICT_FOLLOW_PFN + bool "Disable unsafe use of follow_pfn" + depends on MMU + help + Some functionality in the kernel follows userspace mappings to iomem + ranges in an unsafe matter. Examples include v4l userptr for zero-copy + buffers sharing. + + If this option is switched on, such access is rejected. Only enable + this option when you must run userspace which requires this. + + If in doubt, say Y. + source "security/selinux/Kconfig" source "security/smack/Kconfig" source "security/tomoyo/Kconfig"