Gentoo Archives: gentoo-commits

From: "Ian Delaney (idella4)" <idella4@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in app-emulation/xen-pvgrub/files: xen-4-CVE-2013-1952-XSA-49.patch xen-4-CVE-2013-1922-XSA-48.patch xen-4-CVE-2013-0215-XSA-38.patch xen-4-CVE-2013-1952-XSA_49.patch xen-4-CVE-2013-1919-XSA-46.patch
Date: Mon, 20 May 2013 14:15:48
Message-Id: 20130520141545.35FB22171D@flycatcher.gentoo.org
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__ */