diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/mmu_audit.c | 42 |
1 files changed, 18 insertions, 24 deletions
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c index dcca3e7d7b4e..66219afcc91e 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu_audit.c | |||
@@ -19,7 +19,11 @@ | |||
19 | 19 | ||
20 | #include <linux/ratelimit.h> | 20 | #include <linux/ratelimit.h> |
21 | 21 | ||
22 | static const char *audit_msg; | 22 | static int audit_point; |
23 | |||
24 | #define audit_printk(fmt, args...) \ | ||
25 | printk(KERN_ERR "audit: (%s) error: " \ | ||
26 | fmt, audit_point_name[audit_point], ##args) | ||
23 | 27 | ||
24 | typedef void (*inspect_spte_fn) (struct kvm_vcpu *vcpu, u64 *sptep, int level); | 28 | typedef void (*inspect_spte_fn) (struct kvm_vcpu *vcpu, u64 *sptep, int level); |
25 | 29 | ||
@@ -93,21 +97,18 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level) | |||
93 | 97 | ||
94 | if (sp->unsync) { | 98 | if (sp->unsync) { |
95 | if (level != PT_PAGE_TABLE_LEVEL) { | 99 | if (level != PT_PAGE_TABLE_LEVEL) { |
96 | printk(KERN_ERR "audit: (%s) error: unsync sp: %p level = %d\n", | 100 | audit_printk("unsync sp: %p level = %d\n", sp, level); |
97 | audit_msg, sp, level); | ||
98 | return; | 101 | return; |
99 | } | 102 | } |
100 | 103 | ||
101 | if (*sptep == shadow_notrap_nonpresent_pte) { | 104 | if (*sptep == shadow_notrap_nonpresent_pte) { |
102 | printk(KERN_ERR "audit: (%s) error: notrap spte in unsync sp: %p\n", | 105 | audit_printk("notrap spte in unsync sp: %p\n", sp); |
103 | audit_msg, sp); | ||
104 | return; | 106 | return; |
105 | } | 107 | } |
106 | } | 108 | } |
107 | 109 | ||
108 | if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) { | 110 | if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) { |
109 | printk(KERN_ERR "audit: (%s) error: notrap spte in direct sp: %p\n", | 111 | audit_printk("notrap spte in direct sp: %p\n", sp); |
110 | audit_msg, sp); | ||
111 | return; | 112 | return; |
112 | } | 113 | } |
113 | 114 | ||
@@ -124,10 +125,8 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level) | |||
124 | 125 | ||
125 | hpa = pfn << PAGE_SHIFT; | 126 | hpa = pfn << PAGE_SHIFT; |
126 | if ((*sptep & PT64_BASE_ADDR_MASK) != hpa) | 127 | if ((*sptep & PT64_BASE_ADDR_MASK) != hpa) |
127 | printk(KERN_ERR "xx audit error: (%s) levels %d" | 128 | audit_printk("levels %d pfn %llx hpa %llx ent %llxn", |
128 | "pfn %llx hpa %llx ent %llxn", | 129 | vcpu->arch.mmu.root_level, pfn, hpa, *sptep); |
129 | audit_msg, vcpu->arch.mmu.root_level, | ||
130 | pfn, hpa, *sptep); | ||
131 | } | 130 | } |
132 | 131 | ||
133 | static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep) | 132 | static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep) |
@@ -143,11 +142,9 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep) | |||
143 | if (!gfn_to_memslot(kvm, gfn)) { | 142 | if (!gfn_to_memslot(kvm, gfn)) { |
144 | if (!printk_ratelimit()) | 143 | if (!printk_ratelimit()) |
145 | return; | 144 | return; |
146 | printk(KERN_ERR "%s: no memslot for gfn %llx\n", | 145 | audit_printk("no memslot for gfn %llx\n", gfn); |
147 | audit_msg, gfn); | 146 | audit_printk("index %ld of sp (gfn=%llx)\n", |
148 | printk(KERN_ERR "%s: index %ld of sp (gfn=%llx)\n", | 147 | (long int)(sptep - rev_sp->spt), rev_sp->gfn); |
149 | audit_msg, (long int)(sptep - rev_sp->spt), | ||
150 | rev_sp->gfn); | ||
151 | dump_stack(); | 148 | dump_stack(); |
152 | return; | 149 | return; |
153 | } | 150 | } |
@@ -156,8 +153,7 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep) | |||
156 | if (!*rmapp) { | 153 | if (!*rmapp) { |
157 | if (!printk_ratelimit()) | 154 | if (!printk_ratelimit()) |
158 | return; | 155 | return; |
159 | printk(KERN_ERR "%s: no rmap for writable spte %llx\n", | 156 | audit_printk("no rmap for writable spte %llx\n", *sptep); |
160 | audit_msg, *sptep); | ||
161 | dump_stack(); | 157 | dump_stack(); |
162 | } | 158 | } |
163 | } | 159 | } |
@@ -198,10 +194,8 @@ void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp) | |||
198 | spte = rmap_next(kvm, rmapp, NULL); | 194 | spte = rmap_next(kvm, rmapp, NULL); |
199 | while (spte) { | 195 | while (spte) { |
200 | if (is_writable_pte(*spte)) | 196 | if (is_writable_pte(*spte)) |
201 | printk(KERN_ERR "%s: (%s) shadow page has " | 197 | audit_printk("shadow page has writable mappings: gfn " |
202 | "writable mappings: gfn %llx role %x\n", | 198 | "%llx role %x\n", sp->gfn, sp->role.word); |
203 | __func__, audit_msg, sp->gfn, | ||
204 | sp->role.word); | ||
205 | spte = rmap_next(kvm, rmapp, spte); | 199 | spte = rmap_next(kvm, rmapp, spte); |
206 | } | 200 | } |
207 | } | 201 | } |
@@ -228,14 +222,14 @@ static void audit_vcpu_spte(struct kvm_vcpu *vcpu) | |||
228 | mmu_spte_walk(vcpu, audit_spte); | 222 | mmu_spte_walk(vcpu, audit_spte); |
229 | } | 223 | } |
230 | 224 | ||
231 | static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int audit_point) | 225 | static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int point) |
232 | { | 226 | { |
233 | static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10); | 227 | static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10); |
234 | 228 | ||
235 | if (!__ratelimit(&ratelimit_state)) | 229 | if (!__ratelimit(&ratelimit_state)) |
236 | return; | 230 | return; |
237 | 231 | ||
238 | audit_msg = audit_point_name[audit_point]; | 232 | audit_point = point; |
239 | audit_all_active_sps(vcpu->kvm); | 233 | audit_all_active_sps(vcpu->kvm); |
240 | audit_vcpu_spte(vcpu); | 234 | audit_vcpu_spte(vcpu); |
241 | } | 235 | } |