1 |
idella4 13/05/20 14:15:45 |
2 |
|
3 |
Added: xen-4-CVE-2013-1952-XSA-49.patch |
4 |
xen-4-CVE-2013-1922-XSA-48.patch |
5 |
xen-4-CVE-2013-0215-XSA-38.patch |
6 |
xen-4-CVE-2013-1952-XSA_49.patch |
7 |
xen-4-CVE-2013-1919-XSA-46.patch |
8 |
Log: |
9 |
rebump with sec. pathces, ditto bump |
10 |
|
11 |
(Portage version: 2.1.11.62/cvs/Linux x86_64, signed Manifest commit with key 0xB8072B0D) |
12 |
|
13 |
Revision Changes Path |
14 |
1.1 app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1952-XSA-49.patch |
15 |
|
16 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1952-XSA-49.patch?rev=1.1&view=markup |
17 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1952-XSA-49.patch?rev=1.1&content-type=text/plain |
18 |
|
19 |
Index: xen-4-CVE-2013-1952-XSA-49.patch |
20 |
=================================================================== |
21 |
VT-d: don't permit SVT_NO_VERIFY entries for known device types |
22 |
|
23 |
Only in cases where we don't know what to do we should leave the IRTE |
24 |
blank (suppressing all validation), but we should always log a warning |
25 |
in those cases (as being insecure). |
26 |
|
27 |
This is CVE-2013-1952 / XSA-49. |
28 |
|
29 |
Signed-off-by: Jan Beulich <jbeulich@××××.com> |
30 |
Acked-by: "Zhang, Xiantao" <xiantao.zhang@×××××.com> |
31 |
|
32 |
--- a/xen/drivers/passthrough/vtd/intremap.c |
33 |
+++ b/xen/drivers/passthrough/vtd/intremap.c |
34 |
@@ -440,16 +440,15 @@ static void set_msi_source_id(struct pci |
35 |
type = pdev_type(seg, bus, devfn); |
36 |
switch ( type ) |
37 |
{ |
38 |
+ case DEV_TYPE_PCIe_ENDPOINT: |
39 |
case DEV_TYPE_PCIe_BRIDGE: |
40 |
case DEV_TYPE_PCIe2PCI_BRIDGE: |
41 |
- case DEV_TYPE_LEGACY_PCI_BRIDGE: |
42 |
- break; |
43 |
- |
44 |
- case DEV_TYPE_PCIe_ENDPOINT: |
45 |
set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, PCI_BDF2(bus, devfn)); |
46 |
break; |
47 |
|
48 |
case DEV_TYPE_PCI: |
49 |
+ case DEV_TYPE_LEGACY_PCI_BRIDGE: |
50 |
+ /* case DEV_TYPE_PCI2PCIe_BRIDGE: */ |
51 |
ret = find_upstream_bridge(seg, &bus, &devfn, &secbus); |
52 |
if ( ret == 0 ) /* integrated PCI device */ |
53 |
{ |
54 |
@@ -461,10 +460,15 @@ static void set_msi_source_id(struct pci |
55 |
if ( pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE ) |
56 |
set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16, |
57 |
(bus << 8) | pdev->bus); |
58 |
- else if ( pdev_type(seg, bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE ) |
59 |
+ else |
60 |
set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, |
61 |
PCI_BDF2(bus, devfn)); |
62 |
} |
63 |
+ else |
64 |
+ dprintk(XENLOG_WARNING VTDPREFIX, |
65 |
+ "d%d: no upstream bridge for %04x:%02x:%02x.%u\n", |
66 |
+ pdev->domain->domain_id, |
67 |
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
68 |
break; |
69 |
|
70 |
default: |
71 |
|
72 |
|
73 |
|
74 |
1.1 app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1922-XSA-48.patch |
75 |
|
76 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1922-XSA-48.patch?rev=1.1&view=markup |
77 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1922-XSA-48.patch?rev=1.1&content-type=text/plain |
78 |
|
79 |
Index: xen-4-CVE-2013-1922-XSA-48.patch |
80 |
=================================================================== |
81 |
Add -f FMT / --format FMT arg to qemu-nbd |
82 |
|
83 |
From: "Daniel P. Berrange" <berrange@××××××.com> |
84 |
|
85 |
Currently the qemu-nbd program will auto-detect the format of |
86 |
any disk it is given. This behaviour is known to be insecure. |
87 |
For example, if qemu-nbd initially exposes a 'raw' file to an |
88 |
unprivileged app, and that app runs |
89 |
|
90 |
'qemu-img create -f qcow2 -o backing_file=/etc/shadow /dev/nbd0' |
91 |
|
92 |
then the next time the app is started, the qemu-nbd will now |
93 |
detect it as a 'qcow2' file and expose /etc/shadow to the |
94 |
unprivileged app. |
95 |
|
96 |
The only way to avoid this is to explicitly tell qemu-nbd what |
97 |
disk format to use on the command line, completely disabling |
98 |
auto-detection. This patch adds a '-f' / '--format' arg for |
99 |
this purpose, mirroring what is already available via qemu-img |
100 |
and qemu commands. |
101 |
|
102 |
qemu-nbd --format raw -p 9000 evil.img |
103 |
|
104 |
will now always use raw, regardless of what format 'evil.img' |
105 |
looks like it contains |
106 |
|
107 |
Signed-off-by: Daniel P. Berrange <berrange@××××××.com> |
108 |
[Use errx, not err. - Paolo] |
109 |
Signed-off-by: Paolo Bonzini <pbonzini@××××××.com> |
110 |
Signed-off-by: Stefano Stabellini <stefano.stabellini@×××××××××.com> |
111 |
|
112 |
[ This is a security issue, CVE-2013-1922 / XSA-48. ] |
113 |
|
114 |
diff --git a/qemu-nbd.c b/qemu-nbd.c |
115 |
index 291cba2..8fbe2cf 100644 |
116 |
--- a/tools/qemu-xen/qemu-nbd.c |
117 |
+++ b/tools/qemu-xen/qemu-nbd.c |
118 |
@@ -247,6 +247,7 @@ out: |
119 |
int main(int argc, char **argv) |
120 |
{ |
121 |
BlockDriverState *bs; |
122 |
+ BlockDriver *drv; |
123 |
off_t dev_offset = 0; |
124 |
off_t offset = 0; |
125 |
uint32_t nbdflags = 0; |
126 |
@@ -256,7 +257,7 @@ int main(int argc, char **argv) |
127 |
struct sockaddr_in addr; |
128 |
socklen_t addr_len = sizeof(addr); |
129 |
off_t fd_size; |
130 |
- const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t"; |
131 |
+ const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t"; |
132 |
struct option lopt[] = { |
133 |
{ "help", 0, NULL, 'h' }, |
134 |
{ "version", 0, NULL, 'V' }, |
135 |
@@ -271,6 +272,7 @@ int main(int argc, char **argv) |
136 |
{ "snapshot", 0, NULL, 's' }, |
137 |
{ "nocache", 0, NULL, 'n' }, |
138 |
{ "shared", 1, NULL, 'e' }, |
139 |
+ { "format", 1, NULL, 'f' }, |
140 |
{ "persistent", 0, NULL, 't' }, |
141 |
{ "verbose", 0, NULL, 'v' }, |
142 |
{ NULL, 0, NULL, 0 } |
143 |
@@ -292,6 +294,7 @@ int main(int argc, char **argv) |
144 |
int max_fd; |
145 |
int persistent = 0; |
146 |
pthread_t client_thread; |
147 |
+ const char *fmt = NULL; |
148 |
|
149 |
/* The client thread uses SIGTERM to interrupt the server. A signal |
150 |
* handler ensures that "qemu-nbd -v -c" exits with a nice status code. |
151 |
@@ -368,6 +371,9 @@ int main(int argc, char **argv) |
152 |
errx(EXIT_FAILURE, "Shared device number must be greater than 0\n"); |
153 |
} |
154 |
break; |
155 |
+ case 'f': |
156 |
+ fmt = optarg; |
157 |
+ break; |
158 |
case 't': |
159 |
persistent = 1; |
160 |
break; |
161 |
@@ -478,9 +484,19 @@ int main(int argc, char **argv) |
162 |
bdrv_init(); |
163 |
atexit(bdrv_close_all); |
164 |
|
165 |
+ if (fmt) { |
166 |
+ drv = bdrv_find_format(fmt); |
167 |
+ if (!drv) { |
168 |
+ errx(EXIT_FAILURE, "Unknown file format '%s'", fmt); |
169 |
+ } |
170 |
+ } else { |
171 |
+ drv = NULL; |
172 |
+ } |
173 |
+ |
174 |
bs = bdrv_new("hda"); |
175 |
srcpath = argv[optind]; |
176 |
- if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) { |
177 |
+ ret = bdrv_open(bs, srcpath, flags, drv); |
178 |
+ if (ret < 0) { |
179 |
errno = -ret; |
180 |
err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]); |
181 |
} |
182 |
diff --git a/qemu-nbd.texi b/qemu-nbd.texi |
183 |
index 44996cc..f56c68e 100644 |
184 |
--- a/tools/qemu-xen/qemu-nbd.texi |
185 |
+++ b/tools/qemu-xen/qemu-nbd.texi |
186 |
@@ -36,6 +36,8 @@ Export Qemu disk image using NBD protocol. |
187 |
disconnect the specified device |
188 |
@item -e, --shared=@var{num} |
189 |
device can be shared by @var{num} clients (default @samp{1}) |
190 |
+@item -f, --format=@var{fmt} |
191 |
+ force block driver for format @var{fmt} instead of auto-detecting |
192 |
@item -t, --persistent |
193 |
don't exit on the last connection |
194 |
@item -v, --verbose |
195 |
|
196 |
|
197 |
|
198 |
1.1 app-emulation/xen-pvgrub/files/xen-4-CVE-2013-0215-XSA-38.patch |
199 |
|
200 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-0215-XSA-38.patch?rev=1.1&view=markup |
201 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-0215-XSA-38.patch?rev=1.1&content-type=text/plain |
202 |
|
203 |
Index: xen-4-CVE-2013-0215-XSA-38.patch |
204 |
=================================================================== |
205 |
diff --git a/tools/ocaml/libs/xb/partial.ml b/tools/ocaml/libs/xb/partial.ml |
206 |
index 3558889..d4d1c7b 100644 |
207 |
--- a/tools/ocaml/libs/xb/partial.ml |
208 |
+++ b/tools/ocaml/libs/xb/partial.ml |
209 |
@@ -27,8 +27,15 @@ external header_size: unit -> int = "stub_header_size" |
210 |
external header_of_string_internal: string -> int * int * int * int |
211 |
= "stub_header_of_string" |
212 |
|
213 |
+let xenstore_payload_max = 4096 (* xen/include/public/io/xs_wire.h *) |
214 |
+ |
215 |
let of_string s = |
216 |
let tid, rid, opint, dlen = header_of_string_internal s in |
217 |
+ (* A packet which is bigger than xenstore_payload_max is illegal. |
218 |
+ This will leave the guest connection is a bad state and will |
219 |
+ be hard to recover from without restarting the connection |
220 |
+ (ie rebooting the guest) *) |
221 |
+ let dlen = min xenstore_payload_max dlen in |
222 |
{ |
223 |
tid = tid; |
224 |
rid = rid; |
225 |
@@ -38,6 +45,7 @@ let of_string s = |
226 |
} |
227 |
|
228 |
let append pkt s sz = |
229 |
+ if pkt.len > 4096 then failwith "Buffer.add: cannot grow buffer"; |
230 |
Buffer.add_string pkt.buf (String.sub s 0 sz) |
231 |
|
232 |
let to_complete pkt = |
233 |
diff --git a/tools/ocaml/libs/xb/xs_ring_stubs.c b/tools/ocaml/libs/xb/xs_ring_stubs.c |
234 |
index 00414c5..4888ac5 100644 |
235 |
--- a/tools/ocaml/libs/xb/xs_ring_stubs.c |
236 |
+++ b/tools/ocaml/libs/xb/xs_ring_stubs.c |
237 |
@@ -39,21 +39,23 @@ static int xs_ring_read(struct mmap_interface *interface, |
238 |
char *buffer, int len) |
239 |
{ |
240 |
struct xenstore_domain_interface *intf = interface->addr; |
241 |
- XENSTORE_RING_IDX cons, prod; |
242 |
+ XENSTORE_RING_IDX cons, prod; /* offsets only */ |
243 |
int to_read; |
244 |
|
245 |
- cons = intf->req_cons; |
246 |
- prod = intf->req_prod; |
247 |
+ cons = *(volatile uint32*)&intf->req_cons; |
248 |
+ prod = *(volatile uint32*)&intf->req_prod; |
249 |
xen_mb(); |
250 |
+ cons = MASK_XENSTORE_IDX(cons); |
251 |
+ prod = MASK_XENSTORE_IDX(prod); |
252 |
if (prod == cons) |
253 |
return 0; |
254 |
- if (MASK_XENSTORE_IDX(prod) > MASK_XENSTORE_IDX(cons)) |
255 |
+ if (prod > cons) |
256 |
to_read = prod - cons; |
257 |
else |
258 |
- to_read = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); |
259 |
+ to_read = XENSTORE_RING_SIZE - cons; |
260 |
if (to_read < len) |
261 |
len = to_read; |
262 |
- memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), len); |
263 |
+ memcpy(buffer, intf->req + cons, len); |
264 |
xen_mb(); |
265 |
intf->req_cons += len; |
266 |
return len; |
267 |
@@ -66,8 +68,8 @@ static int xs_ring_write(struct mmap_interface *interface, |
268 |
XENSTORE_RING_IDX cons, prod; |
269 |
int can_write; |
270 |
|
271 |
- cons = intf->rsp_cons; |
272 |
- prod = intf->rsp_prod; |
273 |
+ cons = *(volatile uint32*)&intf->rsp_cons; |
274 |
+ prod = *(volatile uint32*)&intf->rsp_prod; |
275 |
xen_mb(); |
276 |
if ( (prod - cons) >= XENSTORE_RING_SIZE ) |
277 |
return 0; |
278 |
|
279 |
|
280 |
|
281 |
1.1 app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1952-XSA_49.patch |
282 |
|
283 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1952-XSA_49.patch?rev=1.1&view=markup |
284 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1952-XSA_49.patch?rev=1.1&content-type=text/plain |
285 |
|
286 |
Index: xen-4-CVE-2013-1952-XSA_49.patch |
287 |
=================================================================== |
288 |
diff -ur xen-4.2.1.orig/xen/drivers/passthrough/vtd/intremap.c xen-4.2.1/xen/drivers/passthrough/vtd/intremap.c |
289 |
--- xen/drivers/passthrough/vtd/intremap.c 2012-12-17 23:01:55.000000000 +0800 |
290 |
+++ xen/drivers/passthrough/vtd/intremap.c 2013-05-15 23:09:06.704546506 +0800 |
291 |
@@ -440,16 +440,17 @@ |
292 |
type = pdev_type(seg, bus, devfn); |
293 |
switch ( type ) |
294 |
{ |
295 |
+ case DEV_TYPE_PCIe_ENDPOINT: |
296 |
case DEV_TYPE_PCIe_BRIDGE: |
297 |
case DEV_TYPE_PCIe2PCI_BRIDGE: |
298 |
- case DEV_TYPE_LEGACY_PCI_BRIDGE: |
299 |
- break; |
300 |
|
301 |
- case DEV_TYPE_PCIe_ENDPOINT: |
302 |
set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, PCI_BDF2(bus, devfn)); |
303 |
break; |
304 |
|
305 |
case DEV_TYPE_PCI: |
306 |
+ case DEV_TYPE_LEGACY_PCI_BRIDGE: |
307 |
+ /* case DEV_TYPE_PCI2PCIe_BRIDGE: */ |
308 |
+ |
309 |
ret = find_upstream_bridge(seg, &bus, &devfn, &secbus); |
310 |
if ( ret == 0 ) /* integrated PCI device */ |
311 |
{ |
312 |
@@ -461,10 +462,15 @@ |
313 |
if ( pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE ) |
314 |
set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16, |
315 |
(bus << 8) | pdev->bus); |
316 |
- else if ( pdev_type(seg, bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE ) |
317 |
+ else |
318 |
set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16, |
319 |
PCI_BDF2(bus, devfn)); |
320 |
} |
321 |
+ else |
322 |
+ dprintk(XENLOG_WARNING VTDPREFIX, |
323 |
+ "d%d: no upstream bridge for %04x:%02x:%02x.%u\n", |
324 |
+ pdev->domain->domain_id, |
325 |
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
326 |
break; |
327 |
|
328 |
default: |
329 |
|
330 |
|
331 |
|
332 |
1.1 app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1919-XSA-46.patch |
333 |
|
334 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1919-XSA-46.patch?rev=1.1&view=markup |
335 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/app-emulation/xen-pvgrub/files/xen-4-CVE-2013-1919-XSA-46.patch?rev=1.1&content-type=text/plain |
336 |
|
337 |
Index: xen-4-CVE-2013-1919-XSA-46.patch |
338 |
=================================================================== |
339 |
x86: fix various issues with handling guest IRQs |
340 |
|
341 |
- properly revoke IRQ access in map_domain_pirq() error path |
342 |
- don't permit replacing an in use IRQ |
343 |
- don't accept inputs in the GSI range for MAP_PIRQ_TYPE_MSI |
344 |
- track IRQ access permission in host IRQ terms, not guest IRQ ones |
345 |
(and with that, also disallow Dom0 access to IRQ0) |
346 |
|
347 |
This is CVE-2013-1919 / XSA-46. |
348 |
|
349 |
Signed-off-by: Jan Beulich <jbeulich@××××.com> |
350 |
Acked-by: Stefano Stabellini <stefano.stabellini@×××××××××.com> |
351 |
|
352 |
--- a/tools/libxl/libxl_create.c |
353 |
+++ b/tools/libxl/libxl_create.c |
354 |
@@ -968,14 +968,16 @@ static void domcreate_launch_dm(libxl__e |
355 |
} |
356 |
|
357 |
for (i = 0; i < d_config->b_info.num_irqs; i++) { |
358 |
- uint32_t irq = d_config->b_info.irqs[i]; |
359 |
+ int irq = d_config->b_info.irqs[i]; |
360 |
|
361 |
- LOG(DEBUG, "dom%d irq %"PRIx32, domid, irq); |
362 |
+ LOG(DEBUG, "dom%d irq %d", domid, irq); |
363 |
|
364 |
- ret = xc_domain_irq_permission(CTX->xch, domid, irq, 1); |
365 |
+ ret = irq >= 0 ? xc_physdev_map_pirq(CTX->xch, domid, irq, &irq) |
366 |
+ : -EOVERFLOW; |
367 |
+ if (!ret) |
368 |
+ ret = xc_domain_irq_permission(CTX->xch, domid, irq, 1); |
369 |
if ( ret<0 ){ |
370 |
- LOGE(ERROR, |
371 |
- "failed give dom%d access to irq %"PRId32, domid, irq); |
372 |
+ LOGE(ERROR, "failed give dom%d access to irq %d", domid, irq); |
373 |
ret = ERROR_FAIL; |
374 |
} |
375 |
} |
376 |
--- a/tools/python/xen/xend/server/irqif.py |
377 |
+++ b/tools/python/xen/xend/server/irqif.py |
378 |
@@ -73,6 +73,12 @@ class IRQController(DevController): |
379 |
|
380 |
pirq = get_param('irq') |
381 |
|
382 |
+ rc = xc.physdev_map_pirq(domid = self.getDomid(), |
383 |
+ index = pirq, |
384 |
+ pirq = pirq) |
385 |
+ if rc < 0: |
386 |
+ raise VmError('irq: Failed to map irq %x' % (pirq)) |
387 |
+ |
388 |
rc = xc.domain_irq_permission(domid = self.getDomid(), |
389 |
pirq = pirq, |
390 |
allow_access = True) |
391 |
@@ -81,12 +87,6 @@ class IRQController(DevController): |
392 |
#todo non-fatal |
393 |
raise VmError( |
394 |
'irq: Failed to configure irq: %d' % (pirq)) |
395 |
- rc = xc.physdev_map_pirq(domid = self.getDomid(), |
396 |
- index = pirq, |
397 |
- pirq = pirq) |
398 |
- if rc < 0: |
399 |
- raise VmError( |
400 |
- 'irq: Failed to map irq %x' % (pirq)) |
401 |
back = dict([(k, config[k]) for k in self.valid_cfg if k in config]) |
402 |
return (self.allocateDeviceID(), back, {}) |
403 |
|
404 |
--- a/xen/arch/x86/domain_build.c |
405 |
+++ b/xen/arch/x86/domain_build.c |
406 |
@@ -1219,7 +1219,7 @@ int __init construct_dom0( |
407 |
/* DOM0 is permitted full I/O capabilities. */ |
408 |
rc |= ioports_permit_access(dom0, 0, 0xFFFF); |
409 |
rc |= iomem_permit_access(dom0, 0UL, ~0UL); |
410 |
- rc |= irqs_permit_access(dom0, 0, d->nr_pirqs - 1); |
411 |
+ rc |= irqs_permit_access(dom0, 1, nr_irqs_gsi - 1); |
412 |
|
413 |
/* |
414 |
* Modify I/O port access permissions. |
415 |
--- a/xen/arch/x86/domctl.c |
416 |
+++ b/xen/arch/x86/domctl.c |
417 |
@@ -772,9 +772,13 @@ long arch_do_domctl( |
418 |
goto bind_out; |
419 |
|
420 |
ret = -EPERM; |
421 |
- if ( !IS_PRIV(current->domain) && |
422 |
- !irq_access_permitted(current->domain, bind->machine_irq) ) |
423 |
- goto bind_out; |
424 |
+ if ( !IS_PRIV(current->domain) ) |
425 |
+ { |
426 |
+ int irq = domain_pirq_to_irq(d, bind->machine_irq); |
427 |
+ |
428 |
+ if ( irq <= 0 || !irq_access_permitted(current->domain, irq) ) |
429 |
+ goto bind_out; |
430 |
+ } |
431 |
|
432 |
ret = -ESRCH; |
433 |
if ( iommu_enabled ) |
434 |
@@ -803,9 +807,13 @@ long arch_do_domctl( |
435 |
bind = &(domctl->u.bind_pt_irq); |
436 |
|
437 |
ret = -EPERM; |
438 |
- if ( !IS_PRIV(current->domain) && |
439 |
- !irq_access_permitted(current->domain, bind->machine_irq) ) |
440 |
- goto unbind_out; |
441 |
+ if ( !IS_PRIV(current->domain) ) |
442 |
+ { |
443 |
+ int irq = domain_pirq_to_irq(d, bind->machine_irq); |
444 |
+ |
445 |
+ if ( irq <= 0 || !irq_access_permitted(current->domain, irq) ) |
446 |
+ goto unbind_out; |
447 |
+ } |
448 |
|
449 |
if ( iommu_enabled ) |
450 |
{ |
451 |
--- a/xen/arch/x86/irq.c |
452 |
+++ b/xen/arch/x86/irq.c |
453 |
@@ -184,6 +184,14 @@ int create_irq(int node) |
454 |
desc->arch.used = IRQ_UNUSED; |
455 |
irq = ret; |
456 |
} |
457 |
+ else if ( dom0 ) |
458 |
+ { |
459 |
+ ret = irq_permit_access(dom0, irq); |
460 |
+ if ( ret ) |
461 |
+ printk(XENLOG_G_ERR |
462 |
+ "Could not grant Dom0 access to IRQ%d (error %d)\n", |
463 |
+ irq, ret); |
464 |
+ } |
465 |
|
466 |
return irq; |
467 |
} |
468 |
@@ -280,6 +288,17 @@ void clear_irq_vector(int irq) |
469 |
void destroy_irq(unsigned int irq) |
470 |
{ |
471 |
BUG_ON(!MSI_IRQ(irq)); |
472 |
+ |
473 |
+ if ( dom0 ) |
474 |
+ { |
475 |
+ int err = irq_deny_access(dom0, irq); |
476 |
+ |
477 |
+ if ( err ) |
478 |
+ printk(XENLOG_G_ERR |
479 |
+ "Could not revoke Dom0 access to IRQ%u (error %d)\n", |
480 |
+ irq, err); |
481 |
+ } |
482 |
+ |
483 |
dynamic_irq_cleanup(irq); |
484 |
clear_irq_vector(irq); |
485 |
} |
486 |
@@ -1858,7 +1877,7 @@ int map_domain_pirq( |
487 |
|
488 |
if ( !IS_PRIV(current->domain) && |
489 |
!(IS_PRIV_FOR(current->domain, d) && |
490 |
- irq_access_permitted(current->domain, pirq))) |
491 |
+ irq_access_permitted(current->domain, irq))) |
492 |
return -EPERM; |
493 |
|
494 |
if ( pirq < 0 || pirq >= d->nr_pirqs || irq < 0 || irq >= nr_irqs ) |
495 |
@@ -1887,17 +1906,18 @@ int map_domain_pirq( |
496 |
return ret; |
497 |
} |
498 |
|
499 |
- ret = irq_permit_access(d, pirq); |
500 |
+ ret = irq_permit_access(d, irq); |
501 |
if ( ret ) |
502 |
{ |
503 |
- dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", |
504 |
- d->domain_id, pirq); |
505 |
+ printk(XENLOG_G_ERR |
506 |
+ "dom%d: could not permit access to IRQ%d (pirq %d)\n", |
507 |
+ d->domain_id, irq, pirq); |
508 |
return ret; |
509 |
} |
510 |
|
511 |
ret = prepare_domain_irq_pirq(d, irq, pirq, &info); |
512 |
if ( ret ) |
513 |
- return ret; |
514 |
+ goto revoke; |
515 |
|
516 |
desc = irq_to_desc(irq); |
517 |
|
518 |
@@ -1921,8 +1941,14 @@ int map_domain_pirq( |
519 |
spin_lock_irqsave(&desc->lock, flags); |
520 |
|
521 |
if ( desc->handler != &no_irq_type ) |
522 |
+ { |
523 |
+ spin_unlock_irqrestore(&desc->lock, flags); |
524 |
dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n", |
525 |
d->domain_id, irq); |
526 |
+ pci_disable_msi(msi_desc); |
527 |
+ ret = -EBUSY; |
528 |
+ goto done; |
529 |
+ } |
530 |
setup_msi_handler(desc, msi_desc); |
531 |
|
532 |
if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV |
533 |
@@ -1951,7 +1977,14 @@ int map_domain_pirq( |
534 |
|
535 |
done: |
536 |
if ( ret ) |
537 |
+ { |
538 |
cleanup_domain_irq_pirq(d, irq, info); |
539 |
+ revoke: |
540 |
+ if ( irq_deny_access(d, irq) ) |
541 |
+ printk(XENLOG_G_ERR |
542 |
+ "dom%d: could not revoke access to IRQ%d (pirq %d)\n", |
543 |
+ d->domain_id, irq, pirq); |
544 |
+ } |
545 |
return ret; |
546 |
} |
547 |
|
548 |
@@ -2017,10 +2050,11 @@ int unmap_domain_pirq(struct domain *d, |
549 |
if ( !forced_unbind ) |
550 |
cleanup_domain_irq_pirq(d, irq, info); |
551 |
|
552 |
- ret = irq_deny_access(d, pirq); |
553 |
+ ret = irq_deny_access(d, irq); |
554 |
if ( ret ) |
555 |
- dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n", |
556 |
- d->domain_id, pirq); |
557 |
+ printk(XENLOG_G_ERR |
558 |
+ "dom%d: could not deny access to IRQ%d (pirq %d)\n", |
559 |
+ d->domain_id, irq, pirq); |
560 |
|
561 |
done: |
562 |
return ret; |
563 |
--- a/xen/arch/x86/physdev.c |
564 |
+++ b/xen/arch/x86/physdev.c |
565 |
@@ -147,7 +147,7 @@ int physdev_map_pirq(domid_t domid, int |
566 |
if ( irq == -1 ) |
567 |
irq = create_irq(NUMA_NO_NODE); |
568 |
|
569 |
- if ( irq < 0 || irq >= nr_irqs ) |
570 |
+ if ( irq < nr_irqs_gsi || irq >= nr_irqs ) |
571 |
{ |
572 |
dprintk(XENLOG_G_ERR, "dom%d: can't create irq for msi!\n", |
573 |
d->domain_id); |
574 |
--- a/xen/common/domctl.c |
575 |
+++ b/xen/common/domctl.c |
576 |
@@ -25,6 +25,7 @@ |
577 |
#include <xen/paging.h> |
578 |
#include <xen/hypercall.h> |
579 |
#include <asm/current.h> |
580 |
+#include <asm/irq.h> |
581 |
#include <asm/page.h> |
582 |
#include <public/domctl.h> |
583 |
#include <xsm/xsm.h> |
584 |
@@ -897,9 +898,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc |
585 |
else if ( xsm_irq_permission(d, pirq, allow) ) |
586 |
ret = -EPERM; |
587 |
else if ( allow ) |
588 |
- ret = irq_permit_access(d, pirq); |
589 |
+ ret = pirq_permit_access(d, pirq); |
590 |
else |
591 |
- ret = irq_deny_access(d, pirq); |
592 |
+ ret = pirq_deny_access(d, pirq); |
593 |
|
594 |
rcu_unlock_domain(d); |
595 |
} |
596 |
--- a/xen/common/event_channel.c |
597 |
+++ b/xen/common/event_channel.c |
598 |
@@ -369,7 +369,7 @@ static long evtchn_bind_pirq(evtchn_bind |
599 |
if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) |
600 |
return -EINVAL; |
601 |
|
602 |
- if ( !is_hvm_domain(d) && !irq_access_permitted(d, pirq) ) |
603 |
+ if ( !is_hvm_domain(d) && !pirq_access_permitted(d, pirq) ) |
604 |
return -EPERM; |
605 |
|
606 |
spin_lock(&d->event_lock); |
607 |
--- a/xen/include/xen/iocap.h |
608 |
+++ b/xen/include/xen/iocap.h |
609 |
@@ -28,4 +28,22 @@ |
610 |
#define irq_access_permitted(d, i) \ |
611 |
rangeset_contains_singleton((d)->irq_caps, i) |
612 |
|
613 |
+#define pirq_permit_access(d, i) ({ \ |
614 |
+ struct domain *d__ = (d); \ |
615 |
+ int i__ = domain_pirq_to_irq(d__, i); \ |
616 |
+ i__ > 0 ? rangeset_add_singleton(d__->irq_caps, i__)\ |
617 |
+ : -EINVAL; \ |
618 |
+}) |
619 |
+#define pirq_deny_access(d, i) ({ \ |
620 |
+ struct domain *d__ = (d); \ |
621 |
+ int i__ = domain_pirq_to_irq(d__, i); \ |
622 |
+ i__ > 0 ? rangeset_remove_singleton(d__->irq_caps, i__)\ |
623 |
+ : -EINVAL; \ |
624 |
+}) |
625 |
+#define pirq_access_permitted(d, i) ({ \ |
626 |
+ struct domain *d__ = (d); \ |
627 |
+ rangeset_contains_singleton(d__->irq_caps, \ |
628 |
+ domain_pirq_to_irq(d__, i));\ |
629 |
+}) |
630 |
+ |
631 |
#endif /* __XEN_IOCAP_H__ */ |