All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathias Krause <minipli@grsecurity.net>
To: kvm@vger.kernel.org
Cc: Mathias Krause <minipli@grsecurity.net>
Subject: [kvm-unit-tests PATCH v2 2/4] x86/access: CR0.WP toggling write to r/o data test
Date: Fri, 31 Mar 2023 15:57:07 +0200	[thread overview]
Message-ID: <20230331135709.132713-3-minipli@grsecurity.net> (raw)
In-Reply-To: <20230331135709.132713-1-minipli@grsecurity.net>

We already have tests that verify a write access to an r/o page is
successful when CR0.WP=0, but we lack a test that explicitly verifies
that the same access will fail after we set CR0.WP=1 without flushing
any associated TLB entries either explicitly (INVLPG) or implicitly
(write to CR3). Add such a test.

Signed-off-by: Mathias Krause <minipli@grsecurity.net>
---
 x86/access.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/x86/access.c b/x86/access.c
index 203353a3f74f..d1ec99b4fa73 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -575,9 +575,10 @@ fault:
 		at->expected_error &= ~PFERR_FETCH_MASK;
 }
 
-static void ac_set_expected_status(ac_test_t *at)
+static void __ac_set_expected_status(ac_test_t *at, bool flush)
 {
-	invlpg(at->virt);
+	if (flush)
+		invlpg(at->virt);
 
 	if (at->ptep)
 		at->expected_pte = *at->ptep;
@@ -599,6 +600,11 @@ static void ac_set_expected_status(ac_test_t *at)
 	ac_emulate_access(at, at->flags);
 }
 
+static void ac_set_expected_status(ac_test_t *at)
+{
+	__ac_set_expected_status(at, true);
+}
+
 static pt_element_t ac_get_pt(ac_test_t *at, int i, pt_element_t *ptep)
 {
 	pt_element_t pte;
@@ -1061,6 +1067,51 @@ err:
 	return 0;
 }
 
+static int check_write_cr0wp(ac_pt_env_t *pt_env)
+{
+	ac_test_t at;
+	int err = 0;
+
+	ac_test_init(&at, 0xffff923042007000ul, pt_env);
+	at.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK |
+		   AC_PDE_ACCESSED_MASK | AC_PTE_ACCESSED_MASK |
+		   AC_ACCESS_WRITE_MASK;
+	ac_test_setup_ptes(&at);
+
+	/*
+	 * Under VMX the guest might own the CR0.WP bit, requiring KVM to
+	 * manually keep track of its state where needed, e.g. in the guest
+	 * page table walker.
+	 *
+	 * We load CR0.WP with the inverse value of what would be used during
+	 * the access test and toggle EFER.NX to flush and rebuild the current
+	 * MMU context based on that value.
+	 */
+
+	set_cr0_wp(1);
+	set_efer_nx(1);
+	set_efer_nx(0);
+
+	if (!ac_test_do_access(&at)) {
+		printf("%s: CR0.WP=0 r/o write fail\n", __FUNCTION__);
+		err++;
+	}
+
+	at.flags |= AC_CPU_CR0_WP_MASK;
+	__ac_set_expected_status(&at, false);
+
+	set_cr0_wp(0);
+	set_efer_nx(1);
+	set_efer_nx(0);
+
+	if (!ac_test_do_access(&at)) {
+		printf("%s: CR0.WP=1 r/o write deny fail\n", __FUNCTION__);
+		err++;
+	}
+
+	return err == 0;
+}
+
 static int check_effective_sp_permissions(ac_pt_env_t *pt_env)
 {
 	unsigned long ptr1 = 0xffff923480000000;
@@ -1150,6 +1201,7 @@ const ac_test_fn ac_test_cases[] =
 	check_pfec_on_prefetch_pte,
 	check_large_pte_dirty_for_nowp,
 	check_smep_andnot_wp,
+	check_write_cr0wp,
 	check_effective_sp_permissions,
 };
 
-- 
2.39.2


  parent reply	other threads:[~2023-03-31 13:57 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-31 13:57 [kvm-unit-tests PATCH v2 0/4] Tests for CR0.WP=0/1 r/o write access Mathias Krause
2023-03-31 13:57 ` [kvm-unit-tests PATCH v2 1/4] x86: Use existing CR0.WP / CR4.SMEP bit definitions Mathias Krause
2023-03-31 16:02   ` Sean Christopherson
2023-03-31 13:57 ` Mathias Krause [this message]
2023-03-31 16:20   ` [kvm-unit-tests PATCH v2 2/4] x86/access: CR0.WP toggling write to r/o data test Sean Christopherson
2023-04-03  9:01     ` Mathias Krause
2023-04-03 17:09       ` Sean Christopherson
2023-03-31 13:57 ` [kvm-unit-tests PATCH v2 3/4] x86/access: Forced emulation support Mathias Krause
2023-03-31 16:24   ` Sean Christopherson
2023-04-03  9:08     ` Mathias Krause
2023-03-31 13:57 ` [kvm-unit-tests PATCH v2 4/4] x86/access: Try emulation for CR0.WP test as well Mathias Krause
2023-03-31 16:24   ` Sean Christopherson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230331135709.132713-3-minipli@grsecurity.net \
    --to=minipli@grsecurity.net \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.