]> bbs.cooldavid.org Git - net-next-2.6.git/blob - arch/x86/kvm/mmu_audit.c
KVM: MMU: audit: introduce audit_printk to cleanup audit code
[net-next-2.6.git] / arch / x86 / kvm / mmu_audit.c
1 /*
2  * mmu_audit.c:
3  *
4  * Audit code for KVM MMU
5  *
6  * Copyright (C) 2006 Qumranet, Inc.
7  * Copyright 2010 Red Hat, Inc. and/or its affilates.
8  *
9  * Authors:
10  *   Yaniv Kamay  <yaniv@qumranet.com>
11  *   Avi Kivity   <avi@qumranet.com>
12  *   Marcelo Tosatti <mtosatti@redhat.com>
13  *   Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
14  *
15  * This work is licensed under the terms of the GNU GPL, version 2.  See
16  * the COPYING file in the top-level directory.
17  *
18  */
19
20 #include <linux/ratelimit.h>
21
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)
27
28 typedef void (*inspect_spte_fn) (struct kvm_vcpu *vcpu, u64 *sptep, int level);
29
30 static void __mmu_spte_walk(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
31                             inspect_spte_fn fn, int level)
32 {
33         int i;
34
35         for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
36                 u64 *ent = sp->spt;
37
38                 fn(vcpu, ent + i, level);
39
40                 if (is_shadow_present_pte(ent[i]) &&
41                       !is_last_spte(ent[i], level)) {
42                         struct kvm_mmu_page *child;
43
44                         child = page_header(ent[i] & PT64_BASE_ADDR_MASK);
45                         __mmu_spte_walk(vcpu, child, fn, level - 1);
46                 }
47         }
48 }
49
50 static void mmu_spte_walk(struct kvm_vcpu *vcpu, inspect_spte_fn fn)
51 {
52         int i;
53         struct kvm_mmu_page *sp;
54
55         if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
56                 return;
57
58         if (vcpu->arch.mmu.root_level == PT64_ROOT_LEVEL) {
59                 hpa_t root = vcpu->arch.mmu.root_hpa;
60
61                 sp = page_header(root);
62                 __mmu_spte_walk(vcpu, sp, fn, PT64_ROOT_LEVEL);
63                 return;
64         }
65
66         for (i = 0; i < 4; ++i) {
67                 hpa_t root = vcpu->arch.mmu.pae_root[i];
68
69                 if (root && VALID_PAGE(root)) {
70                         root &= PT64_BASE_ADDR_MASK;
71                         sp = page_header(root);
72                         __mmu_spte_walk(vcpu, sp, fn, 2);
73                 }
74         }
75
76         return;
77 }
78
79 typedef void (*sp_handler) (struct kvm *kvm, struct kvm_mmu_page *sp);
80
81 static void walk_all_active_sps(struct kvm *kvm, sp_handler fn)
82 {
83         struct kvm_mmu_page *sp;
84
85         list_for_each_entry(sp, &kvm->arch.active_mmu_pages, link)
86                 fn(kvm, sp);
87 }
88
89 static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)
90 {
91         struct kvm_mmu_page *sp;
92         gfn_t gfn;
93         pfn_t pfn;
94         hpa_t hpa;
95
96         sp = page_header(__pa(sptep));
97
98         if (sp->unsync) {
99                 if (level != PT_PAGE_TABLE_LEVEL) {
100                         audit_printk("unsync sp: %p level = %d\n", sp, level);
101                         return;
102                 }
103
104                 if (*sptep == shadow_notrap_nonpresent_pte) {
105                         audit_printk("notrap spte in unsync sp: %p\n", sp);
106                         return;
107                 }
108         }
109
110         if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) {
111                 audit_printk("notrap spte in direct sp: %p\n", sp);
112                 return;
113         }
114
115         if (!is_shadow_present_pte(*sptep) || !is_last_spte(*sptep, level))
116                 return;
117
118         gfn = kvm_mmu_page_get_gfn(sp, sptep - sp->spt);
119         pfn = gfn_to_pfn_atomic(vcpu->kvm, gfn);
120
121         if (is_error_pfn(pfn)) {
122                 kvm_release_pfn_clean(pfn);
123                 return;
124         }
125
126         hpa =  pfn << PAGE_SHIFT;
127         if ((*sptep & PT64_BASE_ADDR_MASK) != hpa)
128                 audit_printk("levels %d pfn %llx hpa %llx ent %llxn",
129                                    vcpu->arch.mmu.root_level, pfn, hpa, *sptep);
130 }
131
132 static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
133 {
134         unsigned long *rmapp;
135         struct kvm_mmu_page *rev_sp;
136         gfn_t gfn;
137
138
139         rev_sp = page_header(__pa(sptep));
140         gfn = kvm_mmu_page_get_gfn(rev_sp, sptep - rev_sp->spt);
141
142         if (!gfn_to_memslot(kvm, gfn)) {
143                 if (!printk_ratelimit())
144                         return;
145                 audit_printk("no memslot for gfn %llx\n", gfn);
146                 audit_printk("index %ld of sp (gfn=%llx)\n",
147                        (long int)(sptep - rev_sp->spt), rev_sp->gfn);
148                 dump_stack();
149                 return;
150         }
151
152         rmapp = gfn_to_rmap(kvm, gfn, rev_sp->role.level);
153         if (!*rmapp) {
154                 if (!printk_ratelimit())
155                         return;
156                 audit_printk("no rmap for writable spte %llx\n", *sptep);
157                 dump_stack();
158         }
159 }
160
161 static void audit_sptes_have_rmaps(struct kvm_vcpu *vcpu, u64 *sptep, int level)
162 {
163         if (is_shadow_present_pte(*sptep) && is_last_spte(*sptep, level))
164                 inspect_spte_has_rmap(vcpu->kvm, sptep);
165 }
166
167 static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp)
168 {
169         int i;
170
171         if (sp->role.level != PT_PAGE_TABLE_LEVEL)
172                 return;
173
174         for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
175                 if (!is_rmap_spte(sp->spt[i]))
176                         continue;
177
178                 inspect_spte_has_rmap(kvm, sp->spt + i);
179         }
180 }
181
182 void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
183 {
184         struct kvm_memory_slot *slot;
185         unsigned long *rmapp;
186         u64 *spte;
187
188         if (sp->role.direct || sp->unsync || sp->role.invalid)
189                 return;
190
191         slot = gfn_to_memslot(kvm, sp->gfn);
192         rmapp = &slot->rmap[sp->gfn - slot->base_gfn];
193
194         spte = rmap_next(kvm, rmapp, NULL);
195         while (spte) {
196                 if (is_writable_pte(*spte))
197                         audit_printk("shadow page has writable mappings: gfn "
198                                      "%llx role %x\n", sp->gfn, sp->role.word);
199                 spte = rmap_next(kvm, rmapp, spte);
200         }
201 }
202
203 static void audit_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
204 {
205         check_mappings_rmap(kvm, sp);
206         audit_write_protection(kvm, sp);
207 }
208
209 static void audit_all_active_sps(struct kvm *kvm)
210 {
211         walk_all_active_sps(kvm, audit_sp);
212 }
213
214 static void audit_spte(struct kvm_vcpu *vcpu, u64 *sptep, int level)
215 {
216         audit_sptes_have_rmaps(vcpu, sptep, level);
217         audit_mappings(vcpu, sptep, level);
218 }
219
220 static void audit_vcpu_spte(struct kvm_vcpu *vcpu)
221 {
222         mmu_spte_walk(vcpu, audit_spte);
223 }
224
225 static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int point)
226 {
227         static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
228
229         if (!__ratelimit(&ratelimit_state))
230                 return;
231
232         audit_point = point;
233         audit_all_active_sps(vcpu->kvm);
234         audit_vcpu_spte(vcpu);
235 }
236
237 static bool mmu_audit;
238
239 static void mmu_audit_enable(void)
240 {
241         int ret;
242
243         if (mmu_audit)
244                 return;
245
246         ret = register_trace_kvm_mmu_audit(kvm_mmu_audit, NULL);
247         WARN_ON(ret);
248
249         mmu_audit = true;
250 }
251
252 static void mmu_audit_disable(void)
253 {
254         if (!mmu_audit)
255                 return;
256
257         unregister_trace_kvm_mmu_audit(kvm_mmu_audit, NULL);
258         tracepoint_synchronize_unregister();
259         mmu_audit = false;
260 }
261
262 static int mmu_audit_set(const char *val, const struct kernel_param *kp)
263 {
264         int ret;
265         unsigned long enable;
266
267         ret = strict_strtoul(val, 10, &enable);
268         if (ret < 0)
269                 return -EINVAL;
270
271         switch (enable) {
272         case 0:
273                 mmu_audit_disable();
274                 break;
275         case 1:
276                 mmu_audit_enable();
277                 break;
278         default:
279                 return -EINVAL;
280         }
281
282         return 0;
283 }
284
285 static struct kernel_param_ops audit_param_ops = {
286         .set = mmu_audit_set,
287         .get = param_get_bool,
288 };
289
290 module_param_cb(mmu_audit, &audit_param_ops, &mmu_audit, 0644);