]> git.pld-linux.org Git - packages/xen.git/blame - CVE-2013-1918-4
- rel 4
[packages/xen.git] / CVE-2013-1918-4
CommitLineData
23d51c33
JR
1Description: x86: make vcpu_reset() preemptible
2 ... as dropping the old page tables may take significant amounts of
3 time.
4From: Jan Beulich <jbeulich@suse.com>
5Origin: upstream
6Id: CVE-2013-1918 XSA-45
7---
8--- a/xen/arch/x86/domain.c
9+++ b/xen/arch/x86/domain.c
10@@ -1051,17 +1051,16 @@ int arch_set_info_guest(
11 #undef c
12 }
13
14-void arch_vcpu_reset(struct vcpu *v)
15+int arch_vcpu_reset(struct vcpu *v)
16 {
17 if ( !is_hvm_vcpu(v) )
18 {
19 destroy_gdt(v);
20- vcpu_destroy_pagetables(v, 0);
21- }
22- else
23- {
24- vcpu_end_shutdown_deferral(v);
25+ return vcpu_destroy_pagetables(v);
26 }
27+
28+ vcpu_end_shutdown_deferral(v);
29+ return 0;
30 }
31
32 /*
33@@ -2085,7 +2084,7 @@ int domain_relinquish_resources(struct domain *d)
34 /* Drop the in-use references to page-table bases. */
35 for_each_vcpu ( d, v )
36 {
37- ret = vcpu_destroy_pagetables(v, 1);
38+ ret = vcpu_destroy_pagetables(v);
39 if ( ret )
40 return ret;
41 }
42--- a/xen/arch/x86/hvm/hvm.c
43+++ b/xen/arch/x86/hvm/hvm.c
44@@ -3509,8 +3509,11 @@ static void hvm_s3_suspend(struct domain *d)
45
46 for_each_vcpu ( d, v )
47 {
48+ int rc;
49+
50 vlapic_reset(vcpu_vlapic(v));
51- vcpu_reset(v);
52+ rc = vcpu_reset(v);
53+ ASSERT(!rc);
54 }
55
56 vpic_reset(d);
57--- a/xen/arch/x86/hvm/vlapic.c
58+++ b/xen/arch/x86/hvm/vlapic.c
59@@ -252,10 +252,13 @@ static void vlapic_init_sipi_action(unsigned long _vcpu)
60 {
61 case APIC_DM_INIT: {
62 bool_t fpu_initialised;
63+ int rc;
64+
65 domain_lock(target->domain);
66 /* Reset necessary VCPU state. This does not include FPU state. */
67 fpu_initialised = target->fpu_initialised;
68- vcpu_reset(target);
69+ rc = vcpu_reset(target);
70+ ASSERT(!rc);
71 target->fpu_initialised = fpu_initialised;
72 vlapic_reset(vcpu_vlapic(target));
73 domain_unlock(target->domain);
74--- a/xen/arch/x86/mm.c
75+++ b/xen/arch/x86/mm.c
76@@ -2827,7 +2827,7 @@ static int put_old_guest_table(struct vcpu *v)
77 return rc;
78 }
79
80-int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible)
81+int vcpu_destroy_pagetables(struct vcpu *v)
82 {
83 unsigned long mfn = pagetable_get_pfn(v->arch.guest_table);
84 struct page_info *page;
85@@ -2847,7 +2847,7 @@ int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible)
86 if ( paging_mode_refcounts(v->domain) )
87 put_page(page);
88 else
89- rc = put_page_and_type_preemptible(page, preemptible);
90+ rc = put_page_and_type_preemptible(page, 1);
91 }
92
93 #ifdef __x86_64__
94@@ -2873,7 +2873,7 @@ int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible)
95 if ( paging_mode_refcounts(v->domain) )
96 put_page(page);
97 else
98- rc = put_page_and_type_preemptible(page, preemptible);
99+ rc = put_page_and_type_preemptible(page, 1);
100 }
101 if ( !rc )
102 v->arch.guest_table_user = pagetable_null();
103--- a/xen/common/domain.c
104+++ b/xen/common/domain.c
105@@ -779,14 +779,18 @@ void domain_unpause_by_systemcontroller(struct domain *d)
106 domain_unpause(d);
107 }
108
109-void vcpu_reset(struct vcpu *v)
110+int vcpu_reset(struct vcpu *v)
111 {
112 struct domain *d = v->domain;
113+ int rc;
114
115 vcpu_pause(v);
116 domain_lock(d);
117
118- arch_vcpu_reset(v);
119+ set_bit(_VPF_in_reset, &v->pause_flags);
120+ rc = arch_vcpu_reset(v);
121+ if ( rc )
122+ goto out_unlock;
123
124 set_bit(_VPF_down, &v->pause_flags);
125
126@@ -802,9 +806,13 @@ void vcpu_reset(struct vcpu *v)
127 #endif
128 cpumask_clear(v->cpu_affinity_tmp);
129 clear_bit(_VPF_blocked, &v->pause_flags);
130+ clear_bit(_VPF_in_reset, &v->pause_flags);
131
132+ out_unlock:
133 domain_unlock(v->domain);
134 vcpu_unpause(v);
135+
136+ return rc;
137 }
138
139
140--- a/xen/common/domctl.c
141+++ b/xen/common/domctl.c
142@@ -307,8 +307,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
143
144 if ( guest_handle_is_null(op->u.vcpucontext.ctxt) )
145 {
146- vcpu_reset(v);
147- ret = 0;
148+ ret = vcpu_reset(v);
149+ if ( ret == -EAGAIN )
150+ ret = hypercall_create_continuation(
151+ __HYPERVISOR_domctl, "h", u_domctl);
152 goto svc_out;
153 }
154
155--- a/xen/include/asm-x86/mm.h
156+++ b/xen/include/asm-x86/mm.h
157@@ -605,7 +605,7 @@ void audit_domains(void);
158 int new_guest_cr3(unsigned long pfn);
159 void make_cr3(struct vcpu *v, unsigned long mfn);
160 void update_cr3(struct vcpu *v);
161-int vcpu_destroy_pagetables(struct vcpu *, bool_t preemptible);
162+int vcpu_destroy_pagetables(struct vcpu *);
163 void propagate_page_fault(unsigned long addr, u16 error_code);
164 void *do_page_walk(struct vcpu *v, unsigned long addr);
165
166--- a/xen/include/xen/domain.h
167+++ b/xen/include/xen/domain.h
168@@ -13,7 +13,7 @@ typedef union {
169 struct vcpu *alloc_vcpu(
170 struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
171 struct vcpu *alloc_dom0_vcpu0(void);
172-void vcpu_reset(struct vcpu *v);
173+int vcpu_reset(struct vcpu *);
174
175 struct xen_domctl_getdomaininfo;
176 void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info);
177@@ -67,7 +67,7 @@ void arch_dump_vcpu_info(struct vcpu *v);
178
179 void arch_dump_domain_info(struct domain *d);
180
181-void arch_vcpu_reset(struct vcpu *v);
182+int arch_vcpu_reset(struct vcpu *);
183
184 extern spinlock_t vcpu_alloc_lock;
185 bool_t domctl_lock_acquire(void);
186--- a/xen/include/xen/sched.h
187+++ b/xen/include/xen/sched.h
188@@ -644,6 +644,9 @@ static inline struct domain *next_domain_in_cpupool(
189 /* VCPU is blocked due to missing mem_sharing ring. */
190 #define _VPF_mem_sharing 6
191 #define VPF_mem_sharing (1UL<<_VPF_mem_sharing)
192+ /* VCPU is being reset. */
193+#define _VPF_in_reset 7
194+#define VPF_in_reset (1UL<<_VPF_in_reset)
195
196 static inline int vcpu_runnable(struct vcpu *v)
197 {
This page took 0.435709 seconds and 4 git commands to generate.