Unverified Commit d47d6369 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!5610 [sync] PR-5447: Fix CVE-2021-47094

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/5447 
 
PR sync from: Liu Shixin <liushixin2@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/75L4J5XHJZPPNZLBKF7G4LLXLQ3VGBJF/ 
The first patch is a cleanup patch and no functional change.
The second patch is bugfix for CVE-2021-47094.

Ben Gardon (1):
  KVM: x86/mmu: Factor out tdp_iter_return_to_root

Sean Christopherson (1):
  KVM: x86/mmu: Don't advance iterator after restart due to yielding


-- 
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/I95REM 
 
Link:https://gitee.com/openeuler/kernel/pulls/5610

 

Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents d0577e25 0105ee95
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -20,6 +20,22 @@ static gfn_t round_gfn_for_level(gfn_t gfn, int level)
	return gfn & -KVM_PAGES_PER_HPAGE(level);
}

/*
 * Return the TDP iterator to the root PT and allow it to continue its
 * traversal over the paging structure from there.
 */
void tdp_iter_restart(struct tdp_iter *iter)
{
	iter->yielded = false;
	iter->yielded_gfn = iter->next_last_level_gfn;
	iter->level = iter->root_level;

	iter->gfn = round_gfn_for_level(iter->next_last_level_gfn, iter->level);
	tdp_iter_refresh_sptep(iter);

	iter->valid = true;
}

/*
 * Sets a TDP iterator to walk a pre-order traversal of the paging structure
 * rooted at root_pt, starting with the walk to translate next_last_level_gfn.
@@ -31,16 +47,11 @@ void tdp_iter_start(struct tdp_iter *iter, u64 *root_pt, int root_level,
	WARN_ON(root_level > PT64_ROOT_MAX_LEVEL);

	iter->next_last_level_gfn = next_last_level_gfn;
	iter->yielded_gfn = iter->next_last_level_gfn;
	iter->root_level = root_level;
	iter->min_level = min_level;
	iter->level = root_level;
	iter->pt_path[iter->level - 1] = root_pt;

	iter->gfn = round_gfn_for_level(iter->next_last_level_gfn, iter->level);
	tdp_iter_refresh_sptep(iter);
	iter->pt_path[iter->root_level - 1] = root_pt;

	iter->valid = true;
	tdp_iter_restart(iter);
}

/*
@@ -149,6 +160,11 @@ static bool try_step_up(struct tdp_iter *iter)
 */
void tdp_iter_next(struct tdp_iter *iter)
{
	if (iter->yielded) {
		tdp_iter_restart(iter);
		return;
	}

	if (try_step_down(iter))
		return;

+7 −0
Original line number Diff line number Diff line
@@ -41,6 +41,12 @@ struct tdp_iter {
	 * iterator walks off the end of the paging structure.
	 */
	bool valid;
	/*
	 * True if KVM dropped mmu_lock and yielded in the middle of a walk, in
	 * which case tdp_iter_next() needs to restart the walk at the root
	 * level instead of advancing to the next entry.
	 */
	bool yielded;
};

/*
@@ -61,5 +67,6 @@ void tdp_iter_start(struct tdp_iter *iter, u64 *root_pt, int root_level,
		    int min_level, gfn_t next_last_level_gfn);
void tdp_iter_next(struct tdp_iter *iter);
u64 *tdp_iter_root_pt(struct tdp_iter *iter);
void tdp_iter_restart(struct tdp_iter *iter);

#endif /* __KVM_X86_MMU_TDP_ITER_H */
+14 −14
Original line number Diff line number Diff line
@@ -357,6 +357,8 @@ static inline void __tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter,
	struct kvm_mmu_page *root = sptep_to_sp(root_pt);
	int as_id = kvm_mmu_page_as_id(root);

	WARN_ON_ONCE(iter->yielded);

	WRITE_ONCE(*iter->sptep, new_spte);

	__handle_changed_spte(kvm, as_id, iter->gfn, iter->old_spte, new_spte,
@@ -411,17 +413,19 @@ static inline void tdp_mmu_set_spte_no_dirty_log(struct kvm *kvm,
 * If this function should yield and flush is set, it will perform a remote
 * TLB flush before yielding.
 *
 * If this function yields, it will also reset the tdp_iter's walk over the
 * paging structure and the calling function should skip to the next
 * iteration to allow the iterator to continue its traversal from the
 * paging structure root.
 * If this function yields, iter->yielded is set and the caller must skip to
 * the next iteration, where tdp_iter_next() will reset the tdp_iter's walk
 * over the paging structures to allow the iterator to continue its traversal
 * from the paging structure root.
 *
 * Return true if this function yielded and the iterator's traversal was reset.
 * Return false if a yield was not needed.
 * Returns true if this function yielded.
 */
static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm,
					     struct tdp_iter *iter, bool flush)
static inline bool __must_check tdp_mmu_iter_cond_resched(struct kvm *kvm,
							  struct tdp_iter *iter,
							  bool flush)
{
	WARN_ON(iter->yielded);

	/* Ensure forward progress has been made before yielding. */
	if (iter->next_last_level_gfn == iter->yielded_gfn)
		return false;
@@ -434,14 +438,10 @@ static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm,

		WARN_ON(iter->gfn > iter->next_last_level_gfn);

		tdp_iter_start(iter, iter->pt_path[iter->root_level - 1],
			       iter->root_level, iter->min_level,
			       iter->next_last_level_gfn);

		return true;
		iter->yielded = true;
	}

	return false;
	return iter->yielded;
}

/*