Received: by 2002:ab2:7041:0:b0:1f4:bcc8:f211 with SMTP id x1csp214904lql; Fri, 12 Apr 2024 08:17:48 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCV6ogPNsg4OnHbVbVh/qUSZoIqGDabCEEVJOZff9NYMaXXEVBAuaKOdhpnXN4ShA6NPWYOAI/ZbIDavO1PbJKHYjxx70NW4DAj1hJv1Yg== X-Google-Smtp-Source: AGHT+IGjuZLRi/UoPCLV8pq6HbZpSI5aU7b+uUckhb9IoPIN7CC9MujtSgARESM9BmbUzBeAdjqa X-Received: by 2002:ae9:e644:0:b0:78b:ddda:82b5 with SMTP id x4-20020ae9e644000000b0078bddda82b5mr3356181qkl.50.1712935068000; Fri, 12 Apr 2024 08:17:48 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1712935067; cv=pass; d=google.com; s=arc-20160816; b=ILMlrRguCY/QhLdeLns25UHGSsZemV6bznKjQQTBKX4tAb120PeioRMFxpSHio324s UDoSvOAjF3+ZfvLaOvIrKfEh2AgGByIsDLJ5M9SU9Rqm5PoBF0psxL9B1Z9vQoEoz2Od gePuRTz44lzG76w2UG9orcA3rFINADbb6XnPgtrvW8KGnZVUVayb1wR/Dc7k9lNVwLfr 99KV/ShAApnzJlUDbr1WYe6l8IW2KLnoPR0GEr+w+kAZbGAeVwsP3RYsBgBTP/Um+sgF W7aZwBUyeAKqZ/3Dz6H0c/Ds/ZC7hGNmU40ujoPVXFcNQXaKeXAy/+8tVntQFHlZxyZ7 gVoQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature:dkim-signature; bh=uPYxr/Er+fWtv8wZe5AP8h36917nOHnZyZPf9ZFqN/I=; fh=DAnO+8H9Lrjcim3e4g9UJ7i5/NAoU4yGt1+mKcjwm4A=; b=yMc1Ga3yLdwNRYqbd1a5v+eEhswIp6MRfaseElVM+YEwmKtO4VJXOhzfL9vp9O1a3A mt2Ryz/rAlhphBINneg6wGFv8PAcer8kkuC/F7uMfsTk/3lCJomB3X0l2apSAP2i5vAp iHps0fMta8HwueaCRds4kr2lh1wVUuPO6LBQ/sOSfT7IYH1YGYfN6sXBUtFAKjp6biIv maaRBwKm1hEqyoGyD/P0yjduKTMzP+H6J++Lra6qZ3hIPY5ib5vjlcA8ncxyR8loKdhf obwWNhMrAf2Od4F7E9TvTXxRtrXEMhDviS+i16VaZv2wk49qC2t3enecAi8lWKbhR7jF tZZA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@suse.com header.s=susede1 header.b=jH6DHQ21; dkim=pass header.i=@suse.com header.s=susede1 header.b=jH6DHQ21; arc=pass (i=1 spf=pass spfdomain=suse.com dkim=pass dkdomain=suse.com dkim=pass dkdomain=suse.com dmarc=pass fromdomain=suse.com); spf=pass (google.com: domain of linux-kernel+bounces-142920-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-142920-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=suse.com Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id vr16-20020a05620a55b000b0078ecd2742casi1297814qkn.145.2024.04.12.08.17.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Apr 2024 08:17:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-142920-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@suse.com header.s=susede1 header.b=jH6DHQ21; dkim=pass header.i=@suse.com header.s=susede1 header.b=jH6DHQ21; arc=pass (i=1 spf=pass spfdomain=suse.com dkim=pass dkdomain=suse.com dkim=pass dkdomain=suse.com dmarc=pass fromdomain=suse.com); spf=pass (google.com: domain of linux-kernel+bounces-142920-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-142920-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=suse.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 8D90F1C2152C for ; Fri, 12 Apr 2024 15:17:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6F9D114900B; Fri, 12 Apr 2024 15:13:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="jH6DHQ21"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="jH6DHQ21" Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFA3B1482ED for ; Fri, 12 Apr 2024 15:13:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712934819; cv=none; b=gllRK1sUrDejbkCRtPInHRUQdQ8yV43HfcRoTqtnNq9a6/+Xo9txOy6ISP4eKkK7UmlVSl31BXZ1XUkEMs+YHDOMck1Fq88PtHxR5/VPIcCjkPjCZ5GREzrv4spO0paGIC1NkFOshPfh/pkxh2krssaV/sH1hdqTEyvK4eCu9jk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712934819; c=relaxed/simple; bh=7ZATv9FDwuL7DkpjJIpgT4aYqLVn3V0wxJUMj5+sp6w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uk7t6XiQGBupdOfRUrau8iFHVGRKnhQ4Tn065gVq9RuUd9zOGJnjCGnwspOQkHy1CZ7xhFWZXQJup0H+14FEnMtbi6E1cTtIySWRg5vnnnbJA+NnsTc9qvgeEs4ZLRAHTRbvZyao45pDBRbRBOpjqyCcDOHFj3kcnk0XlyCwehg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=jH6DHQ21; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=jH6DHQ21; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 34A065FE6E; Fri, 12 Apr 2024 15:13:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1712934816; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uPYxr/Er+fWtv8wZe5AP8h36917nOHnZyZPf9ZFqN/I=; b=jH6DHQ21N/Q5KuPdBFHykQKzyWAp3ww+K0ijb/3kTFifHOv1xhXmP2SJZ3Eytkw8FnNg+1 Tya2cG8kp1tR/AsYPQr0kEmrFSrqJi9EyIqcuNAZaMikUmB77ifzsNaFACYqEEM6kbqM53 T6Il3To6krAhyLz2HetKtbZ6t+fsFJU= Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1712934816; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uPYxr/Er+fWtv8wZe5AP8h36917nOHnZyZPf9ZFqN/I=; b=jH6DHQ21N/Q5KuPdBFHykQKzyWAp3ww+K0ijb/3kTFifHOv1xhXmP2SJZ3Eytkw8FnNg+1 Tya2cG8kp1tR/AsYPQr0kEmrFSrqJi9EyIqcuNAZaMikUmB77ifzsNaFACYqEEM6kbqM53 T6Il3To6krAhyLz2HetKtbZ6t+fsFJU= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id D21FF1368B; Fri, 12 Apr 2024 15:13:34 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id zxaPLp5PGWbDAQAAD6G6ig (envelope-from ); Fri, 12 Apr 2024 15:13:34 +0000 From: Juergen Gross To: linux-kernel@vger.kernel.org, x86@kernel.org Cc: Juergen Gross , Dave Hansen , Andy Lutomirski , Peter Zijlstra , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , Jason Andryuk Subject: [PATCH v2 4/4] x86/pat: fix W^X violation false-positives when running as Xen PV guest Date: Fri, 12 Apr 2024 17:12:58 +0200 Message-Id: <20240412151258.9171-5-jgross@suse.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240412151258.9171-1-jgross@suse.com> References: <20240412151258.9171-1-jgross@suse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Flag: NO X-Spam-Score: -2.80 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_HAS_DN(0.00)[]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_CC(0.00)[suse.com,linux.intel.com,kernel.org,infradead.org,linutronix.de,redhat.com,alien8.de,zytor.com,gmail.com]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:email,imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; RCPT_COUNT_SEVEN(0.00)[11]; FUZZY_BLOCKED(0.00)[rspamd.com]; TO_DN_SOME(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FREEMAIL_ENVRCPT(0.00)[gmail.com] When running as Xen PV guest in some cases W^X violation WARN()s have been observed. Those WARN()s are produced by verify_rwx(), which looks into the PTE to verify that writable kernel pages have the NX bit set in order to avoid code modifications of the kernel by rogue code. As the NX bits of all levels of translation entries are or-ed and the RW bits of all levels are and-ed, looking just into the PTE isn't enough for the decision that a writable page is executable, too. When running as a Xen PV guest, the direct map PMDs and kernel high map PMDs share the same set of PTEs. Xen kernel initialization will set the NX bit in the direct map PMD entries, and not the shared PTEs. Fixes: 652c5bf380ad ("x86/mm: Refuse W^X violations") Reported-by: Jason Andryuk Signed-off-by: Juergen Gross --- V2: - patch split (Ingo Molnar) - commit message reworded (Jason Andryuk) --- arch/x86/mm/pat/set_memory.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 4ebccaf29bf2..19fdfbb171ed 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -619,7 +619,8 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start, * Validate strict W^X semantics. */ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long start, - unsigned long pfn, unsigned long npg) + unsigned long pfn, unsigned long npg, + bool nx, bool rw) { unsigned long end; @@ -641,6 +642,10 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star if ((pgprot_val(new) & (_PAGE_RW | _PAGE_NX)) != _PAGE_RW) return new; + /* Non-leaf translation entries can disable writing or execution. */ + if (!rw || nx) + return new; + end = start + npg * PAGE_SIZE - 1; WARN_ONCE(1, "CPA detected W^X violation: %016llx -> %016llx range: 0x%016lx - 0x%016lx PFN %lx\n", (unsigned long long)pgprot_val(old), @@ -742,7 +747,7 @@ pte_t *lookup_address(unsigned long address, unsigned int *level) EXPORT_SYMBOL_GPL(lookup_address); static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address, - unsigned int *level) + unsigned int *level, bool *nx, bool *rw) { pgd_t *pgd; @@ -751,7 +756,7 @@ static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address, else pgd = cpa->pgd + pgd_index(address); - return lookup_address_in_pgd(pgd, address, level); + return lookup_address_in_pgd_attr(pgd, address, level, nx, rw); } /* @@ -879,12 +884,13 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address, pgprot_t old_prot, new_prot, req_prot, chk_prot; pte_t new_pte, *tmp; enum pg_level level; + bool nx, rw; /* * Check for races, another CPU might have split this page * up already: */ - tmp = _lookup_address_cpa(cpa, address, &level); + tmp = _lookup_address_cpa(cpa, address, &level, &nx, &rw); if (tmp != kpte) return 1; @@ -995,7 +1001,8 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address, new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages, psize, CPA_DETECT); - new_prot = verify_rwx(old_prot, new_prot, lpaddr, old_pfn, numpages); + new_prot = verify_rwx(old_prot, new_prot, lpaddr, old_pfn, numpages, + nx, rw); /* * If there is a conflict, split the large page. @@ -1076,6 +1083,7 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address, pte_t *pbase = (pte_t *)page_address(base); unsigned int i, level; pgprot_t ref_prot; + bool nx, rw; pte_t *tmp; spin_lock(&pgd_lock); @@ -1083,7 +1091,7 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address, * Check for races, another CPU might have split this page * up for us already: */ - tmp = _lookup_address_cpa(cpa, address, &level); + tmp = _lookup_address_cpa(cpa, address, &level, &nx, &rw); if (tmp != kpte) { spin_unlock(&pgd_lock); return 1; @@ -1624,10 +1632,11 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) int do_split, err; unsigned int level; pte_t *kpte, old_pte; + bool nx, rw; address = __cpa_addr(cpa, cpa->curpage); repeat: - kpte = _lookup_address_cpa(cpa, address, &level); + kpte = _lookup_address_cpa(cpa, address, &level, &nx, &rw); if (!kpte) return __cpa_process_fault(cpa, address, primary); @@ -1649,7 +1658,8 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) new_prot = static_protections(new_prot, address, pfn, 1, 0, CPA_PROTECT); - new_prot = verify_rwx(old_prot, new_prot, address, pfn, 1); + new_prot = verify_rwx(old_prot, new_prot, address, pfn, 1, + nx, rw); new_prot = pgprot_clear_protnone_bits(new_prot); -- 2.35.3