Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp1019084ybe; Wed, 4 Sep 2019 11:13:49 -0700 (PDT) X-Google-Smtp-Source: APXvYqzd8rvwrCSm7UmtqYiELDC49oKwvPiZObQUkJ8v+sfPEbtfYIDoIvtmV/GwtlFBjVJh+DAX X-Received: by 2002:a62:d14c:: with SMTP id t12mr14324241pfl.185.1567620829059; Wed, 04 Sep 2019 11:13:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1567620829; cv=none; d=google.com; s=arc-20160816; b=favWAkOI2bbcLDnydMaKC/eOIVOYQslkJmyKLwe0BFPyPVDznvDsY6rT/pBmEBUwSZ Ialow4EFEdwS0CbMsG0cijta80BNTUBpzFzaSZtv9Gz8fMAMpk/6uPFSCKmE2HmTt5Ld +ODYLVMch20s6Kdck1rWv8XJxxAZWnWXsxu2Fep3ZaXSHZmAf+C1QRZ/IVaXDhqRAfNa SMNqGZMYupk5YDLSvWouuTD3LA8avk/Ruq4/oCcPlHkqmFXSVyHCusKbwLJoMiRJ3Tz7 W6JzANinkoLF9pWHKFfCZT8uE6aAlR4hRCcB73Hc8KoPg5Ik00jWX3VZ9irXB2fg2VnL pGrw== 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:subject:cc:to :from:dkim-signature; bh=OEjg96kyz/3FnupEfEw4QIJ/gb5KDjYKf1xGoD0lpoQ=; b=NPpUJlVzyIxltscdYIMeQSt42q9+bts/TbMNmKJyOYbnnIsXRV0JM9x5dkNTC2cXkf Ntb8+iIMtZs6ZP3nebqUL2ltzNnMKof0m5ZX3/u/BeqFfLyL9AKpZ23pi8syfSTAlSta K1EoEGctpvt1ZYkDeRap8uKpI+BdXHQb83mpjIaiMhEdCtWmMWqJ0r5l3gyrPPOazL9N 6RV48HQC9azHrSIW+u1B4oki28Vjm8Bi+4AIkqnEhOuwGU/JPkHDrqMMGyabkctJZ6/e JfrAvbavuSlde9SIgSJ3Bm9AeUw9vowX5eFyR1ALNRFiTiSa9QztNiY8NkckPhOqSnjy xnGg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="l32z6/zU"; 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 b6si11936156pfr.225.2019.09.04.11.13.33; Wed, 04 Sep 2019 11:13:49 -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; dkim=pass header.i=@kernel.org header.s=default header.b="l32z6/zU"; 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 S2389667AbfIDSMD (ORCPT + 99 others); Wed, 4 Sep 2019 14:12:03 -0400 Received: from mail.kernel.org ([198.145.29.99]:56270 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390435AbfIDSMC (ORCPT ); Wed, 4 Sep 2019 14:12:02 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (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 5A48222CF7; Wed, 4 Sep 2019 18:12:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1567620720; bh=5S9ox43KCcEMnUOn2PQ6DQ0gzqXSLPSYZm5AqhUbdfc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l32z6/zUMgZRYBPQHuR7zzH/lE+ZoBx+3EbFygZcgsotGaAwxE00V4RVuLptYcRkx ExX/iz7b15pzI079HDMgH+uoWTOoTFH19hHg5+EvdT0fJqpU5/MHERNZx6MO3EN3ey mkYrQpUa1rctipcDpQsNq1mAUCEzwMjl841ozfGw= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Song Liu , Thomas Gleixner , "Peter Zijlstra (Intel)" Subject: [PATCH 5.2 071/143] x86/mm/cpa: Prevent large page split when ftrace flips RW on kernel text Date: Wed, 4 Sep 2019 19:53:34 +0200 Message-Id: <20190904175316.836809015@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190904175314.206239922@linuxfoundation.org> References: <20190904175314.206239922@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Thomas Gleixner commit 7af0145067bc429a09ac4047b167c0971c9f0dc7 upstream. ftrace does not use text_poke() for enabling trace functionality. It uses its own mechanism and flips the whole kernel text to RW and back to RO. The CPA rework removed a loop based check of 4k pages which tried to preserve a large page by checking each 4k page whether the change would actually cover all pages in the large page. This resulted in endless loops for nothing as in testing it turned out that it actually never preserved anything. Of course testing missed to include ftrace, which is the one and only case which benefitted from the 4k loop. As a consequence enabling function tracing or ftrace based kprobes results in a full 4k split of the kernel text, which affects iTLB performance. The kernel RO protection is the only valid case where this can actually preserve large pages. All other static protections (RO data, data NX, PCI, BIOS) are truly static. So a conflict with those protections which results in a split should only ever happen when a change of memory next to a protected region is attempted. But these conflicts are rightfully splitting the large page to preserve the protected regions. In fact a change to the protected regions itself is a bug and is warned about. Add an exception for the static protection check for kernel text RO when the to be changed region spawns a full large page which allows to preserve the large mappings. This also prevents the syslog to be spammed about CPA violations when ftrace is used. The exception needs to be removed once ftrace switched over to text_poke() which avoids the whole issue. Fixes: 585948f4f695 ("x86/mm/cpa: Avoid the 4k pages check completely") Reported-by: Song Liu Signed-off-by: Thomas Gleixner Tested-by: Song Liu Reviewed-by: Song Liu Acked-by: Peter Zijlstra (Intel) Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1908282355340.1938@nanos.tec.linutronix.de Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/pageattr.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -516,7 +516,7 @@ static inline void check_conflict(int wa */ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start, unsigned long pfn, unsigned long npg, - int warnlvl) + unsigned long lpsize, int warnlvl) { pgprotval_t forbidden, res; unsigned long end; @@ -535,9 +535,17 @@ static inline pgprot_t static_protection check_conflict(warnlvl, prot, res, start, end, pfn, "Text NX"); forbidden = res; - res = protect_kernel_text_ro(start, end); - check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO"); - forbidden |= res; + /* + * Special case to preserve a large page. If the change spawns the + * full large page mapping then there is no point to split it + * up. Happens with ftrace and is going to be removed once ftrace + * switched to text_poke(). + */ + if (lpsize != (npg * PAGE_SIZE) || (start & (lpsize - 1))) { + res = protect_kernel_text_ro(start, end); + check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO"); + forbidden |= res; + } /* Check the PFN directly */ res = protect_pci_bios(pfn, pfn + npg - 1); @@ -819,7 +827,7 @@ static int __should_split_large_page(pte * extra conditional required here. */ chk_prot = static_protections(old_prot, lpaddr, old_pfn, numpages, - CPA_CONFLICT); + psize, CPA_CONFLICT); if (WARN_ON_ONCE(pgprot_val(chk_prot) != pgprot_val(old_prot))) { /* @@ -855,7 +863,7 @@ static int __should_split_large_page(pte * protection requirement in the large page. */ new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages, - CPA_DETECT); + psize, CPA_DETECT); /* * If there is a conflict, split the large page. @@ -906,7 +914,8 @@ static void split_set_pte(struct cpa_dat if (!cpa->force_static_prot) goto set; - prot = static_protections(ref_prot, address, pfn, npg, CPA_PROTECT); + /* Hand in lpsize = 0 to enforce the protection mechanism */ + prot = static_protections(ref_prot, address, pfn, npg, 0, CPA_PROTECT); if (pgprot_val(prot) == pgprot_val(ref_prot)) goto set; @@ -1503,7 +1512,8 @@ repeat: pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); cpa_inc_4k_install(); - new_prot = static_protections(new_prot, address, pfn, 1, + /* Hand in lpsize = 0 to enforce the protection mechanism */ + new_prot = static_protections(new_prot, address, pfn, 1, 0, CPA_PROTECT); new_prot = pgprot_clear_protnone_bits(new_prot);