1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
$NetBSD: patch-CVE-2013-4355_1,v 1.4 2014/05/05 13:39:10 drochner Exp $
http://lists.xenproject.org/archives/html/xen-devel/2013-09/msg03160.html
also fixes
http://lists.xenproject.org/archives/html/xen-devel/2013-11/msg03827.html
(CVE-2013-4554)
also fixes
http://lists.xenproject.org/archives/html/xen-devel/2014-03/msg03177.html
(CVE-2014-2599)
also fixes
http://lists.xenproject.org/archives/html/xen-devel/2014-04/msg03853.html
(CVE-2014-3124)
--- xen/arch/x86/hvm/hvm.c.orig 2013-09-10 06:42:18.000000000 +0000
+++ xen/arch/x86/hvm/hvm.c 2014-04-30 13:11:30.000000000 +0000
@@ -1961,11 +1961,7 @@ void hvm_task_switch(
rc = hvm_copy_from_guest_virt(
&tss, prev_tr.base, sizeof(tss), PFEC_page_present);
- if ( rc == HVMCOPY_bad_gva_to_gfn )
- goto out;
- if ( rc == HVMCOPY_gfn_paged_out )
- goto out;
- if ( rc == HVMCOPY_gfn_shared )
+ if ( rc != HVMCOPY_okay )
goto out;
eflags = regs->eflags;
@@ -2010,13 +2006,11 @@ void hvm_task_switch(
rc = hvm_copy_from_guest_virt(
&tss, tr.base, sizeof(tss), PFEC_page_present);
- if ( rc == HVMCOPY_bad_gva_to_gfn )
- goto out;
- if ( rc == HVMCOPY_gfn_paged_out )
- goto out;
- /* Note: this could be optimised, if the callee functions knew we want RO
- * access */
- if ( rc == HVMCOPY_gfn_shared )
+ /*
+ * Note: The HVMCOPY_gfn_shared case could be optimised, if the callee
+ * functions knew we want RO access.
+ */
+ if ( rc != HVMCOPY_okay )
goto out;
@@ -2834,7 +2828,7 @@ int hvm_do_hypercall(struct cpu_user_reg
case 4:
case 2:
hvm_get_segment_register(curr, x86_seg_ss, &sreg);
- if ( unlikely(sreg.attr.fields.dpl == 3) )
+ if ( unlikely(sreg.attr.fields.dpl) )
{
default:
regs->eax = -EPERM;
@@ -3657,13 +3651,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
rc = -EINVAL;
goto param_fail4;
}
- if ( p2m_is_grant(t) )
- {
- gdprintk(XENLOG_WARNING,
- "type for pfn 0x%lx changed to grant while "
- "we were working?\n", pfn);
+ if ( !p2m_is_ram(t) &&
+ (!p2m_is_hole(t) || a.hvmmem_type != HVMMEM_mmio_dm) )
goto param_fail4;
- }
else
{
nt = p2m_change_type(p2m, pfn, t, memtype[a.hvmmem_type]);
@@ -3746,7 +3736,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) )
goto param_fail5;
- for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
+ for ( pfn = a.first_pfn; a.nr; ++pfn )
{
p2m_type_t t;
mfn_t mfn;
@@ -3759,6 +3749,17 @@ long do_hvm_op(unsigned long op, XEN_GUE
p2m_unlock(p2m);
if ( !success )
goto param_fail5;
+
+ /* Check for continuation if it's not the last interation. */
+ if ( --a.nr && hypercall_preempt_check() )
+ {
+ a.first_pfn = pfn + 1;
+ if ( copy_to_guest(arg, &a, 1) )
+ rc = -EFAULT;
+ else
+ rc = -EAGAIN;
+ goto param_fail5;
+ }
}
rc = 0;
|