Patch "KVM: arm64: Reload PTE after invoking walker callback on preorder traversal" has been added to the 6.3-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    KVM: arm64: Reload PTE after invoking walker callback on preorder traversal

to the 6.3-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-reload-pte-after-invoking-walker-callback-.patch
and it can be found in the queue-6.3 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 1a08fe1e4ac12f99a1725b0f92ef5ba9976bacf9
Author: Fuad Tabba <tabba@xxxxxxxxxx>
Date:   Mon May 22 11:32:58 2023 +0100

    KVM: arm64: Reload PTE after invoking walker callback on preorder traversal
    
    [ Upstream commit a9f0e3d5a089d0844abb679a5e99f15010d53e25 ]
    
    The preorder callback on the kvm_pgtable_stage2_map() path can replace
    a table with a block, then recursively free the detached table. The
    higher-level walking logic stashes the old page table entry and
    then walks the freed table, invoking the leaf callback and
    potentially freeing pgtable pages prematurely.
    
    In normal operation, the call to tear down the detached stage-2
    is indirected and uses an RCU callback to trigger the freeing.
    RCU is not available to pKVM, which is where this bug is
    triggered.
    
    Change the behavior of the walker to reload the page table entry
    after invoking the walker callback on preorder traversal, as it
    does for leaf entries.
    
    Tested on Pixel 6.
    
    Fixes: 5c359cca1faf ("KVM: arm64: Tear down unlinked stage-2 subtree after break-before-make")
    Suggested-by: Oliver Upton <oliver.upton@xxxxxxxxx>
    Signed-off-by: Fuad Tabba <tabba@xxxxxxxxxx>
    Signed-off-by: Marc Zyngier <maz@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230522103258.402272-1-tabba@xxxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index dc3c072e862f1..93bd0975b15f5 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -632,9 +632,9 @@ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size);
  *
  * The walker will walk the page-table entries corresponding to the input
  * address range specified, visiting entries according to the walker flags.
- * Invalid entries are treated as leaf entries. Leaf entries are reloaded
- * after invoking the walker callback, allowing the walker to descend into
- * a newly installed table.
+ * Invalid entries are treated as leaf entries. The visited page table entry is
+ * reloaded after invoking the walker callback, allowing the walker to descend
+ * into a newly installed table.
  *
  * Returning a negative error code from the walker callback function will
  * terminate the walk immediately with the same error code.
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 140f82300db5a..faddf1e71c8de 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -209,14 +209,26 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
 		.flags	= flags,
 	};
 	int ret = 0;
+	bool reload = false;
 	kvm_pteref_t childp;
 	bool table = kvm_pte_table(ctx.old, level);
 
-	if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE))
+	if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE)) {
 		ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_PRE);
+		reload = true;
+	}
 
 	if (!table && (ctx.flags & KVM_PGTABLE_WALK_LEAF)) {
 		ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_LEAF);
+		reload = true;
+	}
+
+	/*
+	 * Reload the page table after invoking the walker callback for leaf
+	 * entries or after pre-order traversal, to allow the walker to descend
+	 * into a newly installed or replaced table.
+	 */
+	if (reload) {
 		ctx.old = READ_ONCE(*ptep);
 		table = kvm_pte_table(ctx.old, level);
 	}



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux