Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b034cf01 authored by Xiao Guangrong's avatar Xiao Guangrong Committed by Avi Kivity
Browse files

KVM: MMU: audit: allow audit more guests at the same time



It only allows to audit one guest in the system since:
- 'audit_point' is a glob variable
- mmu_audit_disable() is called in kvm_mmu_destroy(), so audit is disabled
  after a guest exited

this patch fix those issues then allow to audit more guests at the same time

Signed-off-by: default avatarXiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent aff48baa
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -461,6 +461,10 @@ struct kvm_arch {
	/* fields used by HYPER-V emulation */
	u64 hv_guest_os_id;
	u64 hv_hypercall;

	#ifdef CONFIG_KVM_MMU_AUDIT
	int audit_point;
	#endif
};

struct kvm_vm_stat {
+13 −13
Original line number Diff line number Diff line
@@ -3534,13 +3534,6 @@ static void mmu_destroy_caches(void)
		kmem_cache_destroy(mmu_page_header_cache);
}

void kvm_mmu_module_exit(void)
{
	mmu_destroy_caches();
	percpu_counter_destroy(&kvm_total_used_mmu_pages);
	unregister_shrinker(&mmu_shrinker);
}

int kvm_mmu_module_init(void)
{
	pte_chain_cache = kmem_cache_create("kvm_pte_chain",
@@ -3733,12 +3726,6 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])
}
EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy);

#ifdef CONFIG_KVM_MMU_AUDIT
#include "mmu_audit.c"
#else
static void mmu_audit_disable(void) { }
#endif

void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
{
	ASSERT(vcpu);
@@ -3746,5 +3733,18 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
	destroy_kvm_mmu(vcpu);
	free_mmu_pages(vcpu);
	mmu_free_memory_caches(vcpu);
}

#ifdef CONFIG_KVM_MMU_AUDIT
#include "mmu_audit.c"
#else
static void mmu_audit_disable(void) { }
#endif

void kvm_mmu_module_exit(void)
{
	mmu_destroy_caches();
	percpu_counter_destroy(&kvm_total_used_mmu_pages);
	unregister_shrinker(&mmu_shrinker);
	mmu_audit_disable();
}
+22 −17
Original line number Diff line number Diff line
@@ -19,11 +19,9 @@

#include <linux/ratelimit.h>

static int audit_point;

#define audit_printk(fmt, args...)		\
#define audit_printk(kvm, fmt, args...)		\
	printk(KERN_ERR "audit: (%s) error: "	\
		fmt, audit_point_name[audit_point], ##args)
		fmt, audit_point_name[kvm->arch.audit_point], ##args)

typedef void (*inspect_spte_fn) (struct kvm_vcpu *vcpu, u64 *sptep, int level);

@@ -97,18 +95,21 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)

	if (sp->unsync) {
		if (level != PT_PAGE_TABLE_LEVEL) {
			audit_printk("unsync sp: %p level = %d\n", sp, level);
			audit_printk(vcpu->kvm, "unsync sp: %p "
				     "level = %d\n", sp, level);
			return;
		}

		if (*sptep == shadow_notrap_nonpresent_pte) {
			audit_printk("notrap spte in unsync sp: %p\n", sp);
			audit_printk(vcpu->kvm, "notrap spte in unsync "
				     "sp: %p\n", sp);
			return;
		}
	}

	if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) {
		audit_printk("notrap spte in direct sp: %p\n", sp);
		audit_printk(vcpu->kvm, "notrap spte in direct sp: %p\n",
			     sp);
		return;
	}

@@ -125,8 +126,9 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)

	hpa =  pfn << PAGE_SHIFT;
	if ((*sptep & PT64_BASE_ADDR_MASK) != hpa)
		audit_printk("levels %d pfn %llx hpa %llx ent %llxn",
				   vcpu->arch.mmu.root_level, pfn, hpa, *sptep);
		audit_printk(vcpu->kvm, "levels %d pfn %llx hpa %llx "
			     "ent %llxn", vcpu->arch.mmu.root_level, pfn,
			     hpa, *sptep);
}

static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
@@ -142,8 +144,8 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
	if (!gfn_to_memslot(kvm, gfn)) {
		if (!printk_ratelimit())
			return;
		audit_printk("no memslot for gfn %llx\n", gfn);
		audit_printk("index %ld of sp (gfn=%llx)\n",
		audit_printk(kvm, "no memslot for gfn %llx\n", gfn);
		audit_printk(kvm, "index %ld of sp (gfn=%llx)\n",
		       (long int)(sptep - rev_sp->spt), rev_sp->gfn);
		dump_stack();
		return;
@@ -153,7 +155,8 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
	if (!*rmapp) {
		if (!printk_ratelimit())
			return;
		audit_printk("no rmap for writable spte %llx\n", *sptep);
		audit_printk(kvm, "no rmap for writable spte %llx\n",
			     *sptep);
		dump_stack();
	}
}
@@ -168,8 +171,9 @@ static void audit_spte_after_sync(struct kvm_vcpu *vcpu, u64 *sptep, int level)
{
	struct kvm_mmu_page *sp = page_header(__pa(sptep));

	if (audit_point == AUDIT_POST_SYNC && sp->unsync)
		audit_printk("meet unsync sp(%p) after sync root.\n", sp);
	if (vcpu->kvm->arch.audit_point == AUDIT_POST_SYNC && sp->unsync)
		audit_printk(vcpu->kvm, "meet unsync sp(%p) after sync "
			     "root.\n", sp);
}

static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp)
@@ -202,8 +206,9 @@ static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
	spte = rmap_next(kvm, rmapp, NULL);
	while (spte) {
		if (is_writable_pte(*spte))
			audit_printk("shadow page has writable mappings: gfn "
				     "%llx role %x\n", sp->gfn, sp->role.word);
			audit_printk(kvm, "shadow page has writable "
				     "mappings: gfn %llx role %x\n",
				     sp->gfn, sp->role.word);
		spte = rmap_next(kvm, rmapp, spte);
	}
}
@@ -238,7 +243,7 @@ static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int point)
	if (!__ratelimit(&ratelimit_state))
		return;

	audit_point = point;
	vcpu->kvm->arch.audit_point = point;
	audit_all_active_sps(vcpu->kvm);
	audit_vcpu_spte(vcpu);
}