Compare commits

..

15 commits

Author SHA1 Message Date
Michael Young
86d80e3acb guest use of HLE constructs may lock up host [XSA-282] 2018-11-06 22:37:44 +00:00
Michael Young
a150492887 x86: Nested VT-x usable even when disabled [XSA-278] (#1643118) 2018-10-25 21:11:01 +01:00
Michael Young
4d37d7e4ce update to 4.9.3 2018-09-25 20:54:41 +01:00
Michael Young
e2de31fea8 add CVE references 2018-09-12 19:52:42 +01:00
Michael Young
56f3a702a3 L1 Terminal Fault speculative side channel patch bundle [XSA-273,
CVE-2018-3620, CVE-2018-3646]
drop patches also in the bundle, which also includes
Use of v2 grant tables may cause crash on ARM [XSA-268] (#1616081)
x86: Incorrect MSR_DEBUGCTL handling lets guests enable BTS [XSA-269]
	(#1616077)
oxenstored does not apply quota-maxentity [XSA-272] (#1616080)
2018-08-15 23:14:46 +01:00
Michael Young
833288d408 add bug references 2018-06-28 00:03:42 +01:00
Michael Young
db2bf3b4f8 preemption checks bypassed in x86 PV MM handling [XSA-264, CVE-2018-12891]
x86: #DB exception safety check can be triggered by a guest [XSA-265,
        CVE-2018-12893]
libxl fails to honour readonly flag on HVM emulated SCSI disks [XSA-266,
        CVE-2018-12892]
2018-06-27 22:54:20 +01:00
Michael Young
4401709c83 Speculative register leakage from lazy FPU context switching
[XSA-267, CVE-2018-3665]
fix for change in iasl output
2018-06-16 15:06:41 +01:00
Michael Young
b4719e3501 Speculative Store Bypass [XSA-263, CVE-2018-3639] 2018-05-22 22:45:43 +01:00
Michael Young
2d7f2b9a77 add CVEs and bug reference 2018-05-11 22:58:46 +01:00
Michael Young
67cbf78425 x86: mishandling of debug exceptions [XSA-260, CVE-2018-8897]
x86 vHPET interrupt injection errors [XSA-261] (#1576089)
qemu may drive Xen into unbounded loop [XSA-262]
2018-05-09 21:44:45 +01:00
Michael Young
70e5ed2b64 Information leak via crafted user-supplied CDROM [XSA-258] (#1571867)
x86: PV guest may crash Xen with XPTI [XSA-259] (#1571878)
2018-04-25 21:23:18 +01:00
Michael Young
7185b9d897 update to xen-4.9.2 2018-04-04 22:08:44 +01:00
Michael Young
d4696bae25 add CVE references 2018-02-28 12:22:04 +00:00
Michael Young
aec7903969 add Xen page-table isolation (XPTI) mitigation
and Branch Target Injection (BTI) mitigation for XSA-254
DoS via non-preemptable L3/L4 pagetable freeing [XSA-252] (#1549568)
grant table v2 -> v1 transition may crash Xen [XSA-255] (#1549570)
x86 PVH guest without LAPIC may DoS the host [XSA-256] (#1549572)
2018-02-27 16:40:17 +00:00
96 changed files with 3401 additions and 6136 deletions

3
.gitignore vendored
View file

@ -6,5 +6,4 @@ lwip-1.3.0.tar.gz
pciutils-2.2.9.tar.bz2
zlib-1.2.3.tar.gz
polarssl-1.1.4-gpl.tgz
/mini-os-4.21.0.tar.xz
/xen-4.21.1.tar.xz
/xen-4.9.3.tar.gz

11
CVE-2014-0150.patch Normal file
View file

@ -0,0 +1,11 @@
--- xen-4.4.1/tools/qemu-xen-traditional/hw/virtio-net.c.orig 2014-07-02 15:54:37.000000000 +0100
+++ xen-4.4.1/tools/qemu-xen-traditional/hw/virtio-net.c 2014-11-18 20:50:13.593122915 +0000
@@ -192,7 +192,7 @@
return VIRTIO_NET_ERR;
if (mac_data.entries) {
- if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
+ if (n->mac_table.in_use <= MAC_TABLE_ENTRIES - mac_data.entries) {
memcpy(n->mac_table.macs + (n->mac_table.in_use * ETH_ALEN),
elem->out_sg[2].iov_base + sizeof(mac_data),
mac_data.entries * ETH_ALEN);

View file

@ -0,0 +1,47 @@
From 041e32b8d9d076980b4e35317c0339e57ab888f1 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
Date: Sun, 11 Jun 2017 14:37:14 +0200
Subject: [PATCH] qemu-nbd: Ignore SIGPIPE
qemu proper has done so for 13 years
(8a7ddc38a60648257dc0645ab4a05b33d6040063), qemu-img and qemu-io have
done so for four years (526eda14a68d5b3596be715505289b541288ef2a).
Ignoring this signal is especially important in qemu-nbd because
otherwise a client can easily take down the qemu-nbd server by dropping
the connection when the server wants to send something, for example:
$ qemu-nbd -x foo -f raw -t null-co:// &
[1] 12726
$ qemu-io -c quit nbd://localhost/bar
can't open device nbd://localhost/bar: No export with name 'bar' available
[1] + 12726 broken pipe qemu-nbd -x foo -f raw -t null-co://
In this case, the client sends an NBD_OPT_ABORT and closes the
connection (because it is not required to wait for a reply), but the
server replies with an NBD_REP_ACK (because it is required to reply).
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20170611123714.31292-1-mreitz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
qemu-nbd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 9464a04..4dd3fd4 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -581,6 +581,10 @@ int main(int argc, char **argv)
sa_sigterm.sa_handler = termsig_handler;
sigaction(SIGTERM, &sa_sigterm, NULL);
+#ifdef CONFIG_POSIX
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
module_call_init(MODULE_INIT_TRACE);
qcrypto_init(&error_fatal);
--
1.8.3.1

View file

@ -0,0 +1,43 @@
From 04bf2526ce87f21b32c9acba1c5518708c243ad0 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Wed, 12 Jul 2017 18:08:40 +0530
Subject: [PATCH] exec: use qemu_ram_ptr_length to access guest ram
When accessing guest's ram block during DMA operation, use
'qemu_ram_ptr_length' to get ram block pointer. It ensures
that DMA operation of given length is possible; And avoids
any OOB memory access situations.
Reported-by: Alex <broscutamaker@gmail.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <20170712123840.29328-1-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
exec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/exec.c b/exec.c
index a083ff8..ad103ce 100644
--- a/exec.c
+++ b/exec.c
@@ -2929,7 +2929,7 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l);
}
@@ -3020,7 +3020,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(buf, ptr, l);
}
--
1.8.3.1

View file

@ -0,0 +1,55 @@
From 069eb7b2b8fc47c7cb52e5a4af23ea98d939e3da Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Wed, 14 Dec 2016 18:32:22 -0800
Subject: [PATCH] audio: es1370: add exit function
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit
Currently the es1370 device emulation doesn't have a exit function,
hot unplug this device will leak some memory. Add a exit function to
avoid this.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 585200c9.a968ca0a.1ab80.4c98@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/audio/es1370.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index 8449b5f..883ec69 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -1041,6 +1041,19 @@ static void es1370_realize(PCIDevice *dev, Error **errp)
es1370_reset (s);
}
+static void es1370_exit(PCIDevice *dev)
+{
+ ES1370State *s = ES1370(dev);
+ int i;
+
+ for (i = 0; i < 2; ++i) {
+ AUD_close_out(&s->card, s->dac_voice[i]);
+ }
+
+ AUD_close_in(&s->card, s->adc_voice);
+ AUD_remove_card(&s->card);
+}
+
static int es1370_init (PCIBus *bus)
{
pci_create_simple (bus, -1, TYPE_ES1370);
@@ -1053,6 +1066,7 @@ static void es1370_class_init (ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
k->realize = es1370_realize;
+ k->exit = es1370_exit;
k->vendor_id = PCI_VENDOR_ID_ENSONIQ;
k->device_id = PCI_DEVICE_ID_ENSONIQ_ES1370;
k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
--
1.7.0.4

View file

@ -0,0 +1,197 @@
From 0c9390d978cbf61e8f16c9f580fa96b305c43568 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Thu, 8 Jun 2017 17:26:17 -0500
Subject: [PATCH] nbd: Fix regression on resiliency to port scan
Back in qemu 2.5, qemu-nbd was immune to port probes (a transient
server would not quit, regardless of how many probe connections
came and went, until a connection actually negotiated). But we
broke that in commit ee7d7aa when removing the return value to
nbd_client_new(), although that patch also introduced a bug causing
an assertion failure on a client that fails negotiation. We then
made it worse during refactoring in commit 1a6245a (a segfault
before we could even assert); the (masked) assertion was cleaned
up in d3780c2 (still in 2.6), and just recently we finally fixed
the segfault ("nbd: Fully intialize client in case of failed
negotiation"). But that still means that ever since we added
TLS support to qemu-nbd, we have been vulnerable to an ill-timed
port-scan being able to cause a denial of service by taking down
qemu-nbd before a real client has a chance to connect.
Since negotiation is now handled asynchronously via coroutines,
we no longer have a synchronous point of return by re-adding a
return value to nbd_client_new(). So this patch instead wires
things up to pass the negotiation status through the close_fn
callback function.
Simple test across two terminals:
$ qemu-nbd -f raw -p 30001 file
$ nmap 127.0.0.1 -p 30001 && \
qemu-io -c 'r 0 512' -f raw nbd://localhost:30001
Note that this patch does not change what constitutes successful
negotiation (thus, a client must enter transmission phase before
that client can be considered as a reason to terminate the server
when the connection ends). Perhaps we may want to tweak things
in a later patch to also treat a client that uses NBD_OPT_ABORT
as being a 'successful' negotiation (the client correctly talked
the NBD protocol, and informed us it was not going to use our
export after all), but that's a discussion for another day.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170608222617.20376-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
blockdev-nbd.c | 6 +++++-
include/block/nbd.h | 2 +-
nbd/server.c | 24 +++++++++++++++---------
qemu-nbd.c | 4 ++--
4 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index dd0860f..28f551a 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -27,6 +27,10 @@ typedef struct NBDServerData {
static NBDServerData *nbd_server;
+static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
+{
+ nbd_client_put(client);
+}
static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
gpointer opaque)
@@ -46,7 +50,7 @@ static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
nbd_client_new(NULL, cioc,
nbd_server->tlscreds, NULL,
- nbd_client_put);
+ nbd_blockdev_client_closed);
object_unref(OBJECT(cioc));
return TRUE;
}
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 416257a..8fa5ce5 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -162,7 +162,7 @@ void nbd_client_new(NBDExport *exp,
QIOChannelSocket *sioc,
QCryptoTLSCreds *tlscreds,
const char *tlsaclname,
- void (*close)(NBDClient *));
+ void (*close_fn)(NBDClient *, bool));
void nbd_client_get(NBDClient *client);
void nbd_client_put(NBDClient *client);
diff --git a/nbd/server.c b/nbd/server.c
index 49b55f6..f2b1aa4 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -81,7 +81,7 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
struct NBDClient {
int refcount;
- void (*close)(NBDClient *client);
+ void (*close_fn)(NBDClient *client, bool negotiated);
bool no_zeroes;
NBDExport *exp;
@@ -778,7 +778,7 @@ void nbd_client_put(NBDClient *client)
}
}
-static void client_close(NBDClient *client)
+static void client_close(NBDClient *client, bool negotiated)
{
if (client->closing) {
return;
@@ -793,8 +793,8 @@ static void client_close(NBDClient *client)
NULL);
/* Also tell the client, so that they release their reference. */
- if (client->close) {
- client->close(client);
+ if (client->close_fn) {
+ client->close_fn(client, negotiated);
}
}
@@ -975,7 +975,7 @@ void nbd_export_close(NBDExport *exp)
nbd_export_get(exp);
QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
- client_close(client);
+ client_close(client, true);
}
nbd_export_set_name(exp, NULL);
nbd_export_set_description(exp, NULL);
@@ -1337,7 +1337,7 @@ done:
out:
nbd_request_put(req);
- client_close(client);
+ client_close(client, true);
}
static void nbd_read(void *opaque)
@@ -1363,7 +1363,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
qemu_co_mutex_init(&client->send_lock);
if (nbd_negotiate(data)) {
- client_close(client);
+ client_close(client, false);
goto out;
}
nbd_set_handlers(client);
@@ -1373,11 +1373,17 @@ out:
g_free(data);
}
+/*
+ * Create a new client listener on the given export @exp, using the
+ * given channel @sioc. Begin servicing it in a coroutine. When the
+ * connection closes, call @close_fn with an indication of whether the
+ * client completed negotiation.
+ */
void nbd_client_new(NBDExport *exp,
QIOChannelSocket *sioc,
QCryptoTLSCreds *tlscreds,
const char *tlsaclname,
- void (*close_fn)(NBDClient *))
+ void (*close_fn)(NBDClient *, bool))
{
NBDClient *client;
NBDClientNewData *data = g_new(NBDClientNewData, 1);
@@ -1394,7 +1400,7 @@ void nbd_client_new(NBDExport *exp,
client->ioc = QIO_CHANNEL(sioc);
object_ref(OBJECT(client->ioc));
client->can_read = true;
- client->close = close_fn;
+ client->close_fn = close_fn;
data->client = client;
data->co = qemu_coroutine_create(nbd_co_client_start, data);
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 651f85e..9464a04 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -336,10 +336,10 @@ static void nbd_export_closed(NBDExport *exp)
static void nbd_update_server_watch(void);
-static void nbd_client_closed(NBDClient *client)
+static void nbd_client_closed(NBDClient *client, bool negotiated)
{
nb_fds--;
- if (nb_fds == 0 && !persistent && state == RUNNING) {
+ if (negotiated && nb_fds == 0 && !persistent && state == RUNNING) {
state = TERMINATE;
}
nbd_update_server_watch();
--
1.8.3.1

View file

@ -0,0 +1,52 @@
From 12351a91da97b414eec8cdb09f1d9f41e535a401 Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Wed, 14 Dec 2016 18:30:21 -0800
Subject: [PATCH] audio: ac97: add exit function
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit
Currently the ac97 device emulation doesn't have a exit function,
hot unplug this device will leak some memory. Add a exit function to
avoid this.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 58520052.4825ed0a.27a71.6cae@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/audio/ac97.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index cbd959e..c306575 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -1387,6 +1387,16 @@ static void ac97_realize(PCIDevice *dev, Error **errp)
ac97_on_reset (&s->dev.qdev);
}
+static void ac97_exit(PCIDevice *dev)
+{
+ AC97LinkState *s = DO_UPCAST(AC97LinkState, dev, dev);
+
+ AUD_close_in(&s->card, s->voice_pi);
+ AUD_close_out(&s->card, s->voice_po);
+ AUD_close_in(&s->card, s->voice_mc);
+ AUD_remove_card(&s->card);
+}
+
static int ac97_init (PCIBus *bus)
{
pci_create_simple (bus, -1, "AC97");
@@ -1404,6 +1414,7 @@ static void ac97_class_init (ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
k->realize = ac97_realize;
+ k->exit = ac97_exit;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
k->revision = 0x01;
--
1.7.0.4

View file

@ -0,0 +1,51 @@
From 215902d7b6fb50c6fc216fc74f770858278ed904 Mon Sep 17 00:00:00 2001
From: hangaohuai <hangaohuai@huawei.com>
Date: Tue, 14 Mar 2017 14:39:19 +0800
Subject: [PATCH] fix :cirrus_vga fix OOB read case qemu Segmentation fault
check the validity of parameters in cirrus_bitblt_rop_fwd_transp_xxx
and cirrus_bitblt_rop_fwd_xxx to avoid the OOB read which causes qemu Segmentation fault.
After the fix, we will touch the assert in
cirrus_invalidate_region:
assert(off_cur_end >= off_cur);
Signed-off-by: fangying <fangying1@huawei.com>
Signed-off-by: hangaohuai <hangaohuai@huawei.com>
Message-id: 20170314063919.16200-1-hangaohuai@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/display/cirrus_vga_rop.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index 0925a00..b7447f8 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -97,6 +97,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
uint8_t p;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
+
+ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
+ return;
+ }
+
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
p = *dst;
@@ -143,6 +148,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
uint8_t p1, p2;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
+
+ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
+ return;
+ }
+
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x+=2) {
p1 = *dst;
--
1.8.3.1

View file

@ -0,0 +1,31 @@
From 26f670a244982335cc08943fb1ec099a2c81e42d Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Tue, 7 Feb 2017 03:15:03 -0800
Subject: [PATCH] usb: ohci: fix error return code in servicing iso td
It should return 1 if an error occurs when reading iso td.
This will avoid an infinite loop issue in ohci_service_ed_list.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Message-id: 5899ac3e.1033240a.944d5.9a2d@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/hcd-ohci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index c82a92f..2cba3e3 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -725,7 +725,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
if (ohci_read_iso_td(ohci, addr, &iso_td)) {
trace_usb_ohci_iso_td_read_failed(addr);
ohci_die(ohci);
- return 0;
+ return 1;
}
starting_frame = OHCI_BM(iso_td.flags, TD_SF);
--
1.8.3.1

View file

@ -0,0 +1,38 @@
From 3268a845f41253fb55852a8429c32b50f36f349a Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 28 Apr 2017 09:56:12 +0200
Subject: [PATCH] audio: release capture buffers
AUD_add_capture() allocates two buffers which are never released.
Add the missing calls to AUD_del_capture().
Impact: Allows vnc clients to exhaust host memory by repeatedly
starting and stopping audio capture.
Fixes: CVE-2017-8309
Cc: P J P <ppandit@redhat.com>
Cc: Huawei PSIRT <PSIRT@huawei.com>
Reported-by: "Jiangxin (hunter, SCC)" <jiangxin1@huawei.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 20170428075612.9997-1-kraxel@redhat.com
---
audio/audio.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/audio/audio.c b/audio/audio.c
index c8898d8..beafed2 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -2028,6 +2028,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
sw = sw1;
}
QLIST_REMOVE (cap, entries);
+ g_free (cap->hw.mix_buf);
+ g_free (cap->buf);
g_free (cap);
}
return;
--
1.8.3.1

View file

@ -0,0 +1,40 @@
From 8409dc884a201bf74b30a9d232b6bbdd00cb7e2b Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Wed, 4 Jan 2017 00:43:16 -0800
Subject: [PATCH] serial: fix memory leak in serial exit
The serial_exit_core function doesn't free some resources.
This can lead memory leak when hotplug and unplug. This
patch avoid this.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Message-Id: <586cb5ab.f31d9d0a.38ac3.acf2@mx.google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/serial.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index ffbacd8..67b18ed 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -906,6 +906,16 @@ void serial_realize_core(SerialState *s, Error **errp)
void serial_exit_core(SerialState *s)
{
qemu_chr_fe_deinit(&s->chr);
+
+ timer_del(s->modem_status_poll);
+ timer_free(s->modem_status_poll);
+
+ timer_del(s->fifo_timeout_timer);
+ timer_free(s->fifo_timeout_timer);
+
+ fifo8_destroy(&s->recv_fifo);
+ fifo8_destroy(&s->xmit_fifo);
+
qemu_unregister_reset(serial_reset, s);
}
--
1.8.3.1

View file

@ -0,0 +1,52 @@
From 95ed56939eb2eaa4e2f349fe6dcd13ca4edfd8fb Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Tue, 7 Feb 2017 02:23:33 -0800
Subject: [PATCH] usb: ohci: limit the number of link eds
The guest may builds an infinite loop with link eds. This patch
limit the number of linked ed to avoid this.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Message-id: 5899a02e.45ca240a.6c373.93c1@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/hcd-ohci.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 2cba3e3..21c93e0 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -42,6 +42,8 @@
#define OHCI_MAX_PORTS 15
+#define ED_LINK_LIMIT 4
+
static int64_t usb_frame_time;
static int64_t usb_bit_time;
@@ -1184,7 +1186,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
uint32_t next_ed;
uint32_t cur;
int active;
-
+ uint32_t link_cnt = 0;
active = 0;
if (head == 0)
@@ -1199,6 +1201,11 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
next_ed = ed.next & OHCI_DPTR_MASK;
+ if (++link_cnt > ED_LINK_LIMIT) {
+ ohci_die(ohci);
+ return 0;
+ }
+
if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
uint32_t addr;
/* Cancel pending packets for ED that have been paused. */
--
1.8.3.1

View file

@ -0,0 +1,49 @@
From d63fb193e71644a073b77ff5ac6f1216f2f6cf6e Mon Sep 17 00:00:00 2001
From: Li Qiang <liq3ea@gmail.com>
Date: Mon, 27 Mar 2017 21:13:19 +0200
Subject: [PATCH] 9pfs: fix file descriptor leak
The v9fs_create() and v9fs_lcreate() functions are used to create a file
on the backend and to associate it to a fid. The fid shouldn't be already
in-use, otherwise both functions may silently leak a file descriptor or
allocated memory. The current code doesn't check that.
This patch ensures that the fid isn't already associated to anything
before using it.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
(reworded the changelog, Greg Kurz)
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index b8c0b99..48babce 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1550,6 +1550,10 @@ static void coroutine_fn v9fs_lcreate(void *opaque)
err = -ENOENT;
goto out_nofid;
}
+ if (fidp->fid_type != P9_FID_NONE) {
+ err = -EINVAL;
+ goto out;
+ }
flags = get_dotl_openflags(pdu->s, flags);
err = v9fs_co_open2(pdu, fidp, &name, gid,
@@ -2153,6 +2157,10 @@ static void coroutine_fn v9fs_create(void *opaque)
err = -EINVAL;
goto out_nofid;
}
+ if (fidp->fid_type != P9_FID_NONE) {
+ err = -EINVAL;
+ goto out;
+ }
if (perm & P9_STAT_MODE_DIR) {
err = v9fs_co_mkdir(pdu, fidp, &name, perm & 0777,
fidp->uid, -1, &stbuf);
--
1.8.3.1

View file

@ -0,0 +1,81 @@
From df8ad9f128c15aa0a0ebc7b24e9a22c9775b67af Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Fri, 26 May 2017 22:04:21 -0500
Subject: [PATCH] nbd: Fully initialize client in case of failed negotiation
If a non-NBD client connects to qemu-nbd, we would end up with
a SIGSEGV in nbd_client_put() because we were trying to
unregister the client's association to the export, even though
we skipped inserting the client into that list. Easy trigger
in two terminals:
$ qemu-nbd -p 30001 --format=raw file
$ nmap 127.0.0.1 -p 30001
nmap claims that it thinks it connected to a pago-services1
server (which probably means nmap could be updated to learn the
NBD protocol and give a more accurate diagnosis of the open
port - but that's not our problem), then terminates immediately,
so our call to nbd_negotiate() fails. The fix is to reorder
nbd_co_client_start() to ensure that all initialization occurs
before we ever try talking to a client in nbd_negotiate(), so
that the teardown sequence on negotiation failure doesn't fault
while dereferencing a half-initialized object.
While debugging this, I also noticed that nbd_update_server_watch()
called by nbd_client_closed() was still adding a channel to accept
the next client, even when the state was no longer RUNNING. That
is fixed by making nbd_can_accept() pay attention to the current
state.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170527030421.28366-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/server.c | 8 +++-----
qemu-nbd.c | 2 +-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index ee59e5d..49b55f6 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1358,17 +1358,15 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
if (exp) {
nbd_export_get(exp);
+ QTAILQ_INSERT_TAIL(&exp->clients, client, next);
}
+ qemu_co_mutex_init(&client->send_lock);
+
if (nbd_negotiate(data)) {
client_close(client);
goto out;
}
- qemu_co_mutex_init(&client->send_lock);
nbd_set_handlers(client);
-
- if (exp) {
- QTAILQ_INSERT_TAIL(&exp->clients, client, next);
- }
out:
g_free(data);
}
diff --git a/qemu-nbd.c b/qemu-nbd.c
index f60842f..651f85e 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -325,7 +325,7 @@ out:
static int nbd_can_accept(void)
{
- return nb_fds < shared;
+ return state == RUNNING && nb_fds < shared;
}
static void nbd_export_closed(NBDExport *exp)
--
1.8.3.1

View file

@ -0,0 +1,46 @@
From e65294157d4b69393b3f819c99f4f647452b48e3 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 28 Aug 2017 14:33:07 +0200
Subject: [PATCH] vga: fix display update region calculation (split screen)
vga display update mis-calculated the region for the dirty bitmap
snapshot in case split screen mode is used. This can trigger an
assert in cpu_physical_memory_snapshot_get_dirty().
Impact: DoS for privileged guest users.
Fixes: CVE-2017-13673
Fixes: fec5e8c92becad223df9d972770522f64aafdb72
Cc: P J P <ppandit@redhat.com>
Reported-by: David Buchanan <d@vidbuchanan.co.uk>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20170828123307.15392-1-kraxel@redhat.com
---
hw/display/vga.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 3433102..ad7a465 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1628,9 +1628,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
y1 = 0;
if (!full_update) {
+ ram_addr_t region_start = addr1;
+ ram_addr_t region_end = addr1 + line_offset * height;
vga_sync_dirty_bitmap(s);
- snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1,
- line_offset * height,
+ if (s->line_compare < height) {
+ /* split screen mode */
+ region_start = 0;
+ }
+ snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
+ region_end - region_start,
DIRTY_MEMORY_VGA);
}
--
1.8.3.1

View file

@ -0,0 +1,90 @@
From fa18f36a461984eae50ab957e47ec78dae3c14fc Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 28 Apr 2017 10:42:37 +0200
Subject: [PATCH] input: limit kbd queue depth
Apply a limit to the number of items we accept into the keyboard queue.
Impact: Without this limit vnc clients can exhaust host memory by
sending keyboard events faster than qemu feeds them to the guest.
Fixes: CVE-2017-8379
Cc: P J P <ppandit@redhat.com>
Cc: Huawei PSIRT <PSIRT@huawei.com>
Reported-by: jiangxin1@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20170428084237.23960-1-kraxel@redhat.com
---
ui/input.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/ui/input.c b/ui/input.c
index ed88cda..fb1f404 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -41,6 +41,8 @@ static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
QTAILQ_HEAD_INITIALIZER(kbd_queue);
static QEMUTimer *kbd_timer;
static uint32_t kbd_default_delay_ms = 10;
+static uint32_t queue_count;
+static uint32_t queue_limit = 1024;
QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
QemuInputHandler *handler)
@@ -268,6 +270,7 @@ static void qemu_input_queue_process(void *opaque)
break;
}
QTAILQ_REMOVE(queue, item, node);
+ queue_count--;
g_free(item);
}
}
@@ -282,6 +285,7 @@ static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
item->delay_ms = delay_ms;
item->timer = timer;
QTAILQ_INSERT_TAIL(queue, item, node);
+ queue_count++;
if (start_timer) {
timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
@@ -298,6 +302,7 @@ static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
item->src = src;
item->evt = evt;
QTAILQ_INSERT_TAIL(queue, item, node);
+ queue_count++;
}
static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
@@ -306,6 +311,7 @@ static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
item->type = QEMU_INPUT_QUEUE_SYNC;
QTAILQ_INSERT_TAIL(queue, item, node);
+ queue_count++;
}
void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
@@ -381,7 +387,7 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
qemu_input_event_send(src, evt);
qemu_input_event_sync();
qapi_free_InputEvent(evt);
- } else {
+ } else if (queue_count < queue_limit) {
qemu_input_queue_event(&kbd_queue, src, evt);
qemu_input_queue_sync(&kbd_queue);
}
@@ -409,8 +415,10 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms)
kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
&kbd_queue);
}
- qemu_input_queue_delay(&kbd_queue, kbd_timer,
- delay_ms ? delay_ms : kbd_default_delay_ms);
+ if (queue_count < queue_limit) {
+ qemu_input_queue_delay(&kbd_queue, kbd_timer,
+ delay_ms ? delay_ms : kbd_default_delay_ms);
+ }
}
InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
--
1.8.3.1

View file

@ -0,0 +1,114 @@
From fec5e8c92becad223df9d972770522f64aafdb72 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 21 Apr 2017 11:16:27 +0200
Subject: [PATCH] vga: make display updates thread safe.
The vga code clears the dirty bits *after* reading the framebuffer
memory. So if the guest framebuffer updates hits the race window
between vga reading the framebuffer and vga clearing the dirty bits
vga will miss that update
Fix it by using the new memory_region_copy_and_clear_dirty()
memory_region_copy_get_dirty() functions. That way we clear the
dirty bitmap before reading the framebuffer. Any guest display
updates happening in parallel will be properly tracked in the
dirty bitmap then and the next display refresh will pick them up.
Problem triggers with mttcg only. Before mttcg was merged tcg
never ran in parallel to vga emulation. Using kvm will hide the
problem too, due to qemu operating on a userspace copy of the
kernel's dirty bitmap.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20170421091632.30900-5-kraxel@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/display/vga.c | 36 +++++++++++++++++-------------------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 3991b88..b2516c8 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1465,7 +1465,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
DisplaySurface *surface = qemu_console_surface(s->con);
int y1, y, update, linesize, y_start, double_scan, mask, depth;
int width, height, shift_control, line_offset, bwidth, bits;
- ram_addr_t page0, page1, page_min, page_max;
+ ram_addr_t page0, page1;
+ DirtyBitmapSnapshot *snap = NULL;
int disp_width, multi_scan, multi_run;
uint8_t *d;
uint32_t v, addr1, addr;
@@ -1480,9 +1481,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
full_update |= update_basic_params(s);
- if (!full_update)
- vga_sync_dirty_bitmap(s);
-
s->get_resolution(s, &width, &height);
disp_width = width;
@@ -1625,11 +1623,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
addr1 = (s->start_addr * 4);
bwidth = (width * bits + 7) / 8;
y_start = -1;
- page_min = -1;
- page_max = 0;
d = surface_data(surface);
linesize = surface_stride(surface);
y1 = 0;
+
+ if (!full_update) {
+ vga_sync_dirty_bitmap(s);
+ snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1,
+ line_offset * height,
+ DIRTY_MEMORY_VGA);
+ }
+
for(y = 0; y < height; y++) {
addr = addr1;
if (!(s->cr[VGA_CRTC_MODE] & 1)) {
@@ -1644,17 +1648,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
update = full_update;
page0 = addr;
page1 = addr + bwidth - 1;
- update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
- DIRTY_MEMORY_VGA);
+ if (full_update) {
+ update = 1;
+ } else {
+ update = memory_region_snapshot_get_dirty(&s->vram, snap,
+ page0, page1 - page0);
+ }
/* explicit invalidation for the hardware cursor */
update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
if (update) {
if (y_start < 0)
y_start = y;
- if (page0 < page_min)
- page_min = page0;
- if (page1 > page_max)
- page_max = page1;
if (!(is_buffer_shared(surface))) {
vga_draw_line(s, d, addr, width);
if (s->cursor_draw_line)
@@ -1687,13 +1691,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
dpy_gfx_update(s->con, 0, y_start,
disp_width, y - y_start);
}
- /* reset modified pages */
- if (page_max >= page_min) {
- memory_region_reset_dirty(&s->vram,
- page_min,
- page_max - page_min,
- DIRTY_MEMORY_VGA);
- }
+ g_free(snap);
memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
}
--
1.8.3.1

View file

@ -0,0 +1,11 @@
--- xen-4.5.1/tools/qemu-xen-traditional/hw/ne2000.c.orig 2015-09-26 17:27:49.494334726 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/hw/ne2000.c 2015-09-26 17:31:53.107474932 +0100
@@ -331,7 +331,7 @@
if (index <= s->stop)
avail = s->stop - index;
else
- avail = 0;
+ break;
len = size;
if (len > avail)
len = avail;

View file

@ -0,0 +1,48 @@
--- xen-4.5.1/tools/qemu-xen-traditional/hw/ne2000.c.orig 2015-06-09 16:32:24.000000000 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/hw/ne2000.c 2015-09-26 17:27:49.494334726 +0100
@@ -304,6 +304,9 @@
}
index = s->curpag << 8;
+ if (index >= NE2000_PMEM_END) {
+ index = s->start;
+ }
/* 4 bytes for header */
total_len = size + 4;
/* address for next packet (4 bytes for CRC) */
@@ -387,15 +390,21 @@
offset = addr | (page << 4);
switch(offset) {
case EN0_STARTPG:
- s->start = val << 8;
+ if (val << 8 <= NE2000_PMEM_END) {
+ s->start = val << 8;
+ }
s->tainted = 1;
break;
case EN0_STOPPG:
- s->stop = val << 8;
+ if (val << 8 <= NE2000_PMEM_END) {
+ s->stop = val << 8;
+ }
s->tainted = 1;
break;
case EN0_BOUNDARY:
- s->boundary = val;
+ if (val << 8 < NE2000_PMEM_END) {
+ s->boundary = val;
+ }
break;
case EN0_IMR:
s->imr = val;
@@ -436,7 +445,9 @@
s->phys[offset - EN1_PHYS] = val;
break;
case EN1_CURPAG:
- s->curpag = val;
+ if (val << 8 < NE2000_PMEM_END) {
+ s->curpag = val;
+ }
s->tainted = 1;
break;
case EN1_MULT ... EN1_MULT + 7:

View file

@ -0,0 +1,12 @@
--- xen-4.5.1/tools/qemu-xen-traditional/hw/e1000.c.orig 2015-06-09 16:32:24.000000000 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/hw/e1000.c 2015-09-26 17:16:36.406544380 +0100
@@ -461,7 +461,8 @@
memmove(tp->data, tp->header, hdr);
tp->size = hdr;
}
- } while (split_size -= bytes);
+ split_size -= bytes;
+ } while (bytes && split_size);
} else if (!tp->tse && tp->cptse) {
// context descriptor TSE is not set, while data descriptor TSE is set
DBGOUT(TXERR, "TCP segmentaion Error\n");

View file

@ -0,0 +1,63 @@
--- xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.c.orig 2015-06-09 16:32:24.000000000 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.c 2015-10-10 16:57:01.806370020 +0100
@@ -268,8 +268,8 @@
return vring_avail_idx(vq) == vq->last_avail_idx;
}
-void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
- unsigned int len, unsigned int idx)
+static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len)
{
unsigned int offset;
int i;
@@ -302,7 +302,19 @@
offset += size;
}
+}
+void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len)
+{
+ vq->last_avail_idx--;
+ virtqueue_unmap_sg(vq, elem, len);
+}
+
+void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len, unsigned int idx)
+{
+ virtqueue_unmap_sg(vq, elem, len);
idx = (idx + vring_used_idx(vq)) % vq->vring.num;
/* Get a pointer to the next entry in the used ring. */
--- xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.h.orig 2015-06-09 16:32:24.000000000 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.h 2015-10-10 16:57:53.146216039 +0100
@@ -105,6 +105,8 @@
void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len);
void virtqueue_flush(VirtQueue *vq, unsigned int count);
+void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len);
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len, unsigned int idx);
--- xen-4.5.1/tools/qemu-xen-traditional/hw/virtio-net.c.orig 2015-10-10 16:10:05.071786348 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/hw/virtio-net.c 2015-10-10 19:05:34.510029916 +0100
@@ -424,11 +424,15 @@
len = iov_fill(sg, elem.in_num,
buf + offset, size - offset);
total += len;
+ offset += len;
+ if (!n->mergeable_rx_bufs && offset < size) {
+ virtqueue_discard(n->rx_vq, &elem, total);
+ return;
+ }
/* signal other side */
virtqueue_fill(n->rx_vq, &elem, total, i++);
- offset += len;
}
if (mhdr)

View file

@ -0,0 +1,37 @@
From 8b98a2f07175d46c3f7217639bd5e03f2ec56343 Mon Sep 17 00:00:00 2001
From: Jason Wang <jasowang@redhat.com>
Date: Mon, 30 Nov 2015 15:00:06 +0800
Subject: [PATCH] pcnet: fix rx buffer overflow(CVE-2015-7512)
Backends could provide a packet whose length is greater than buffer
size. Check for this and truncate the packet to avoid rx buffer
overflow in this case.
Cc: Prasad J Pandit <pjp@fedoraproject.org>
Cc: qemu-stable@nongnu.org
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
tools/qemu-xen-traditional/hw/pcnet.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/tools/qemu-xen-traditional/hw/pcnet.c b/tools/qemu-xen-traditional/hw/pcnet.c
index 309c40b..1f4a3db 100644
--- a/tools/qemu-xen-traditional/hw/pcnet.c
+++ b/tools/qemu-xen-traditional/hw/pcnet.c
@@ -1064,6 +1064,12 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
int pktcount = 0;
if (!s->looptest) {
+ if (size > 4092) {
+#ifdef PCNET_DEBUG_RMD
+ fprintf(stderr, "pcnet: truncates rx packet.\n");
+#endif
+ size = 4092;
+ }
memcpy(src, buf, size);
/* no need to compute the CRC */
src[size] = 0;
--
1.7.0.4

View file

@ -0,0 +1,38 @@
From 00837731d254908a841d69298a4f9f077babaf24 Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Fri, 20 Nov 2015 08:42:33 +0100
Subject: [PATCH] eepro100: Prevent two endless loops
http://lists.nongnu.org/archive/html/qemu-devel/2015-11/msg04592.html
shows an example how an endless loop in function action_command can
be achieved.
During my code review, I noticed a 2nd case which can result in an
endless loop.
Reported-by: Qinghao Tang <luodalongde@gmail.com>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
tools/qemu-xen-traditional/hw/eepro100.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/tools/qemu-xen-traditional/hw/eepro100.c b/tools/qemu-xen-traditional/hw/eepro100.c
index 60333b7..685a478 100644
--- a/tools/qemu-xen-traditional/hw/eepro100.c
+++ b/tools/qemu-xen-traditional/hw/eepro100.c
@@ -774,6 +774,11 @@ static void tx_command(EEPRO100State *s)
uint32_t tx_buffer_address = ldl_phys(tbd_address);
uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
//~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+ if (tx_buffer_size == 0) {
+ /* Prevent an endless loop. */
+ logout("loop in %s:%u\n", __FILE__, __LINE__);
+ break;
+ }
tbd_address += 8;
logout
("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
--
1.7.0.4

View file

@ -0,0 +1,44 @@
From 4c65fed8bdf96780735dbdb92a8bd0d6b6526cc3 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Thu, 3 Dec 2015 18:54:17 +0530
Subject: [PATCH] ui: vnc: avoid floating point exception
While sending 'SetPixelFormat' messages to a VNC server,
the client could set the 'red-max', 'green-max' and 'blue-max'
values to be zero. This leads to a floating point exception in
write_png_palette while doing frame buffer updates.
Reported-by: Lian Yihan <lianyihan@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
tools/qemu-xen-traditional/vnc.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/qemu-xen-traditional/vnc.c b/tools/qemu-xen-traditional/vnc.c
index 7538405..cbe4d33 100644
--- a/tools/qemu-xen-traditional/vnc.c
+++ b/tools/qemu-xen-traditional/vnc.c
@@ -2198,15 +2198,15 @@ static void set_pixel_format(VncState *vs,
}
vs->clientds = vs->serverds;
- vs->clientds.pf.rmax = red_max;
+ vs->clientds.pf.rmax = red_max ? red_max : 0xFF;
count_bits(vs->clientds.pf.rbits, red_max);
vs->clientds.pf.rshift = red_shift;
vs->clientds.pf.rmask = red_max << red_shift;
- vs->clientds.pf.gmax = green_max;
+ vs->clientds.pf.gmax = green_max ? green_max : 0xFF;
count_bits(vs->clientds.pf.gbits, green_max);
vs->clientds.pf.gshift = green_shift;
vs->clientds.pf.gmask = green_max << green_shift;
- vs->clientds.pf.bmax = blue_max;
+ vs->clientds.pf.bmax = blue_max ? blue_max : 0xFF;
count_bits(vs->clientds.pf.bbits, blue_max);
vs->clientds.pf.bshift = blue_shift;
vs->clientds.pf.bmask = blue_max << blue_shift;
--
1.7.0.4

View file

@ -0,0 +1,30 @@
--- xen-4.6.1/tools/qemu-xen-traditional/hw/fw_cfg.c.orig 2016-01-04 15:35:42.000000000 +0000
+++ xen-4.6.1/tools/qemu-xen-traditional/hw/fw_cfg.c 2016-03-06 16:42:33.464296362 +0000
@@ -54,11 +54,15 @@
static void fw_cfg_write(FWCfgState *s, uint8_t value)
{
int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
- FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
+ FWCfgEntry *e = (s->cur_entry == FW_CFG_INVALID) ? NULL :
+ &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
FW_CFG_DPRINTF("write %d\n", value);
- if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) {
+ if (s->cur_entry & FW_CFG_WRITE_CHANNEL
+ && e != NULL
+ && e->callback
+ && s->cur_offset < e->len) {
e->data[s->cur_offset++] = value;
if (s->cur_offset == e->len) {
e->callback(e->callback_opaque, e->data);
@@ -88,7 +92,8 @@
static uint8_t fw_cfg_read(FWCfgState *s)
{
int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
- FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
+ FWCfgEntry *e = (s->cur_entry == FW_CFG_INVALID) ? NULL :
+ &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
uint8_t ret;
if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)

View file

@ -0,0 +1,104 @@
------------------------------------------------------------------------
*From*: Laszlo Ersek
*Subject*: [Qemu-devel] [PATCH] e1000: eliminate infinite loops on
out-of-bounds transfer start
*Date*: Tue, 19 Jan 2016 14:17:20 +0100
------------------------------------------------------------------------
The start_xmit() and e1000_receive_iov() functions implement DMA transfers
iterating over a set of descriptors that the guest's e1000 driver
prepares:
- the TDLEN and RDLEN registers store the total size of the descriptor
area,
- while the TDH and RDH registers store the offset (in whole tx / rx
descriptors) into the area where the transfer is supposed to start.
Each time a descriptor is processed, the TDH and RDH register is bumped
(as appropriate for the transfer direction).
QEMU already contains logic to deal with bogus transfers submitted by the
guest:
- Normally, the transmit case wants to increase TDH from its initial value
to TDT. (TDT is allowed to be numerically smaller than the initial TDH
value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe
that QEMU currently has here is a check against reaching the original
TDH value again -- a complete wraparound, which should never happen.
- In the receive case RDH is increased from its initial value until
"total_size" bytes have been received; preferably in a single step, or
in "s->rxbuf_size" byte steps, if the latter is smaller. However, null
RX descriptors are skipped without receiving data, while RDH is
incremented just the same. QEMU tries to prevent an infinite loop
(processing only null RX descriptors) by detecting whether RDH assumes
its original value during the loop. (Again, wrapping from RDLEN to 0 is
normal.)
What both directions miss is that the guest could program TDLEN and RDLEN
so low, and the initial TDH and RDH so high, that these registers will
immediately be truncated to zero, and then never reassume their initial
values in the loop -- a full wraparound will never occur.
The condition that expresses this is:
xdh_start >= s->mac_reg[XDLEN] / sizeof(desc)
i.e., TDH or RDH start out after the last whole rx or tx descriptor that
fits into the TDLEN or RDLEN sized area.
This condition could be checked before we enter the loops, but
pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for
bogus DMA addresses, so we just extend the existing failsafes with the
above condition.
Cc: "Michael S. Tsirkin" <address@hidden>
Cc: Petr Matousek <address@hidden>
Cc: Stefano Stabellini <address@hidden>
Cc: Prasad Pandit <address@hidden>
Cc: Michael Roth <address@hidden>
Cc: Jason Wang <address@hidden>
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044
Signed-off-by: Laszlo Ersek <address@hidden>
Reviewed-by: Jason Wang <address@hidden>
---
Notes:
Regarding the public posting: we made an honest effort to vet this
vulnerability, and the impact seems low -- no host side reads/writes,
"just" a DoS (infinite loop). We decided the patch could be posted
publicly, for the usual review process. Jason and Prasad checked the
patch in the internal discussion already, but comments, improvements
etc. are clearly welcome. The CVE request is underway. Thanks.
hw/net/e1000.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index bec06e9..34d0823 100644
--- a/tools/qemu-xen-traditional/hw/e1000.c
+++ b/tools/qemu-xen-traditional/hw/e1000.c
@@ -908,7 +908,8 @@ start_xmit(E1000State *s)
* bogus values to TDT/TDLEN.
* there's nothing too intelligent we could do about this.
*/
- if (s->mac_reg[TDH] == tdh_start) {
+ if (s->mac_reg[TDH] == tdh_start ||
+ tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) {
DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
break;
@@ -1165,7 +1166,8 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
s->mac_reg[RDH] = 0;
s->check_rxov = 1;
/* see comment in start_xmit; same here */
- if (s->mac_reg[RDH] == rdh_start) {
+ if (s->mac_reg[RDH] == rdh_start ||
+ rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) {
DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
set_ics(s, 0, E1000_ICS_RXO);
--
1.8.3.1

View file

@ -0,0 +1,56 @@
From: Prasad J Pandit <address@hidden>
When processing remote NDIS control message packets,
the USB Net device emulator uses a fixed length(4096) data buffer.
The incoming informationBufferOffset & Length combination could
overflow and cross that range. Check control message buffer
offsets and length to avoid it.
Reported-by: Qinghao Tang <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
hw/usb/dev-network.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
Update as per review
-> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg03475.html
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 8a4ff49..180adce 100644
--- a/tools/qemu-xen-traditional/hw/usb-net.c
+++ b/tools/qemu-xen-traditional/hw/usb-net.c
@@ -915,8 +915,9 @@ static int rndis_query_response(USBNetState *s,
bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
buflen = le32_to_cpu(buf->InformationBufferLength);
- if (bufoffs + buflen > length)
+ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) {
return USB_RET_STALL;
+ }
infobuflen = ndis_query(s, le32_to_cpu(buf->OID),
bufoffs + (uint8_t *) buf, buflen, infobuf,
@@ -961,8 +962,9 @@ static int rndis_set_response(USBNetState *s,
bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
buflen = le32_to_cpu(buf->InformationBufferLength);
- if (bufoffs + buflen > length)
+ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) {
return USB_RET_STALL;
+ }
ret = ndis_set(s, le32_to_cpu(buf->OID),
bufoffs + (uint8_t *) buf, buflen);
@@ -1212,8 +1214,9 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
uint32_t size = le32_to_cpu(msg->DataLength);
- if (offs + size <= len)
+ if (offs < len && size < len && offs + size <= len) {
qemu_send_packet(s->vc, s->out_buf + offs, size);
+ }
}
s->out_ptr -= len;
memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
--
2.5.0

View file

@ -0,0 +1,34 @@
From: Prasad J Pandit <address@hidden>
Ne2000 NIC uses ring buffer of NE2000_MEM_SIZE(49152)
bytes to process network packets. Registers PSTART & PSTOP
define ring buffer size & location. Setting these registers
to invalid values could lead to infinite loop or OOB r/w
access issues. Add check to avoid it.
Reported-by: Yang Hongke <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
hw/net/ne2000.c | 4 ++++
1 file changed, 4 insertions(+)
Update per review:
-> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg05522.html
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index b032212..ced4666 100644
--- a/tools/qemu-xen-traditional/hw/ne2000.c
+++ b/tools/qemu-xen-traditional/hw/ne2000.c
@@ -154,6 +154,10 @@ static int ne2000_buffer_full(NE2000State *s)
{
int avail, index, boundary;
+ if (s->stop <= s->start) {
+ return 1;
+ }
+
index = s->curpag << 8;
boundary = s->boundary << 8;
if (index < boundary)
--
2.5.0

View file

@ -0,0 +1,45 @@
From: Prasad J Pandit <address@hidden>
While computing IP checksum, 'net_checksum_calculate' reads
payload length from the packet. It could exceed the given 'data'
buffer size. Add a check to avoid it.
Reported-by: Liu Ling <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
net/checksum.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
Update as per review:
-> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg06121.html
diff --git a/net/checksum.c b/net/checksum.c
index 14c0855..0942437 100644
--- a/tools/qemu-xen-traditional/net-checksum.c
+++ b/tools/qemu-xen-traditional/net-checksum.c
@@ -59,6 +59,11 @@ void net_checksum_calculate(uint8_t *data, int length)
int hlen, plen, proto, csum_offset;
uint16_t csum;
+ /* Ensure data has complete L2 & L3 headers. */
+ if (length < 14 + 20) {
+ return;
+ }
+
if ((data[14] & 0xf0) != 0x40)
return; /* not IPv4 */
hlen = (data[14] & 0x0f) * 4;
@@ -76,8 +81,9 @@ void net_checksum_calculate(uint8_t *data, int length)
return;
}
- if (plen < csum_offset+2)
- return;
+ if (plen < csum_offset + 2 || 14 + hlen + plen > length) {
+ return;
+ }
data[14+hlen+csum_offset] = 0;
data[14+hlen+csum_offset+1] = 0;
--
2.5.0

View file

@ -0,0 +1,46 @@
From 3a15cc0e1ee7168db0782133d2607a6bfa422d66 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Fri, 8 Apr 2016 11:33:48 +0530
Subject: [PATCH] net: stellaris_enet: check packet length against receive buffer
When receiving packets over Stellaris ethernet controller, it
uses receive buffer of size 2048 bytes. In case the controller
accepts large(MTU) packets, it could lead to memory corruption.
Add check to avoid it.
Reported-by: Oleksandr Bazhaniuk <oleksandr.bazhaniuk@intel.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 1460095428-22698-1-git-send-email-ppandit@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
tools/qemu-xen-traditional/hw/stellaris_enet.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/tools/qemu-xen-traditional/hw/stellaris_enet.c b/tools/qemu-xen-traditional/hw/stellaris_enet.c
index 84cf60b..6880894 100644
--- a/tools/qemu-xen-traditional/hw/stellaris_enet.c
+++ b/tools/qemu-xen-traditional/hw/stellaris_enet.c
@@ -236,8 +236,18 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si
n = s->next_packet + s->np;
if (n >= 31)
n -= 31;
- s->np++;
+ if (size >= sizeof(s->rx[n].data) - 6) {
+ /* If the packet won't fit into the
+ * emulated 2K RAM, this is reported
+ * as a FIFO overrun error.
+ */
+ s->ris |= SE_INT_FOV;
+ stellaris_enet_update(s);
+ return -1;
+ }
+
+ s->np++;
s->rx[n].len = size + 6;
p = s->rx[n].data;
*(p++) = (size + 6);
--
1.7.0.4

View file

@ -0,0 +1,31 @@
From: Prasad J Pandit <address@hidden>
When receiving packets over MIPSnet network device, it uses
receive buffer of size 1514 bytes. In case the controller
accepts large(MTU) packets, it could lead to memory corruption.
Add check to avoid it.
Reported by: Oleksandr Bazhaniuk <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
tools/qemu-xen-traditional/hw/mipsnet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/qemu-xen-traditional/hw/mipsnet.c b/tools/qemu-xen-traditional/hw/mipsnet.c
index f261011..e134b31 100644
--- a/tools/qemu-xen-traditional/hw/mipsnet.c
+++ b/tools/qemu-xen-traditional/hw/mipsnet.c
@@ -82,6 +82,9 @@ static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t si
if (!mipsnet_can_receive(opaque))
return;
+ if (size >= sizeof(s->rx_buffer)) {
+ return;
+ }
s->busy = 1;
/* Just accept everything. */
--
2.5.5

View file

@ -0,0 +1,44 @@
------------------------------------------------------------------------
*From*: P J P
*Subject*: [Qemu-devel] [PATCH 1/2] scsi: check command buffer length
before write(CVE-2016-4439)
*Date*: Thu, 19 May 2016 16:09:30 +0530
------------------------------------------------------------------------
From: Prasad J Pandit <address@hidden>
The 53C9X Fast SCSI Controller(FSC) comes with an internal 16-byte
FIFO buffer. It is used to handle command and data transfer. While
writing to this command buffer 's->cmdbuf[TI_BUFSZ=16]', a check
was missing to validate input length. Add check to avoid OOB write
access.
Fixes CVE-2016-4439
Reported-by: Li Qiang <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
hw/scsi/esp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/qemu-xen-traditional/hw/esp.c b/tools/qemu-xen-traditional/hw/esp.c
index 8961be2..01497e6 100644
--- a/tools/qemu-xen-traditional/hw/esp.c
+++ b/tools/qemu-xen-traditional/hw/esp.c
@@ -448,7 +448,11 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
break;
case ESP_FIFO:
if (s->do_cmd) {
- s->cmdbuf[s->cmdlen++] = val & 0xff;
+ if (s->cmdlen < TI_BUFSZ) {
+ s->cmdbuf[s->cmdlen++] = val & 0xff;
+ } else {
+ ESP_ERROR("fifo overrun\n");
+ }
} else if (s->ti_size == TI_BUFSZ - 1) {
ESP_ERROR("fifo overrun\n");
} else {
--
2.5.5

View file

@ -0,0 +1,68 @@
------------------------------------------------------------------------
*From*: P J P
*Subject*: [Qemu-devel] [PATCH 2/2] scsi: check dma length before
reading scsi command(CVE-2016-4441)
*Date*: Thu, 19 May 2016 16:09:31 +0530
------------------------------------------------------------------------
From: Prasad J Pandit <address@hidden>
The 53C9X Fast SCSI Controller(FSC) comes with an internal 16-byte
FIFO buffer. It is used to handle command and data transfer.
Routine get_cmd() uses DMA to read scsi commands into this buffer.
Add check to validate DMA length against buffer size to avoid any
overrun.
Fixes CVE-2016-4441
Reported-by: Li Qiang <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
hw/scsi/esp.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/tools/qemu-xen-traditional/hw/esp.c b/tools/qemu-xen-traditional/hw/esp.c
index 01497e6..591c817 100644
--- a/tools/qemu-xen-traditional/hw/esp.c
+++ b/tools/qemu-xen-traditional/hw/esp.c
@@ -82,7 +82,7 @@ void esp_request_cancelled(SCSIRequest *req)
}
}
-static uint32_t get_cmd(ESPState *s, uint8_t *buf)
+static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
{
uint32_t dmalen;
int target;
@@ -92,6 +92,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
target = s->wregs[ESP_WBUSID] & BUSID_DID;
if (s->dma) {
dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
+ if (dmalen > buflen) {
+ return 0;
+ }
s->dma_memory_read(s->dma_opaque, buf, dmalen);
} else {
dmalen = s->ti_size;
@@ -166,7 +169,7 @@ static void handle_satn(ESPState *s)
uint8_t buf[32];
int len;
- len = get_cmd(s, buf);
+ len = get_cmd(s, buf, sizeof(buf));
if (len)
do_cmd(s, buf);
}
@@ -192,7 +195,7 @@ static void handle_satn_stop(ESPState *s)
static void handle_satn_stop(ESPState *s)
{
- s->cmdlen = get_cmd(s, s->cmdbuf);
+ s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
if (s->cmdlen) {
DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
s->do_cmd = 1;
--
2.5.5

View file

@ -0,0 +1,65 @@
------------------------------------------------------------------------
*From*: Paolo Bonzini
*Subject*: Re: [Qemu-devel] [PATCH] scsi: check buffer length before
reading scsi command
*Date*: Wed, 1 Jun 2016 15:10:16 +0200
*User-agent*: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101
Thunderbird/45.1.0
------------------------------------------------------------------------
On 31/05/2016 19:53, P J P wrote:
>/ From: Prasad J Pandit <address@hidden>/
>/ /
>/ The 53C9X Fast SCSI Controller(FSC) comes with an internal 16-byte/
>/ FIFO buffer. It is used to handle command and data transfer./
>/ Routine get_cmd() in non-DMA mode, uses 'ti_size' to read scsi/
>/ command into a buffer. Add check to validate command length against/
>/ buffer size to avoid any overrun./
>/ /
>/ Reported-by: Li Qiang <address@hidden>/
>/ Signed-off-by: Prasad J Pandit <address@hidden>/
>/ ---/
>/ hw/scsi/esp.c | 3 +++/
>/ 1 file changed, 3 insertions(+)/
>/ /
>/ diff --git a/tools/qemu-xen-traditional/hw/esp.c b/tools/qemu-xen-traditional/hw/esp.c/
>/ index 60c1b28..953027a 100644/
>/ --- a/tools/qemu-xen-traditional/hw/esp.c/
>/ +++ b/tools/qemu-xen-traditional/hw/esp.c/
>/ @@ -98,6 +98,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t /
>/ buflen)/
>/ s->dma_memory_read(s->dma_opaque, buf, dmalen);/
>/ } else {/
>/ dmalen = s->ti_size;/
>/ + if (dmalen > TI_BUFSZ) {/
>/ + return 0;/
>/ + }/
>/ memcpy(buf, s->ti_buf, dmalen);/
>/ buf[0] = buf[2] >> 5;/
>/ }/
>/ /
In theory this shouldn't happen, but I agree that it is better to be
defensive. I'm queuing this patch.
At least the following patch is needed to ensure that ti_size always
matches ti_rptr/ti_wptr (Hervé, what do you think about it? should I
resubmit it formally?). Also, things are more complicated than
necessary due to ti_size being used for both DMA and FIFO transfers.
diff --git a/tools/qemu-xen-traditional/hw/esp.c b/tools/qemu-xen-traditional/hw/esp.c
index c2f6f8f..6407844 100644
--- a/tools/qemu-xen-traditional/hw/esp.c
+++ b/tools/qemu-xen-traditional/hw/esp.c
@@ -222,7 +222,7 @@ static void write_response(ESPState *s)
} else {
s->ti_size = 2;
s->ti_rptr = 0;
- s->ti_wptr = 0;
+ s->ti_wptr = 2;
s->rregs[ESP_RFLAGS] = 2;
}
esp_raise_irq(s);

View file

@ -0,0 +1,76 @@
------------------------------------------------------------------------
*From*: P J P
*Subject*: [Qemu-devel] [PATCH v3] scsi: esp: check TI buffer index
before read/write
*Date*: Mon, 6 Jun 2016 22:04:43 +0530
------------------------------------------------------------------------
From: Prasad J Pandit <address@hidden>
The 53C9X Fast SCSI Controller(FSC) comes with internal 16-byte
FIFO buffers. One is used to handle commands and other is for
information transfer. Three control variables 'ti_rptr',
'ti_wptr' and 'ti_size' are used to control r/w access to the
information transfer buffer ti_buf[TI_BUFSZ=16]. In that,
'ti_rptr' is used as read index, where read occurs.
'ti_wptr' is a write index, where write would occur.
'ti_size' indicates total bytes to be read from the buffer.
While reading/writing to this buffer, index could exceed its
size. Add check to avoid OOB r/w access.
Reported-by: Huawei PSIRT <address@hidden>
Reported-by: Li Qiang <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
hw/scsi/esp.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
Update as per:
-> https://lists.gnu.org/archive/html/qemu-devel/2016-06/msg01326.html
diff --git a/tools/qemu-xen-traditional/hw/esp.c b/tools/qemu-xen-traditional/hw/esp.c
index c2f6f8f..4b94bbc 100644
--- a/tools/qemu-xen-traditional/hw/esp.c
+++ b/tools/qemu-xen-traditional/hw/esp.c
@@ -403,18 +403,17 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
switch (saddr) {
case ESP_FIFO:
- if (s->ti_size > 0) {
+ if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
+ /* Data out. */
+ ESP_ERROR("PIO data read not implemented\n");
+ s->rregs[ESP_FIFO] = 0;
+ esp_raise_irq(s);
+ } else if (s->ti_rptr < s->ti_wptr) {
s->ti_size--;
- if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
- /* Data out. */
- ESP_ERROR("PIO data read not implemented\n");
- s->rregs[ESP_FIFO] = 0;
- } else {
- s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
- }
+ s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
esp_raise_irq(s);
}
- if (s->ti_size == 0) {
+ if (s->ti_rptr == s->ti_wptr) {
s->ti_rptr = 0;
s->ti_wptr = 0;
}
@@ -459,7 +457,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
} else {
ESP_ERROR("fifo overrun\n");
}
- } else if (s->ti_size == TI_BUFSZ - 1) {
+ } else if (s->ti_wptr == TI_BUFSZ - 1) {
ESP_ERROR("fifo overrun\n");
} else {
s->ti_size++;
--
2.5.5

View file

@ -0,0 +1,81 @@
From 926cde5f3e4d2504ed161ed0cb771ac7cad6fd11 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Thu, 16 Jun 2016 00:22:35 +0200
Subject: [PATCH] scsi: esp: make cmdbuf big enough for maximum CDB size
While doing DMA read into ESP command buffer 's->cmdbuf', it could
write past the 's->cmdbuf' area, if it was transferring more than 16
bytes. Increase the command buffer size to 32, which is maximum when
's->do_cmd' is set, and add a check on 'len' to avoid OOB access.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/esp.c | 6 ++++--
hw/esp.c | 3 ++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/hw/esp.c b/hw/esp.c
index 64680b3..baa0a2c 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -25,6 +25,7 @@
#include "hw.h"
#include "scsi-disk.h"
#include "scsi.h"
+#include <assert.h>
/* debug ESP card */
//#define DEBUG_ESP
@@ -248,6 +248,8 @@ static void esp_do_dma(ESPState *s)
len = s->dma_left;
if (s->do_cmd) {
DPRINTF("command len %d + %d\n", s->cmdlen, len);
+ assert (s->cmdlen <= sizeof(s->cmdbuf) &&
+ len <= sizeof(s->cmdbuf) - s->cmdlen);
s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
s->ti_size = 0;
s->cmdlen = 0;
@@ -345,7 +347,7 @@ static void handle_ti(ESPState *s)
s->dma_counter = dmalen;
if (s->do_cmd)
- minlen = (dmalen < 32) ? dmalen : 32;
+ minlen = (dmalen < ESP_CMDBUF_SZ) ? dmalen : ESP_CMDBUF_SZ;
else if (s->ti_size < 0)
minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
else
@@ -449,7 +451,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
break;
case ESP_FIFO:
if (s->do_cmd) {
- if (s->cmdlen < TI_BUFSZ) {
+ if (s->cmdlen < ESP_CMDBUF_SZ) {
s->cmdbuf[s->cmdlen++] = val & 0xff;
} else {
ESP_ERROR("fifo overrun\n");
diff --git a/hw/esp.c b/hw/esp.c
index 6c79527..d2c4886 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -14,6 +14,7 @@ void esp_init(hwaddr espaddr, int it_shift,
#define ESP_REGS 16
#define TI_BUFSZ 16
+#define ESP_CMDBUF_SZ 32
typedef struct ESPState ESPState;
@@ -31,7 +32,7 @@ struct ESPState {
uint32_t dma;
SCSIDevice *scsi_dev[ESP_MAX_DEVS];
SCSIDevice *current_dev;
- uint8_t cmdbuf[TI_BUFSZ];
+ uint8_t cmdbuf[ESP_CMDBUF_SZ];
uint32_t cmdlen;
uint32_t do_cmd;
--
1.7.0.4

View file

@ -0,0 +1,37 @@
From 3592fe0c919cf27a81d8e9f9b4f269553418bb01 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Wed, 12 Oct 2016 11:28:08 +0530
Subject: [PATCH] char: serial: check divider value against baud base
16550A UART device uses an oscillator to generate frequencies
(baud base), which decide communication speed. This speed could
be changed by dividing it by a divider. If the divider is
greater than the baud base, speed is set to zero, leading to a
divide by zero error. Add check to avoid it.
Reported-by: Huawei PSIRT <psirt@huawei.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1476251888-20238-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/serial.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/hw/serial.c b/hw/serial.c
index 3442f47..eec72b7 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -153,8 +153,9 @@ static void serial_update_parameters(SerialState *s)
int speed, parity, data_bits, stop_bits, frame_size;
QEMUSerialSetParams ssp;
- if (s->divider == 0)
+ if (s->divider == 0 || s->divider > s->baudbase) {
return;
+ }
frame_size = 1;
if (s->lcr & 0x08) {
--
1.7.0.4

View file

@ -0,0 +1,29 @@
From: Prasad J Pandit <address@hidden>
RTL8139 ethernet controller in C+ mode supports multiple
descriptor rings, each with maximum of 64 descriptors. While
processing transmit descriptor ring in 'rtl8139_cplus_transmit',
it does not limit the descriptor count and runs forever. Add
check to avoid it.
Reported-by: Andrew Henderson <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
hw/net/rtl8139.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 3345bc6..f05e59c 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2350,7 +2350,7 @@ static void rtl8139_cplus_transmit(RTL8139State *s)
{
int txcount = 0;
- while (rtl8139_cplus_transmit_one(s))
+ while (txcount < 64 && rtl8139_cplus_transmit_one(s))
{
++txcount;
}
--
2.7.4

View file

@ -0,0 +1,34 @@
From 77d54985b85a0cb760330ec2bd92505e0a2a97a9 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Tue, 29 Nov 2016 00:38:39 +0530
Subject: [PATCH] net: mcf: check receive buffer size register value
ColdFire Fast Ethernet Controller uses a receive buffer size
register(EMRBR) to hold maximum size of all receive buffers.
It is set by a user before any operation. If it was set to be
zero, ColdFire emulator would go into an infinite loop while
receiving data in mcf_fec_receive. Add check to avoid it.
Reported-by: Wjjzhang <wjjzhang@tencent.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/net/mcf_fec.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index dc61bac..4025eb3 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -393,7 +393,7 @@ static void mcf_fec_write(void *opaque, hwaddr addr,
s->tx_descriptor = s->etdsr;
break;
case 0x188:
- s->emrbr = value & 0x7f0;
+ s->emrbr = value > 0 ? value & 0x7F0 : 0x7F0;
break;
default:
cpu_abort(cpu_single_env, "mcf_fec_write Bad address 0x%x\n",
--
1.7.0.4

View file

@ -0,0 +1,51 @@
From 95ed56939eb2eaa4e2f349fe6dcd13ca4edfd8fb Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Tue, 7 Feb 2017 02:23:33 -0800
Subject: [PATCH] usb: ohci: limit the number of link eds
The guest may builds an infinite loop with link eds. This patch
limit the number of linked ed to avoid this.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Message-id: 5899a02e.45ca240a.6c373.93c1@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ohci.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 2cba3e3..21c93e0 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -42,6 +42,8 @@
#define OHCI_MAX_PORTS 15
+#define ED_LINK_LIMIT 4
+
static int64_t usb_frame_time;
static int64_t usb_bit_time;
@@ -1184,7 +1186,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
uint32_t next_ed;
uint32_t cur;
int active;
-
+ uint32_t link_cnt = 0;
active = 0;
if (head == 0)
@@ -1199,6 +1201,10 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
next_ed = ed.next & OHCI_DPTR_MASK;
+ if (++link_cnt > ED_LINK_LIMIT) {
+ return 0;
+ }
+
if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
uint32_t addr;
/* Cancel pending packets for ED that have been paused. */
--
1.8.3.1

View file

@ -0,0 +1,51 @@
From 215902d7b6fb50c6fc216fc74f770858278ed904 Mon Sep 17 00:00:00 2001
From: hangaohuai <hangaohuai@huawei.com>
Date: Tue, 14 Mar 2017 14:39:19 +0800
Subject: [PATCH] fix :cirrus_vga fix OOB read case qemu Segmentation fault
check the validity of parameters in cirrus_bitblt_rop_fwd_transp_xxx
and cirrus_bitblt_rop_fwd_xxx to avoid the OOB read which causes qemu Segmentation fault.
After the fix, we will touch the assert in
cirrus_invalidate_region:
assert(off_cur_end >= off_cur);
Signed-off-by: fangying <fangying1@huawei.com>
Signed-off-by: hangaohuai <hangaohuai@huawei.com>
Message-id: 20170314063919.16200-1-hangaohuai@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/cirrus_vga_rop.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/cirrus_vga_rop.h b/hw/cirrus_vga_rop.h
index 0925a00..b7447f8 100644
--- a/hw/cirrus_vga_rop.h
+++ b/hw/cirrus_vga_rop.h
@@ -97,6 +97,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
src = src_ - src_base;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
+
+ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
+ return;
+ }
+
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
p = *(dst_base + m(dst));
@@ -143,6 +148,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
src = src_ - src_base;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
+
+ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
+ return;
+ }
+
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x+=2) {
p1 = *(dst_base + m(dst));
--
1.8.3.1

View file

@ -0,0 +1,38 @@
From 3268a845f41253fb55852a8429c32b50f36f349a Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 28 Apr 2017 09:56:12 +0200
Subject: [PATCH] audio: release capture buffers
AUD_add_capture() allocates two buffers which are never released.
Add the missing calls to AUD_del_capture().
Impact: Allows vnc clients to exhaust host memory by repeatedly
starting and stopping audio capture.
Fixes: CVE-2017-8309
Cc: P J P <ppandit@redhat.com>
Cc: Huawei PSIRT <PSIRT@huawei.com>
Reported-by: "Jiangxin (hunter, SCC)" <jiangxin1@huawei.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 20170428075612.9997-1-kraxel@redhat.com
---
audio/audio.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/audio/audio.c b/audio/audio.c
index c8898d8..beafed2 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -2028,6 +2028,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
sw = sw1;
}
LIST_REMOVE (cap, entries);
+ qemu_free (cap->hw.mix_buf);
+ qemu_free (cap->buf);
qemu_free (cap);
}
return;
--
1.8.3.1

View file

@ -0,0 +1,31 @@
From 26f670a244982335cc08943fb1ec099a2c81e42d Mon Sep 17 00:00:00 2001
From: Li Qiang <liqiang6-s@360.cn>
Date: Tue, 7 Feb 2017 03:15:03 -0800
Subject: [PATCH] usb: ohci: fix error return code in servicing iso td
It should return 1 if an error occurs when reading iso td.
This will avoid an infinite loop issue in ohci_service_ed_list.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Message-id: 5899ac3e.1033240a.944d5.9a2d@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ohci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c82a92f..2cba3e3 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -725,7 +725,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
if (!ohci_read_iso_td(addr, &iso_td)) {
printf("usb-ohci: ISO_TD read error at %x\n", addr);
- return 0;
+ return 1;
}
starting_frame = OHCI_BM(iso_td.flags, TD_SF);
--
1.8.3.1

View file

@ -0,0 +1,76 @@
From 4299b90e9ba9ce5ca9024572804ba751aa1a7e70 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Tue, 18 Oct 2016 13:15:17 +0530
Subject: [PATCH] display: cirrus: check vga bits per pixel(bpp) value
In Cirrus CLGD 54xx VGA Emulator, if cirrus graphics mode is VGA,
'cirrus_get_bpp' returns zero(0), which could lead to a divide
by zero error in while copying pixel data. The same could occur
via blit pitch values. Add check to avoid it.
Reported-by: Huawei PSIRT <psirt@huawei.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 1476776717-24807-1-git-send-email-ppandit@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/cirrus_vga.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 3d712d5..bdb092e 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -272,6 +272,9 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
static bool blit_region_is_unsafe(struct CirrusVGAState *s,
int32_t pitch, int32_t addr)
{
+ if (!pitch) {
+ return true;
+ }
if (pitch < 0) {
int64_t min = addr
+ ((int64_t)s->cirrus_blt_height - 1) * pitch
@@ -715,7 +718,7 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
s->cirrus_addr_mask));
}
-static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
{
int sx = 0, sy = 0;
int dx = 0, dy = 0;
@@ -729,6 +732,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
int width, height;
depth = s->get_bpp((VGAState *)s) / 8;
+ if (!depth) {
+ return 0;
+ }
s->get_resolution((VGAState *)s, &width, &height);
/* extra x, y */
@@ -783,6 +789,8 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
s->cirrus_blt_dstpitch, s->cirrus_blt_width,
s->cirrus_blt_height);
+
+ return 1;
}
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
@@ -790,11 +798,9 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
if (blit_is_unsafe(s))
return 0;
- cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
+ return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
s->cirrus_blt_srcaddr - s->start_addr,
s->cirrus_blt_width, s->cirrus_blt_height);
-
- return 1;
}
/***************************************
--
1.7.0.4

View file

@ -4,5 +4,4 @@ SHA512 (newlib-1.16.0.tar.gz) = 40eb96bbc6736a16b6399e0cdb73e853d0d90b685c967e77
SHA512 (zlib-1.2.3.tar.gz) = 021b958fcd0d346c4ba761bcf0cc40f3522de6186cf5a0a6ea34a70504ce9622b1c2626fce40675bc8282cf5f5ade18473656abc38050f72f5d6480507a2106e
SHA512 (polarssl-1.1.4-gpl.tgz) = 88da614e4d3f4409c4fd3bb3e44c7587ba051e3fed4e33d526069a67e8180212e1ea22da984656f50e290049f60ddca65383e5983c0f8884f648d71f698303ad
SHA512 (pciutils-2.2.9.tar.bz2) = 2b3d98d027e46d8c08037366dde6f0781ca03c610ef2b380984639e4ef39899ed8d8b8e4cd9c9dc54df101279b95879bd66bfd4d04ad07fef41e847ea7ae32b5
SHA512 (mini-os-4.21.0.tar.xz) = 7543774d15da84476d93d04154990923c82209cb3fa125574c0383652c5a310957200f54b63b34502161f9c3afce4907e0060d9036f3eaf3a7cb6b1b3119b546
SHA512 (xen-4.21.1.tar.xz) = 8dfe65255e202b3dacf9d0d7265636bc1f97627c11b08babc13a5b8e74c7c65e7e2c6a1513e28b3c713fe512edb6702a73b2bf667e2a8f2ce825b196a2cd5aab
SHA512 (xen-4.9.3.tar.gz) = 989efad2b09504ea56a887991c6741e99d9691e483434650759e6a5cfbdbf78e265ee4f34f8609252d121ada361e364b49c5293c099ba2fff1a1da9331778eb3

View file

@ -0,0 +1,27 @@
--- xen-4.1.0-orig/tools/hotplug/Linux/vif-bridge 2008-08-22 10:49:07.000000000 +0100
+++ xen-4.1.0-new/tools/hotplug/Linux/vif-bridge 2008-08-29 11:29:38.000000000 +0100
@@ -96,8 +96,6 @@ case "$command" in
;;
esac
-handle_iptable
-
call_hooks vif post
log debug "Successful vif-bridge $command for $dev, bridge $bridge."
--- xen-3.3.0-orig/tools/hotplug/Linux/xen-network-common.sh 2008-08-22 10:49:07.000000000 +0100
+++ xen-3.3.0-new/tools/hotplug/Linux/xen-network-common.sh 2008-08-29 11:29:38.000000000 +0100
@@ -99,6 +99,13 @@ create_bridge () {
brctl addbr ${bridge}
brctl stp ${bridge} off
brctl setfd ${bridge} 0
+ # Setting these to zero stops guest<->LAN traffic
+ # traversing the bridge from hitting the *tables
+ # rulesets. guest<->host traffic still gets processed
+ # by the host's iptables rules so this isn't a hole
+ sysctl -q -w "net.bridge.bridge-nf-call-arptables=0"
+ sysctl -q -w "net.bridge.bridge-nf-call-ip6tables=0"
+ sysctl -q -w "net.bridge.bridge-nf-call-iptables=0"
fi
}

View file

@ -1,54 +1,56 @@
--- xen-4.18.0-rc1/tools/xenstored/watch.c.orig 2023-09-29 09:09:29.000000000 +0100
+++ xen-4.18.0-rc1/tools/xenstored/watch.c 2023-10-02 16:12:14.971264769 +0100
@@ -164,7 +164,7 @@
const char **path, bool *relative)
{
*relative = !strstarts(*path, "/") && !strstarts(*path, "@");
- *path = canonicalize(conn, ctx, *path, true);
+ *path = xenstore_canonicalize(conn, ctx, *path, true);
return *path ? 0 : errno;
}
@@ -250,7 +250,7 @@
--- xen-4.9.0-rc1.2/tools/xenstore/xenstored_watch.c.orig 2017-04-12 16:18:57.000000000 +0100
+++ xen-4.9.0-rc1.2/tools/xenstore/xenstored_watch.c 2017-04-13 21:17:12.255231094 +0100
@@ -166,7 +166,7 @@
/* check if valid event */
} else {
relative = !strstarts(vec[0], "/");
- vec[0] = canonicalize(conn, in, vec[0]);
+ vec[0] = xenstore_canonicalize(conn, in, vec[0]);
if (!vec[0])
return ENOMEM;
if (!is_valid_nodename(vec[0]))
@@ -219,7 +219,7 @@
if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
return EINVAL;
- node = canonicalize(conn, ctx, vec[0], true);
+ node = xenstore_canonicalize(conn, ctx, vec[0], true);
- node = canonicalize(conn, in, vec[0]);
+ node = xenstore_canonicalize(conn, in, vec[0]);
if (!node)
return errno;
return ENOMEM;
list_for_each_entry(watch, &conn->watches, list) {
--- xen-4.18.0-rc1/tools/xenstored/core.c.orig 2023-09-29 09:09:29.000000000 +0100
+++ xen-4.18.0-rc1/tools/xenstored/core.c 2023-10-02 16:12:14.993264626 +0100
@@ -1249,7 +1249,7 @@
--- xen-4.9.0-rc1.2/tools/xenstore/xenstored_core.c.orig 2017-04-12 16:18:57.000000000 +0100
+++ xen-4.9.0-rc1.2/tools/xenstore/xenstored_core.c 2017-04-13 21:19:35.668429881 +0100
@@ -777,7 +777,7 @@
return strings;
}
-const char *canonicalize(struct connection *conn, const void *ctx,
+const char *xenstore_canonicalize(struct connection *conn, const void *ctx,
const char *node, bool allow_special)
-char *canonicalize(struct connection *conn, const void *ctx, const char *node)
+char *xenstore_canonicalize(struct connection *conn, const void *ctx, const char *node)
{
const char *name;
@@ -1303,7 +1303,7 @@
{
struct node *node;
const char *prefix;
- *canonical_name = canonicalize(conn, ctx, name, allow_special);
+ *canonical_name = xenstore_canonicalize(conn, ctx, name, allow_special);
if (!*canonical_name)
return NULL;
@@ -799,7 +799,7 @@
@@ -1320,7 +1320,7 @@
const char *tmp_name;
const struct node *node;
if (!canonical_name)
canonical_name = &tmp_name;
- *canonical_name = canonicalize(conn, ctx, name);
+ *canonical_name = xenstore_canonicalize(conn, ctx, name);
return get_node(conn, ctx, *canonical_name, perm);
}
- tmp_name = canonicalize(conn, ctx, name, allow_special);
+ tmp_name = xenstore_canonicalize(conn, ctx, name, allow_special);
if (!tmp_name)
return NULL;
--- xen-4.9.0-rc1.2/tools/xenstore/xenstored_core.h.orig 2017-04-12 16:18:57.000000000 +0100
+++ xen-4.9.0-rc1.2/tools/xenstore/xenstored_core.h 2017-04-13 21:20:29.146368478 +0100
@@ -148,7 +148,7 @@
void send_ack(struct connection *conn, enum xsd_sockmsg_type type);
--- xen-4.18.0-rc1/tools/console/testsuite/console-dom0.c.orig 2023-09-29 09:09:29.000000000 +0100
+++ xen-4.18.0-rc1/tools/console/testsuite/console-dom0.c 2023-10-02 16:12:15.001264574 +0100
/* Canonicalize this path if possible. */
-char *canonicalize(struct connection *conn, const void *ctx, const char *node);
+char *xenstore_canonicalize(struct connection *conn, const void *ctx, const char *node);
/* Write a node to the tdb data base. */
int write_node_raw(struct connection *conn, TDB_DATA *key, struct node *node);
--- xen-4.8.0/tools/console/testsuite/console-dom0.c.orig 2016-12-05 12:03:27.000000000 +0000
+++ xen-4.8.0/tools/console/testsuite/console-dom0.c 2017-02-26 21:52:24.554678631 +0000
@@ -18,7 +18,7 @@
}
}
@ -85,8 +87,8 @@
fprintf(stderr, "%s", line);
} while (strcmp(line, "Okay.\n") != 0);
--- xen-4.18.0-rc1/tools/console/testsuite/console-domU.c.orig 2023-09-29 09:09:29.000000000 +0100
+++ xen-4.18.0-rc1/tools/console/testsuite/console-domU.c 2023-10-02 16:12:15.008264528 +0100
--- xen-4.8.0/tools/console/testsuite/console-domU.c.orig 2016-12-05 12:03:27.000000000 +0000
+++ xen-4.8.0/tools/console/testsuite/console-domU.c 2017-02-26 21:52:50.320622804 +0000
@@ -6,7 +6,7 @@
#include <termios.h>
#include <unistd.h>
@ -105,14 +107,3 @@
seed = strtoul(line, 0, 0);
printf("Seed Okay.\n"); fflush(stdout);
--- xen-4.18.0-rc1/tools/xenstored/core.h.orig 2023-09-29 09:09:29.000000000 +0100
+++ xen-4.18.0-rc1/tools/xenstored/core.h 2023-10-02 16:12:15.015264482 +0100
@@ -240,7 +240,7 @@
void send_ack(struct connection *conn, enum xsd_sockmsg_type type);
/* Canonicalize this path if possible. */
-const char *canonicalize(struct connection *conn, const void *ctx,
+const char *xenstore_canonicalize(struct connection *conn, const void *ctx,
const char *node, bool allow_special);
/* Get access permissions. */

View file

@ -1,13 +0,0 @@
--- xen-4.20.0-rc4/xen/arch/x86/arch.mk.orig 2025-02-07 11:56:01.000000000 +0000
+++ xen-4.20.0-rc4/xen/arch/x86/arch.mk 2025-02-09 22:56:05.579507311 +0000
@@ -95,7 +95,9 @@
-c $(srctree)/$(efi-check).c -o $(efi-check).o,y)
# Check if the linker supports PE.
-EFI_LDFLAGS := $(patsubst -m%,-mi386pep,$(LDFLAGS)) --subsystem=10 --enable-long-section-names
+#EFI_LDFLAGS := $(patsubst -m%,-mi386pep,$(LDFLAGS)) --subsystem=10 --enable-long-section-names
+# use a reduced set of options from LDFLAGS
+EFI_LDFLAGS = --as-needed --build-id=sha1 -mi386pep --subsystem=10 --enable-long-section-names
LD_PE_check_cmd = $(call ld-option,$(EFI_LDFLAGS) --image-base=0x100000000 -o $(efi-check).efi $(efi-check).o)
XEN_BUILD_PE := $(LD_PE_check_cmd)

11
xen.fedora.crypt.patch Normal file
View file

@ -0,0 +1,11 @@
--- xen-4.5.1/tools/qemu-xen-traditional/vnc.c.orig 2015-07-12 21:55:32.875504811 +0100
+++ xen-4.5.1/tools/qemu-xen-traditional/vnc.c 2015-07-12 22:03:03.860005391 +0100
@@ -2140,7 +2140,7 @@
GNUTLS_VERSION_NUMBER >= 0x020200 /* 2.2.0 */
static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
{
- const char *priority = x509 ? "NORMAL" : "NORMAL:+ANON-DH";
+ const char *priority = x509 ? "@SYSTEM" : "@SYSTEM:+ANON-DH";
int rc;
rc = gnutls_priority_set_direct(s, priority, NULL);

View file

@ -0,0 +1,57 @@
--- xen-4.8.0/xen/arch/x86/Makefile.orig 2016-12-05 12:03:27.000000000 +0000
+++ xen-4.8.0/xen/arch/x86/Makefile 2017-02-28 00:02:27.989589825 +0000
@@ -73,6 +73,7 @@
efi-y := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \
-O $(BASEDIR)/include/xen/compile.h ]; then \
echo '$(TARGET).efi'; fi)
+LD_EFI ?= $(LD)
ifneq ($(build_id_linker),)
notes_phdrs = --notes
@@ -173,20 +174,20 @@
$(TARGET).efi: prelink-efi.o $(note_file) efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbols-dummy.o efi/mkreloc
$(foreach base, $(VIRT_BASE) $(ALT_BASE), \
- $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< efi/relocs-dummy.o \
+ $(guard) $(LD_EFI) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< efi/relocs-dummy.o \
$(BASEDIR)/common/symbols-dummy.o $(note_file) -o $(@D)/.$(@F).$(base).0 &&) :
$(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) $(ALT_BASE),$(@D)/.$(@F).$(base).0) >$(@D)/.$(@F).0r.S
$(guard) $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).0 \
| $(guard) $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).0s.S
$(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o
$(foreach base, $(VIRT_BASE) $(ALT_BASE), \
- $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< \
+ $(guard) $(LD_EFI) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< \
$(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o $(note_file) -o $(@D)/.$(@F).$(base).1 &&) :
$(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) $(ALT_BASE),$(@D)/.$(@F).$(base).1) >$(@D)/.$(@F).1r.S
$(guard) $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).1 \
| $(guard) $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).1s.S
$(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o
- $(guard) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds -N $< \
+ $(guard) $(LD_EFI) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds -N $< \
$(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o $(note_file) -o $@
if $(guard) false; then rm -f $@; echo 'EFI support disabled'; \
else $(NM) -pa --format=sysv $(@D)/$(@F) \
--- xen-4.9.0-rc1.2/xen/arch/x86/efi/Makefile.orig 2017-04-12 16:18:57.000000000 +0100
+++ xen-4.9.0-rc1.2/xen/arch/x86/efi/Makefile 2017-04-13 21:05:54.170387130 +0100
@@ -1,8 +1,9 @@
CFLAGS += -fshort-wchar
+LD_EFI ?= $(LD)
efi := y$(shell rm -f disabled)
efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) .%.d,$(CFLAGS)) -c check.c 2>disabled && echo y))
-efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2>disabled && echo y))
+efi := $(if $(efi),$(shell $(LD_EFI) -mi386pep --subsystem=10 -o check.efi check.o 2>disabled && echo y))
efi := $(if $(efi),$(shell rm disabled)y)
%.o: %.ihex
--- xen-4.8.0/xen/Makefile.orig 2016-12-05 12:03:27.000000000 +0000
+++ xen-4.8.0/xen/Makefile 2017-02-28 00:02:54.080529810 +0000
@@ -20,6 +20,7 @@
MAKEFLAGS += -rR
EFI_MOUNTPOINT ?= $(BOOT_DIR)/efi
+EFI_VENDOR=fedora
ARCH=$(XEN_TARGET_ARCH)
SRCARCH=$(shell echo $(ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')

View file

@ -1,6 +1,7 @@
--- xen-4.17.0/tools/hotplug/Linux/systemd/Makefile.orig 2022-12-08 18:03:08.000000000 +0000
+++ xen-4.17.0/tools/hotplug/Linux/systemd/Makefile 2022-12-09 19:47:53.227189371 +0000
@@ -10,7 +10,8 @@
diff -uN xen-4.5.0/tools/hotplug/Linux/systemd.orig/Makefile xen-4.5.0/tools/hotplug/Linux/systemd/Makefile
--- xen-4.5.0/tools/hotplug/Linux/systemd.orig/Makefile 2015-01-12 16:53:24.000000000 +0000
+++ xen-4.5.0/tools/hotplug/Linux/systemd/Makefile 2015-01-25 22:23:26.000000000 +0000
@@ -14,7 +14,8 @@
XEN_SYSTEMD_SERVICE += xen-qemu-dom0-disk-backend.service
XEN_SYSTEMD_SERVICE += xendomains.service
XEN_SYSTEMD_SERVICE += xen-watchdog.service
@ -9,7 +10,16 @@
+XEN_SYSTEMD_SERVICE += oxenstored.service
XEN_SYSTEMD_SERVICE += xendriverdomain.service
ALL_XEN_SYSTEMD := $(XEN_SYSTEMD_MODULES) \
ALL_XEN_SYSTEMD = $(XEN_SYSTEMD_MODULES) \
diff -uN xen-4.5.0/tools/hotplug/Linux/systemd.orig/var-lib-xenstored.mount.in xen-4.5.0/tools/hotplug/Linux/systemd/var-lib-xenstored.mount.in
--- xen-4.5.0/tools/hotplug/Linux/systemd.orig/var-lib-xenstored.mount.in 2015-01-12 16:53:24.000000000 +0000
+++ xen-4.5.0/tools/hotplug/Linux/systemd/var-lib-xenstored.mount.in 2015-01-25 22:28:59.000000000 +0000
@@ -9,4 +9,4 @@
What=xenstore
Where=@XEN_LIB_STORED@
Type=tmpfs
-Options=mode=755
+Options=mode=755,context="system_u:object_r:xenstored_var_lib_t:s0"
diff -uN xen-4.5.0/tools/hotplug/Linux/systemd.orig/xenconsoled.service.in xen-4.5.0/tools/hotplug/Linux/systemd/xenconsoled.service.in
--- xen-4.5.0/tools/hotplug/Linux/systemd.orig/xenconsoled.service.in 2015-01-12 16:53:24.000000000 +0000
+++ xen-4.5.0/tools/hotplug/Linux/systemd/xenconsoled.service.in 2015-01-25 22:30:26.000000000 +0000
@ -49,26 +59,27 @@ diff -uN xen-4.5.0/tools/hotplug/Linux/systemd.orig/xen-qemu-dom0-disk-backend.s
Before=xendomains.service libvirtd.service libvirt-guests.service
RefuseManualStop=true
ConditionPathExists=/proc/xen/capabilities
--- xen-4.17.0/tools/configure.ac.orig 2022-12-08 18:03:08.000000000 +0000
+++ xen-4.17.0/tools/configure.ac 2022-12-09 19:50:24.773193862 +0000
@@ -481,8 +481,8 @@
--- xen-4.6.0/tools/configure.ac.orig 2015-02-15 16:47:22.000000000 +0000
+++ xen-4.6.0/tools/configure.ac 2015-03-01 16:18:30.493647587 +0000
@@ -382,9 +382,9 @@
AS_IF([test "x$systemd" = "xy"], [
AC_CONFIG_FILES([
+ hotplug/Linux/systemd/oxenstored.service
hotplug/Linux/systemd/proc-xen.mount
hotplug/Linux/systemd/var-lib-xenstored.mount
- hotplug/Linux/systemd/xen-init-dom0.service
hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service
hotplug/Linux/systemd/xen-watchdog.service
hotplug/Linux/systemd/xenconsoled.service
--- xen-4.17.0/tools/configure.orig 2022-12-08 18:03:08.000000000 +0000
+++ xen-4.17.0/tools/configure 2022-12-09 19:51:43.278708226 +0000
@@ -10081,7 +10081,7 @@
if test "x$systemd" = "xy"
then :
--- xen-4.6.0/tools/configure.orig 2015-02-15 16:47:22.000000000 +0000
+++ xen-4.6.0/tools/configure 2015-03-01 16:20:10.648285840 +0000
@@ -8995,7 +8995,7 @@
- ac_config_files="$ac_config_files hotplug/Linux/systemd/proc-xen.mount hotplug/Linux/systemd/xen-init-dom0.service hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hotplug/Linux/systemd/xenconsoled.service hotplug/Linux/systemd/xendomains.service hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xenstored.service"
+ ac_config_files="$ac_config_files hotplug/Linux/systemd/oxenstored.service hotplug/Linux/systemd/proc-xen.mount hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hotplug/Linux/systemd/xenconsoled.service hotplug/Linux/systemd/xendomains.service hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xenstored.service"
if test "x$systemd" = "xy"; then :
- ac_config_files="$ac_config_files hotplug/Linux/systemd/proc-xen.mount hotplug/Linux/systemd/var-lib-xenstored.mount hotplug/Linux/systemd/xen-init-dom0.service hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hotplug/Linux/systemd/xenconsoled.service hotplug/Linux/systemd/xendomains.service hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xenstored.service"
+ ac_config_files="$ac_config_files hotplug/Linux/systemd/oxenstored.service hotplug/Linux/systemd/proc-xen.mount hotplug/Linux/systemd/var-lib-xenstored.mount hotplug/Linux/systemd/xen-qemu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hotplug/Linux/systemd/xenconsoled.service hotplug/Linux/systemd/xendomains.service hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xenstored.service"
fi

View file

@ -1,24 +0,0 @@
--- xen-4.14.0/xen/include/crypto/vmac.h.orig 2020-07-23 16:07:51.000000000 +0100
+++ xen-4.14.0/xen/include/crypto/vmac.h 2020-10-24 15:45:49.246467465 +0100
@@ -142,7 +142,7 @@
#define vmac_update vhash_update
-void vhash_update(unsigned char m[],
+void vhash_update(uint8_t *m,
unsigned int mbytes,
vmac_ctx_t *ctx);
diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c
index 320e06f..618ae92 100644
--- a/xen/arch/x86/tboot.c
+++ b/xen/arch/x86/tboot.c
@@ -91,7 +91,7 @@ static void __init tboot_copy_memory(unsigned char *va, uint32_t size,
void __init tboot_probe(void)
{
- tboot_shared_t *tboot_shared;
+ tboot_shared_t * volatile tboot_shared;
static const uuid_t __initconst tboot_shared_uuid = TBOOT_SHARED_UUID;
/* Look for valid page-aligned address for shared page. */

View file

@ -1,10 +0,0 @@
--- xen-4.16.0/Config.mk.orig 2021-11-30 11:42:42.000000000 +0000
+++ xen-4.16.0/Config.mk 2022-01-24 20:25:16.687125822 +0000
@@ -186,6 +186,7 @@
$(call cc-option-add,CFLAGS,CC,-Wno-unused-but-set-variable)
$(call cc-option-add,CFLAGS,CC,-Wno-unused-local-typedefs)
+$(call cc-option-add,CFLAGS,CC,-Wno-error=array-bounds)
LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i))
CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))

12
xen.gcc7.fix.patch Normal file
View file

@ -0,0 +1,12 @@
--- xen-4.8.0/extras/mini-os/Makefile.orig 2016-09-28 12:09:38.000000000 +0100
+++ xen-4.8.0/extras/mini-os/Makefile 2017-02-15 21:15:19.340197960 +0000
@@ -142,6 +142,9 @@
APP_LDLIBS += -lz
APP_LDLIBS += -lm
LDLIBS += -lc
+ifeq ($(MINIOS_TARGET_ARCH),x86_32)
+LDLIBS += -L$(shell dirname `gcc -m32 -print-libgcc-file-name`) -lgcc
+endif
endif
ifneq ($(APP_OBJS)-$(lwip),-y)

View file

@ -1,23 +0,0 @@
--- xen-4.11.1/xen/drivers/passthrough/vtd/vtd.h.orig 2018-11-29 14:04:11.000000000 +0000
+++ xen-4.11.1/xen/drivers/passthrough/vtd/vtd.h 2019-02-05 21:32:50.056774501 +0000
@@ -28,7 +28,7 @@
/* Allow for both IOAPIC and IOSAPIC. */
#define IO_xAPIC_route_entry IO_APIC_route_entry
-struct IO_APIC_route_remap_entry {
+struct __packed IO_APIC_route_remap_entry {
union {
u64 val;
struct {
--- xen-4.11.1/xen/arch/x86/cpu/mtrr/generic.c.orig 2018-11-29 14:04:11.000000000 +0000
+++ xen-4.11.1/xen/arch/x86/cpu/mtrr/generic.c 2019-02-10 19:24:09.378805103 +0000
@@ -171,6 +171,9 @@
printk("%sMTRR variable ranges %sabled:\n", level,
mtrr_state.enabled ? "en" : "dis");
width = (paddr_bits - PAGE_SHIFT + 3) / 4;
+ if ( width > 64 ) {
+ width=64;
+ }
for (i = 0; i < num_var_ranges; ++i) {
if (mtrr_state.var_ranges[i].mask & MTRR_PHYSMASK_VALID)

View file

@ -1,88 +0,0 @@
From 90b20547b756a5cf9b0fec9fb0de5b361e8bf4c3 Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Fri, 10 Apr 2026 21:55:46 +0100
Subject: [PATCH] x86/amd: Mitigate AMD-SN-7053 / FP-DSS
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit
This is XSA-488 / CVE-2025-54505
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
(cherry picked from commit 99912d346009fda1e7fb1510c9501fbab17e92a0)
---
xen/arch/x86/cpu/amd.c | 37 ++++++++++++++++++++++++++++
xen/arch/x86/include/asm/msr-index.h | 1 +
2 files changed, 38 insertions(+)
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 8c55d233f3..1bb0766ebf 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -1048,6 +1048,42 @@ void amd_init_de_cfg(const struct cpuinfo_x86 *c)
wrmsrl(MSR_AMD64_DE_CFG, val | new);
}
+static void amd_init_fp_cfg(const struct cpuinfo_x86 *c)
+{
+ uint64_t val, new = 0;
+
+ /* If virtualised, we won't have mutable access even if we can read it. */
+ if ( cpu_has_hypervisor )
+ return;
+
+ /*
+ * On Zen1, mitigate SB-7053 / FP-DSS Floating Point Divider State
+ * Sampling by setting bit 9 as instructed.
+ */
+ if ( c->family == 0x17 && is_zen1_uarch() )
+ new |= 1 << 9;
+
+ /*
+ * Avoid reading FP_CFG if we don't intend to change anything. The
+ * register doesn't exist on all families.
+ */
+ if ( !new )
+ return;
+
+ val = rdmsr(MSR_AMD64_FP_CFG);
+
+ if ( (val & new) == new )
+ return;
+
+ /*
+ * FP_CFG is a Core-scoped MSR, and this write is racy. However, both
+ * threads calculate the new value from state which expected to be
+ * consistent across CPUs and unrelated to the old value, so the result
+ * should be consistent.
+ */
+ wrmsr(MSR_AMD64_FP_CFG, val | new);
+}
+
void __init amd_init_lfence_dispatch(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -1120,6 +1156,7 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
uint64_t value;
amd_init_de_cfg(c);
+ amd_init_fp_cfg(c);
if (c == &boot_cpu_data)
amd_init_lfence_dispatch(); /* Needs amd_init_de_cfg() */
diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h
index df52587c85..6c5b2569e1 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -428,6 +428,7 @@
#define MSR_AMD64_LS_CFG 0xc0011020U
#define MSR_AMD64_IC_CFG 0xc0011021U
#define MSR_AMD64_DC_CFG 0xc0011022U
+#define MSR_AMD64_FP_CFG 0xc0011028U
#define MSR_AMD64_DE_CFG 0xc0011029U
#define AMD64_DE_CFG_LFENCE_SERIALISE (_AC(1, ULL) << 1)
#define MSR_AMD64_EX_CFG 0xc001102cU
--
2.39.5

20
xen.glibcfix.patch Normal file
View file

@ -0,0 +1,20 @@
--- xen-4.7.0/tools/blktap2/control/tap-ctl-allocate.c.orig 2016-06-20 11:38:15.000000000 +0100
+++ xen-4.7.0/tools/blktap2/control/tap-ctl-allocate.c 2016-09-02 10:07:55.964084808 +0100
@@ -36,6 +36,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
#include <linux/major.h>
#include "tap-ctl.h"
--- xen-4.7.0/tools/libxl/libxl_internal.h.orig 2016-06-20 11:38:15.000000000 +0100
+++ xen-4.7.0/tools/libxl/libxl_internal.h 2016-09-02 17:35:24.853783711 +0100
@@ -47,6 +47,7 @@
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
#include <xenevtchn.h>
#include <xenstore.h>

View file

@ -1,208 +1,77 @@
#
# Automatically generated file; DO NOT EDIT.
# Xen/x86 4.20 Configuration
# Xen/x86 4.9.1 Configuration
#
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=150001
CONFIG_CLANG_VERSION=0
CONFIG_LD_IS_GNU=y
CONFIG_CC_HAS_VISIBILITY_ATTRIBUTE=y
CONFIG_CC_SPLIT_SECTIONS=y
CONFIG_FUNCTION_ALIGNMENT_16B=y
CONFIG_FUNCTION_ALIGNMENT=16
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_CC_HAS_INDIRECT_THUNK=y
CONFIG_HAS_AS_CET_SS=y
CONFIG_HAS_CC_CET_IBT=y
#
# Architecture Features
#
CONFIG_AMD=y
CONFIG_INTEL=y
CONFIG_64BIT=y
CONFIG_NR_CPUS=256
CONFIG_NR_NUMA_NODES=64
CONFIG_PV=y
CONFIG_PV32=y
CONFIG_PV_LINEAR_PT=y
CONFIG_HVM=y
CONFIG_AMD_SVM=y
CONFIG_INTEL_VMX=y
CONFIG_XEN_SHSTK=y
CONFIG_XEN_IBT=y
CONFIG_SHADOW_PAGING=y
# CONFIG_BIGMEM is not set
CONFIG_HVM_FEP=y
CONFIG_X86_PSR=y
CONFIG_XEN_ALIGN_DEFAULT=y
# CONFIG_XEN_ALIGN_2M is not set
# CONFIG_X2APIC_PHYSICAL is not set
CONFIG_X2APIC_MIXED=y
# CONFIG_XEN_GUEST is not set
# CONFIG_HYPERV_GUEST is not set
# CONFIG_REQUIRE_NX is not set
CONFIG_ALTP2M=y
# end of Architecture Features
# CONFIG_HVM_FEP is not set
CONFIG_TBOOT=y
#
# Common Features
#
CONFIG_COMPAT=y
CONFIG_CORE_PARKING=y
CONFIG_GRANT_TABLE=y
CONFIG_ALTERNATIVE_CALL=y
CONFIG_ARCH_MAP_DOMAIN_PAGE=y
CONFIG_GENERIC_BUG_FRAME=y
CONFIG_HAS_ALTERNATIVE=y
CONFIG_HAS_COMPAT=y
CONFIG_HAS_DIT=y
CONFIG_HAS_EX_TABLE=y
CONFIG_HAS_FAST_MULTIPLY=y
CONFIG_HAS_IOPORTS=y
CONFIG_HAS_MEM_ACCESS=y
CONFIG_HAS_MEM_PAGING=y
CONFIG_HAS_MEM_SHARING=y
CONFIG_HAS_PDX=y
CONFIG_HAS_KEXEC=y
CONFIG_HAS_PIRQ=y
CONFIG_HAS_SCHED_GRANULARITY=y
CONFIG_HAS_UBSAN=y
CONFIG_HAS_VMAP=y
CONFIG_MEM_ACCESS_ALWAYS_ON=y
CONFIG_MEM_ACCESS=y
CONFIG_NEEDS_LIBELF=y
CONFIG_NUMA=y
#
# Speculative hardening
#
CONFIG_INDIRECT_THUNK=y
CONFIG_RETURN_THUNK=y
CONFIG_SPECULATIVE_HARDEN_ARRAY=y
CONFIG_SPECULATIVE_HARDEN_BRANCH=y
CONFIG_SPECULATIVE_HARDEN_GUEST_ACCESS=y
CONFIG_SPECULATIVE_HARDEN_LOCK=y
# end of Speculative hardening
# CONFIG_DIT_DEFAULT is not set
CONFIG_HYPFS=y
CONFIG_HYPFS_CONFIG=y
CONFIG_IOREQ_SERVER=y
CONFIG_HAS_GDBSX=y
CONFIG_HAS_IOPORTS=y
CONFIG_KEXEC=y
CONFIG_TMEM=y
CONFIG_XENOPROF=y
# CONFIG_XSM is not set
CONFIG_SCHED_CREDIT=y
CONFIG_SCHED_CREDIT2=y
CONFIG_SCHED_RTDS=y
CONFIG_SCHED_ARINC653=y
CONFIG_SCHED_NULL=y
CONFIG_SCHED_DEFAULT="credit2"
# CONFIG_BOOT_TIME_CPUPOOLS is not set
CONFIG_SCHED_DEFAULT="credit"
CONFIG_CRYPTO=y
CONFIG_LIVEPATCH=y
CONFIG_FAST_SYMBOL_LOOKUP=y
CONFIG_ENFORCE_UNIQUE_SYMBOLS=y
CONFIG_CMDLINE=""
CONFIG_DOM0_MEM=""
CONFIG_DTB_FILE=""
CONFIG_TRACEBUFFER=y
# end of Common Features
#
# Device Drivers
#
CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_ACPI_NUMA=y
CONFIG_NUMA=y
CONFIG_HAS_NS16550=y
CONFIG_HAS_EHCI=y
CONFIG_SERIAL_TX_BUFSIZE=32768
# CONFIG_XHCI is not set
CONFIG_HAS_CPUFREQ=y
CONFIG_HAS_PASSTHROUGH=y
CONFIG_AMD_IOMMU=y
CONFIG_INTEL_IOMMU=y
# CONFIG_IOMMU_QUARANTINE_NONE is not set
CONFIG_IOMMU_QUARANTINE_BASIC=y
# CONFIG_IOMMU_QUARANTINE_SCRATCH_PAGE is not set
CONFIG_HAS_PCI=y
CONFIG_HAS_PCI_MSI=y
CONFIG_VIDEO=y
CONFIG_VGA=y
CONFIG_HAS_VPCI=y
# end of Device Drivers
# CONFIG_EXPERT is not set
# CONFIG_UNSUPPORTED is not set
CONFIG_ARCH_SUPPORTS_INT128=y
CONFIG_ARCH_VCPU_IOREQ_COMPLETION=y
CONFIG_DEFCONFIG_LIST="$ARCH_DEFCONFIG"
#
# Debugging Options
#
# CONFIG_DEBUG is not set
CONFIG_GDBSX=y
CONFIG_FRAME_POINTER=y
CONFIG_SELF_TESTS=y
# CONFIG_DEBUG_LOCK_PROFILE is not set
CONFIG_DEBUG_LOCKS=y
# CONFIG_PERF_COUNTERS is not set
CONFIG_VERBOSE_DEBUG=y
CONFIG_SCRUB_DEBUG=y
# CONFIG_UBSAN is not set
# CONFIG_DEBUG_TRACE is not set
CONFIG_XMEM_POOL_POISON=y
CONFIG_DEBUG_INFO=y
# end of Debugging Options
# ARM64 settings
CONFIG_MMU=y
CONFIG_ARM_64=y
CONFIG_ARM=y
CONFIG_ARM_EFI=y
CONFIG_GICV2=y
CONFIG_GICV3=y
CONFIG_VGICV2=y
# CONFIG_NEW_VGIC is not set
CONFIG_SBSA_VUART_CONSOLE=y
CONFIG_HWDOM_VUART=y
CONFIG_ARM_SSBD=y
CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_STATIC_EVTCHN=y
CONFIG_PARTIAL_EMULATION=y
#
# ARM errata workaround via the alternative framework
#
CONFIG_ARM64_ERRATUM_827319=y
CONFIG_ARM64_ERRATUM_824069=y
CONFIG_ARM64_ERRATUM_819472=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_834220=y
CONFIG_ARM_ERRATUM_858921=y
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y
CONFIG_ARM64_ERRATUM_1286807=y
CONFIG_ARM64_ERRATUM_1508412=y
# end of ARM errata workaround via the alternative framework
CONFIG_ARM64_HARDEN_BRANCH_PREDICTOR=y
CONFIG_ALL_PLAT=y
# CONFIG_QEMU is not set
# CONFIG_RCAR3 is not set
# CONFIG_MPSOC is not set
# CONFIG_NO_PLAT is not set
CONFIG_ALL64_PLAT=y
CONFIG_MPSOC_PLATFORM=y
#
# Common Features
#
CONFIG_HAS_DEVICE_TREE=y
CONFIG_HAS_CADENCE_UART=y
CONFIG_HAS_LINFLEX=y
CONFIG_HAS_IMX_LPUART=y
CONFIG_HAS_MVEBU=y
CONFIG_HAS_MESON=y
CONFIG_HAS_PL011=y
CONFIG_HAS_OMAP=y
CONFIG_HAS_SCIF=y
CONFIG_ARM_SMMU=y
# CONFIG_IPMMU_VMSA is not set

View file

@ -1,27 +0,0 @@
--- xen-4.21.0/tools/libs/light/libxl_nocpuid.c.orig 2025-11-18 18:02:13.000000000 +0000
+++ xen-4.21.0/tools/libs/light/libxl_nocpuid.c 2025-11-20 09:03:56.517804514 +0000
@@ -40,11 +40,24 @@
return 0;
}
+#ifdef HAVE_LIBJSONC
+#ifndef _hidden
+#define _hidden
+#endif
+_hidden int libxl_cpuid_policy_list_gen_jso(json_object **jso_r,
+ libxl_cpuid_policy_list *pcpuid)
+{
+ return 0;
+}
+#endif
+
+#if defined(HAVE_LIBYAJL)
yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
libxl_cpuid_policy_list *pcpuid)
{
return 0;
}
+#endif
int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
const libxl__json_object *o,

View file

@ -1,22 +0,0 @@
--- xen-4.17.1/tools/python/Makefile.orig 2023-04-27 13:53:19.000000000 +0100
+++ xen-4.17.1/tools/python/Makefile 2023-06-22 22:21:25.287486906 +0100
@@ -4,7 +4,7 @@
.PHONY: all
all: build
-PY_CFLAGS = $(CFLAGS) $(PY_NOOPT_CFLAGS)
+PY_CFLAGS = $(CFLAGS) $(PY_NOOPT_CFLAGS) -Wno-error=declaration-after-statement
PY_LDFLAGS = $(SHLIB_LDFLAGS) $(APPEND_LDFLAGS)
INSTALL_LOG = build/installed_files.txt
--- xen-4.17.1/tools/pygrub/Makefile.orig 2023-04-27 13:53:19.000000000 +0100
+++ xen-4.17.1/tools/pygrub/Makefile 2023-06-22 22:52:52.803047401 +0100
@@ -2,7 +2,7 @@
XEN_ROOT = $(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
-PY_CFLAGS = $(CFLAGS) $(PY_NOOPT_CFLAGS)
+PY_CFLAGS = $(CFLAGS) $(PY_NOOPT_CFLAGS) -Wno-error=declaration-after-statement
PY_LDFLAGS = $(SHLIB_LDFLAGS) $(APPEND_LDFLAGS)
INSTALL_LOG = build/installed_files.txt

1760
xen.spec

File diff suppressed because it is too large Load diff

33
xen.use.fedora.ipxe.patch Normal file
View file

@ -0,0 +1,33 @@
--- xen-4.2.0/tools/firmware/hvmloader/Makefile.orig 2012-05-27 21:57:04.481812859 +0100
+++ xen-4.2.0/tools/firmware/hvmloader/Makefile 2012-06-02 18:52:44.935034128 +0100
@@ -48,7 +48,7 @@
else
CIRRUSVGA_ROM := ../vgabios/VGABIOS-lgpl-latest.cirrus.bin
endif
-ETHERBOOT_ROMS := $(addprefix ../etherboot/ipxe/src/bin/, $(addsuffix .rom, $(ETHERBOOT_NICS)))
+ETHERBOOT_ROMS := $(addprefix /usr/share/ipxe/, $(addsuffix .rom, $(ETHERBOOT_NICS)))
endif
ROMS :=
--- xen-4.2.0/Config.mk.orig 2012-05-27 21:57:04.479812884 +0100
+++ xen-4.2.0/Config.mk 2012-06-02 18:55:14.087169469 +0100
@@ -206,7 +206,7 @@
# Wed Jun 22 14:53:24 2016 +0800
# fw/msr_feature_control: add support to set MSR_IA32_FEATURE_CONTROL
-ETHERBOOT_NICS ?= rtl8139 8086100e
+ETHERBOOT_NICS ?= 10ec8139 8086100e
QEMU_TRADITIONAL_REVISION ?= xen-4.9.3
--- xen-4.2.0/tools/firmware/Makefile.orig 2012-05-27 21:57:04.480812871 +0100
+++ xen-4.2.0/tools/firmware/Makefile 2012-06-02 19:03:52.254691484 +0100
@@ -10,7 +10,7 @@
SUBDIRS-$(CONFIG_SEABIOS) += seabios-dir
SUBDIRS-$(CONFIG_ROMBIOS) += rombios
SUBDIRS-$(CONFIG_ROMBIOS) += vgabios
-SUBDIRS-$(CONFIG_ROMBIOS) += etherboot
+#SUBDIRS-$(CONFIG_ROMBIOS) += etherboot
SUBDIRS-y += hvmloader
LD32BIT-$(CONFIG_FreeBSD) := LD32BIT_FLAG=-melf_i386_fbsd

View file

@ -0,0 +1,24 @@
--- xen-4.6.3/tools/xenstore/xs.c.orig 2016-06-20 13:08:22.000000000 +0100
+++ xen-4.6.3/tools/xenstore/xs.c 2016-07-10 21:05:57.082217329 +0100
@@ -733,6 +733,7 @@
if (!h->read_thr_exists) {
sigset_t set, old_set;
pthread_attr_t attr;
+ int ptret;
if (pthread_attr_init(&attr) != 0) {
mutex_unlock(&h->request_mutex);
@@ -747,7 +748,12 @@
sigfillset(&set);
pthread_sigmask(SIG_SETMASK, &set, &old_set);
- if (pthread_create(&h->read_thr, &attr, read_thread, h) != 0) {
+ ptret = pthread_create(&h->read_thr, &attr, read_thread, h);
+ if ( (ptret == EINVAL) && (pthread_attr_setstacksize(&attr, READ_THREAD_STACKSIZE + (8*1024)) == 0) ) {
+ /* have a second try with the bigger stacksize */
+ ptret = pthread_create(&h->read_thr, &attr, read_thread, h);
+ }
+ if (ptret != 0) {
pthread_sigmask(SIG_SETMASK, &old_set, NULL);
pthread_attr_destroy(&attr);
mutex_unlock(&h->request_mutex);

326
xsa278-4.11.patch Normal file
View file

@ -0,0 +1,326 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/vvmx: Disallow the use of VT-x instructions when nested virt is disabled
c/s ac6a4500b "vvmx: set vmxon_region_pa of vcpu out of VMX operation to an
invalid address" was a real bugfix as described, but has a very subtle bug
which results in all VT-x instructions being usable by a guest.
The toolstack constructs a guest by issuing:
XEN_DOMCTL_createdomain
XEN_DOMCTL_max_vcpus
and optionally later, HVMOP_set_param to enable nested virt.
As a result, the call to nvmx_vcpu_initialise() in hvm_vcpu_initialise()
(which is what makes the above patch look correct during review) is actually
dead code. In practice, nvmx_vcpu_initialise() first gets called when nested
virt is enabled, which is typically never.
As a result, the zeroed memory of struct vcpu causes nvmx_vcpu_in_vmx() to
return true before nested virt is enabled for the guest.
Fixing the order of initialisation is a work in progress for other reasons,
but not viable for security backports.
A compounding factor is that the vmexit handlers for all instructions, other
than VMXON, pass 0 into vmx_inst_check_privilege()'s vmxop_check parameter,
which skips the CR4.VMXE check. (This is one of many reasons why nested virt
isn't a supported feature yet.)
However, the overall result is that when nested virt is not enabled by the
toolstack (i.e. the default configuration for all production guests), the VT-x
instructions (other than VMXON) are actually usable, and Xen very quickly
falls over the fact that the nvmx structure is uninitialised.
In order to fail safe in the supported case, re-implement all the VT-x
instruction handling using a single function with a common prologue, covering
all the checks which should cause #UD or #GP faults. This deliberately
doesn't use any state from the nvmx structure, in case there are other lurking
issues.
This is XSA-278
Reported-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Sergey Dyasli <sergey.dyasli@citrix.com>
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index a6415f0..a4d2829 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -3982,57 +3982,17 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
break;
case EXIT_REASON_VMXOFF:
- if ( nvmx_handle_vmxoff(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMXON:
- if ( nvmx_handle_vmxon(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMCLEAR:
- if ( nvmx_handle_vmclear(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMPTRLD:
- if ( nvmx_handle_vmptrld(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMPTRST:
- if ( nvmx_handle_vmptrst(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMREAD:
- if ( nvmx_handle_vmread(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMWRITE:
- if ( nvmx_handle_vmwrite(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMLAUNCH:
- if ( nvmx_handle_vmlaunch(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_VMRESUME:
- if ( nvmx_handle_vmresume(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_INVEPT:
- if ( nvmx_handle_invept(regs) == X86EMUL_OKAY )
- update_guest_eip();
- break;
-
case EXIT_REASON_INVVPID:
- if ( nvmx_handle_invvpid(regs) == X86EMUL_OKAY )
+ if ( nvmx_handle_vmx_insn(regs, exit_reason) == X86EMUL_OKAY )
update_guest_eip();
break;
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index e97db33..88cb58c 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1470,7 +1470,7 @@ void nvmx_switch_guest(void)
* VMX instructions handling
*/
-int nvmx_handle_vmxon(struct cpu_user_regs *regs)
+static int nvmx_handle_vmxon(struct cpu_user_regs *regs)
{
struct vcpu *v=current;
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
@@ -1522,7 +1522,7 @@ int nvmx_handle_vmxon(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_vmxoff(struct cpu_user_regs *regs)
+static int nvmx_handle_vmxoff(struct cpu_user_regs *regs)
{
struct vcpu *v=current;
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
@@ -1611,7 +1611,7 @@ static int nvmx_vmresume(struct vcpu *v, struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_vmresume(struct cpu_user_regs *regs)
+static int nvmx_handle_vmresume(struct cpu_user_regs *regs)
{
bool_t launched;
struct vcpu *v = current;
@@ -1645,7 +1645,7 @@ int nvmx_handle_vmresume(struct cpu_user_regs *regs)
return nvmx_vmresume(v,regs);
}
-int nvmx_handle_vmlaunch(struct cpu_user_regs *regs)
+static int nvmx_handle_vmlaunch(struct cpu_user_regs *regs)
{
bool_t launched;
struct vcpu *v = current;
@@ -1688,7 +1688,7 @@ int nvmx_handle_vmlaunch(struct cpu_user_regs *regs)
return rc;
}
-int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
+static int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1759,7 +1759,7 @@ int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
+static int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1784,7 +1784,7 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_vmclear(struct cpu_user_regs *regs)
+static int nvmx_handle_vmclear(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1836,7 +1836,7 @@ int nvmx_handle_vmclear(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_vmread(struct cpu_user_regs *regs)
+static int nvmx_handle_vmread(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1878,7 +1878,7 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
+static int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1926,7 +1926,7 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_invept(struct cpu_user_regs *regs)
+static int nvmx_handle_invept(struct cpu_user_regs *regs)
{
struct vmx_inst_decoded decode;
unsigned long eptp;
@@ -1954,7 +1954,7 @@ int nvmx_handle_invept(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
-int nvmx_handle_invvpid(struct cpu_user_regs *regs)
+static int nvmx_handle_invvpid(struct cpu_user_regs *regs)
{
struct vmx_inst_decoded decode;
unsigned long vpid;
@@ -1980,6 +1980,81 @@ int nvmx_handle_invvpid(struct cpu_user_regs *regs)
return X86EMUL_OKAY;
}
+int nvmx_handle_vmx_insn(struct cpu_user_regs *regs, unsigned int exit_reason)
+{
+ struct vcpu *curr = current;
+ int ret;
+
+ if ( !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_VMXE) ||
+ !nestedhvm_enabled(curr->domain) ||
+ (vmx_guest_x86_mode(curr) < (hvm_long_mode_active(curr) ? 8 : 2)) )
+ {
+ hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC);
+ return X86EMUL_EXCEPTION;
+ }
+
+ if ( vmx_get_cpl() > 0 )
+ {
+ hvm_inject_hw_exception(TRAP_gp_fault, 0);
+ return X86EMUL_EXCEPTION;
+ }
+
+ switch ( exit_reason )
+ {
+ case EXIT_REASON_VMXOFF:
+ ret = nvmx_handle_vmxoff(regs);
+ break;
+
+ case EXIT_REASON_VMXON:
+ ret = nvmx_handle_vmxon(regs);
+ break;
+
+ case EXIT_REASON_VMCLEAR:
+ ret = nvmx_handle_vmclear(regs);
+ break;
+
+ case EXIT_REASON_VMPTRLD:
+ ret = nvmx_handle_vmptrld(regs);
+ break;
+
+ case EXIT_REASON_VMPTRST:
+ ret = nvmx_handle_vmptrst(regs);
+ break;
+
+ case EXIT_REASON_VMREAD:
+ ret = nvmx_handle_vmread(regs);
+ break;
+
+ case EXIT_REASON_VMWRITE:
+ ret = nvmx_handle_vmwrite(regs);
+ break;
+
+ case EXIT_REASON_VMLAUNCH:
+ ret = nvmx_handle_vmlaunch(regs);
+ break;
+
+ case EXIT_REASON_VMRESUME:
+ ret = nvmx_handle_vmresume(regs);
+ break;
+
+ case EXIT_REASON_INVEPT:
+ ret = nvmx_handle_invept(regs);
+ break;
+
+ case EXIT_REASON_INVVPID:
+ ret = nvmx_handle_invvpid(regs);
+ break;
+
+ default:
+ ASSERT_UNREACHABLE();
+ domain_crash(curr->domain);
+ ret = X86EMUL_UNHANDLEABLE;
+ break;
+ }
+
+ return ret;
+}
+
#define __emul_value(enable1, default1) \
((enable1 | default1) << 32 | (default1))
diff --git a/xen/include/asm-x86/hvm/vmx/vvmx.h b/xen/include/asm-x86/hvm/vmx/vvmx.h
index 9ea35eb..fc4a8d1 100644
--- a/xen/include/asm-x86/hvm/vmx/vvmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vvmx.h
@@ -94,9 +94,6 @@ void nvmx_domain_relinquish_resources(struct domain *d);
bool_t nvmx_ept_enabled(struct vcpu *v);
-int nvmx_handle_vmxon(struct cpu_user_regs *regs);
-int nvmx_handle_vmxoff(struct cpu_user_regs *regs);
-
#define EPT_TRANSLATE_SUCCEED 0
#define EPT_TRANSLATE_VIOLATION 1
#define EPT_TRANSLATE_MISCONFIG 2
@@ -191,15 +188,7 @@ enum vmx_insn_errno set_vvmcs_real_safe(const struct vcpu *, u32 encoding,
uint64_t get_shadow_eptp(struct vcpu *v);
void nvmx_destroy_vmcs(struct vcpu *v);
-int nvmx_handle_vmptrld(struct cpu_user_regs *regs);
-int nvmx_handle_vmptrst(struct cpu_user_regs *regs);
-int nvmx_handle_vmclear(struct cpu_user_regs *regs);
-int nvmx_handle_vmread(struct cpu_user_regs *regs);
-int nvmx_handle_vmwrite(struct cpu_user_regs *regs);
-int nvmx_handle_vmresume(struct cpu_user_regs *regs);
-int nvmx_handle_vmlaunch(struct cpu_user_regs *regs);
-int nvmx_handle_invept(struct cpu_user_regs *regs);
-int nvmx_handle_invvpid(struct cpu_user_regs *regs);
+int nvmx_handle_vmx_insn(struct cpu_user_regs *regs, unsigned int exit_reason);
int nvmx_msr_read_intercept(unsigned int msr,
u64 *msr_content);

42
xsa282-2.patch Normal file
View file

@ -0,0 +1,42 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: work around HLE host lockup erratum
XACQUIRE prefixed accesses to the 4Mb range of memory starting at 1Gb
are liable to lock up the processor. Disallow use of this memory range.
Unfortunately the available Core Gen7 and Gen8 spec updates are pretty
old, so I can only guess that they're similarly affected when Core Gen6
is and the Xeon counterparts are, too.
This is part of XSA-282.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
v2: Don't apply the workaround when running ourselves virtualized.
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -5853,6 +5853,22 @@ const struct platform_bad_page *__init g
{ .mfn = 0x20138000 >> PAGE_SHIFT },
{ .mfn = 0x40004000 >> PAGE_SHIFT },
};
+ static const struct platform_bad_page __initconst hle_bad_page = {
+ .mfn = 0x40000000 >> PAGE_SHIFT, .order = 10
+ };
+
+ switch ( cpuid_eax(1) & 0x000f3ff0 )
+ {
+ case 0x000406e0: /* erratum SKL167 */
+ case 0x00050650: /* erratum SKZ63 */
+ case 0x000506e0: /* errata SKL167 / SKW159 */
+ case 0x000806e0: /* erratum KBL??? */
+ case 0x000906e0: /* errata KBL??? / KBW114 / CFW103 */
+ *array_size = (cpuid_eax(0) >= 7 &&
+ !(cpuid_ecx(1) & cpufeat_mask(X86_FEATURE_HYPERVISOR)) &&
+ (cpuid_count_ebx(7, 0) & cpufeat_mask(X86_FEATURE_HLE)));
+ return &hle_bad_page;
+ }
*array_size = ARRAY_SIZE(snb_bad_pages);
igd_id = pci_conf_read32(0, 0, 2, 0, 0);

87
xsa282-4.9-1.patch Normal file
View file

@ -0,0 +1,87 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: extend get_platform_badpages() interface
Use a structure so along with an address (now frame number) an order can
also be specified.
This is part of XSA-282.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -7111,23 +7111,23 @@ void arch_dump_shared_mem_info(void)
mem_sharing_get_nr_saved_mfns());
}
-const unsigned long *__init get_platform_badpages(unsigned int *array_size)
+const struct platform_bad_page *__init get_platform_badpages(unsigned int *array_size)
{
u32 igd_id;
- static unsigned long __initdata bad_pages[] = {
- 0x20050000,
- 0x20110000,
- 0x20130000,
- 0x20138000,
- 0x40004000,
+ static const struct platform_bad_page __initconst snb_bad_pages[] = {
+ { .mfn = 0x20050000 >> PAGE_SHIFT },
+ { .mfn = 0x20110000 >> PAGE_SHIFT },
+ { .mfn = 0x20130000 >> PAGE_SHIFT },
+ { .mfn = 0x20138000 >> PAGE_SHIFT },
+ { .mfn = 0x40004000 >> PAGE_SHIFT },
};
- *array_size = ARRAY_SIZE(bad_pages);
+ *array_size = ARRAY_SIZE(snb_bad_pages);
igd_id = pci_conf_read32(0, 0, 2, 0, 0);
- if ( !IS_SNB_GFX(igd_id) )
- return NULL;
+ if ( IS_SNB_GFX(igd_id) )
+ return snb_bad_pages;
- return bad_pages;
+ return NULL;
}
void paging_invlpg(struct vcpu *v, unsigned long va)
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -270,7 +270,7 @@ void __init init_boot_pages(paddr_t ps,
unsigned long bad_spfn, bad_epfn;
const char *p;
#ifdef CONFIG_X86
- const unsigned long *badpage = NULL;
+ const struct platform_bad_page *badpage;
unsigned int i, array_size;
#endif
@@ -295,8 +295,8 @@ void __init init_boot_pages(paddr_t ps,
{
for ( i = 0; i < array_size; i++ )
{
- bootmem_region_zap(*badpage >> PAGE_SHIFT,
- (*badpage >> PAGE_SHIFT) + 1);
+ bootmem_region_zap(badpage->mfn,
+ badpage->mfn + (1U << badpage->order));
badpage++;
}
}
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -350,7 +350,13 @@ bool is_iomem_page(mfn_t mfn);
void clear_superpage_mark(struct page_info *page);
-const unsigned long *get_platform_badpages(unsigned int *array_size);
+struct platform_bad_page {
+ unsigned long mfn;
+ unsigned int order;
+};
+
+const struct platform_bad_page *get_platform_badpages(unsigned int *array_size);
+
/* Per page locks:
* page_lock() is used for two purposes: pte serialization, and memory sharing.
*

View file

@ -1,30 +0,0 @@
From: Andrii Sultanov <andriy.sultanov@vates.tech>
Subject: tools/oxenstored: Reset quota when resetting permissions
The quota object contains both limits and the current node usage counts.
When a domain is torn down, the node data itself is cleaned up but the node
usage counts are not. A later domain reusing the same domid can create fewer
nodes before being deemed to be over quota.
Reset the count when the node permissions are cleaned up.
This is XSA-483 / CVE-2026-23556.
Signed-off-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
diff --git a/tools/ocaml/xenstored/store.ml b/tools/ocaml/xenstored/store.ml
index 9b8dd2812df0..aa9204ead3ec 100644
--- a/tools/ocaml/xenstored/store.ml
+++ b/tools/ocaml/xenstored/store.ml
@@ -465,7 +465,8 @@ let reset_permissions store domid =
if perms <> node.perms then
Logging.debug "store|node" "Changed permissions for node %s" (Node.get_name node);
Some { node with Node.perms }
- ) store.root
+ ) store.root;
+ store.quota <- Quota.del store.quota domid
type ops = {
store: t;

View file

@ -1,89 +0,0 @@
From 3d0d19ad17f29c64dde4a7baf392da4fd58f3654 Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
Date: Mon, 16 Mar 2026 15:06:11 +0100
Subject: [PATCH] tools/xenstored: make conn_delete_all_transactions()
idempotent
conn_delete_all_transactions() should be callable in any context,
resetting ALL transaction related data.
This includes number of active transactions and the transaction
pointer in struct connection.
So reset conn->trans to NULL in conn_delete_all_transactions() and
do the cleanup for each transaction in destroy_transaction().
This avoids triggering the assert() in conn_delete_all_transactions()
in case e.g. ignore_connection() was called while an operation inside
a transaction was performed, or XS_RESET_WATCHES was called in a
transaction.
This is XSA-484 / CVE-2026-23557.
Reported-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Fixes: 1f9d04fb021c ("xenstored: allow guest to shutdown all its watches/transactions")
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/transaction.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/tools/xenstored/transaction.c b/tools/xenstored/transaction.c
index 167cd597fd..0825c48859 100644
--- a/tools/xenstored/transaction.c
+++ b/tools/xenstored/transaction.c
@@ -432,17 +432,23 @@ static int finalize_transaction(struct connection *conn,
static int destroy_transaction(void *_transaction)
{
struct transaction *trans = _transaction;
+ struct connection *conn = trans->conn;
struct accessed_node *i;
wrl_ntransactions--;
trace_destroy(trans, "transaction");
while ((i = list_top(&trans->accessed, struct accessed_node, list))) {
if (i->ta_node)
- db_delete(trans->conn, i->trans_name, NULL);
+ db_delete(conn, i->trans_name, NULL);
list_del(&i->list);
talloc_free(i);
}
+ list_del(&trans->list);
+ domain_transaction_dec(conn);
+ if (list_empty(&conn->transaction_list))
+ conn->ta_start_time = 0;
+
return 0;
}
@@ -523,10 +529,6 @@ int do_transaction_end(const void *ctx, struct connection *conn,
return ENOENT;
conn->transaction = NULL;
- list_del(&trans->list);
- domain_transaction_dec(conn);
- if (list_empty(&conn->transaction_list))
- conn->ta_start_time = 0;
chk_quota = trans->node_created && domain_is_unprivileged(conn);
@@ -572,14 +574,10 @@ void conn_delete_all_transactions(struct connection *conn)
struct transaction *trans;
while ((trans = list_top(&conn->transaction_list,
- struct transaction, list))) {
- list_del(&trans->list);
+ struct transaction, list)))
talloc_free(trans);
- }
-
- assert(conn->transaction == NULL);
- conn->ta_start_time = 0;
+ conn->transaction = NULL;
}
int check_transactions(struct hashtable *hash)
--
2.53.0

View file

@ -1,181 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: gnttab: split gnttab_map_frame()
If a domain tries to map status frames in parallel to switching grant
table version from 2 to 1, the mapping operation may put in place P2M
entries referencing MFNs which gnttab_unpopulate_status_frames() is in the
process of freeing.
Ideally we would refcount pages when entered into P2M tables, but that's a
significant change. Extend the grant-table-locked region instead in
xenmem_add_to_physmap_one() (being the sole caller of gnttab_map_frame()),
such that a race with gnttab_unpopulate_status_frames() is no longer
possible.
This is XSA-486 / CVE-2026-23558.
Fixes: 5ce8fafa947c ("Dynamic grant-table sizing")
Fixes: a98dc13703e0 ("Introduce a grant_entry_v2 structure")
Reported-by: Rafal Wojtczuk <rafal.wojtczuk@7bulls.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -174,12 +174,10 @@ int xenmem_add_to_physmap_one(
switch ( space )
{
case XENMAPSPACE_grant_table:
- rc = gnttab_map_frame(d, idx, gfn, &mfn);
+ rc = gnttab_map_frame_begin(d, idx, gfn, &mfn);
if ( rc )
return rc;
- /* Need to take care of the reference obtained in gnttab_map_frame(). */
- page = mfn_to_page(mfn);
t = p2m_ram_rw;
break;
@@ -281,10 +279,23 @@ int xenmem_add_to_physmap_one(
* to drop the reference we took earlier. In all other cases we need to
* drop any reference we took earlier (perhaps indirectly).
*/
- if ( space == XENMAPSPACE_gmfn_foreign ? rc : page != NULL )
+ switch ( space )
{
+ default:
+ if ( page )
+ put_page(page);
+ break;
+
+ case XENMAPSPACE_grant_table:
+ gnttab_map_frame_end(d, mfn);
+ break;
+
+ case XENMAPSPACE_gmfn_foreign:
+ if ( !rc )
+ break;
ASSERT(page != NULL);
put_page(page);
+ break;
}
return rc;
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -2009,11 +2009,9 @@ int xenmem_add_to_physmap_one(
break;
case XENMAPSPACE_grant_table:
- rc = gnttab_map_frame(d, idx, gfn, &mfn);
+ rc = gnttab_map_frame_begin(d, idx, gfn, &mfn);
if ( rc )
return rc;
- /* Need to take care of the reference obtained in gnttab_map_frame(). */
- page = mfn_to_page(mfn);
break;
case XENMAPSPACE_gmfn:
@@ -2095,19 +2093,28 @@ int xenmem_add_to_physmap_one(
put_gfn(d, gfn_x(gfn));
put_both:
- /*
- * In the XENMAPSPACE_gmfn case, we took a ref of the gfn at the top.
- * We also may need to transfer ownership of the page reference to our
- * caller.
- */
- if ( space == XENMAPSPACE_gmfn )
+ switch ( space )
{
+ case XENMAPSPACE_gmfn:
+ /*
+ * We took a ref of the gfn at the top. We also may need to transfer
+ * ownership of the page reference to our caller.
+ */
put_gfn(d, gmfn);
if ( !rc && extra.ppage )
{
*extra.ppage = page;
page = NULL;
}
+ break;
+
+ case XENMAPSPACE_grant_table:
+ /*
+ * We (gnttab_map_frame_begin()) acquired a lock and took a ref of the
+ * page underlying the MFN at the top.
+ */
+ gnttab_map_frame_end(d, mfn);
+ break;
}
if ( page )
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -4250,7 +4250,8 @@ int gnttab_acquire_resource(
return rc;
}
-int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn)
+int gnttab_map_frame_begin(
+ struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn)
{
int rc = 0;
struct grant_table *gt = d->grant_table;
@@ -4288,11 +4289,19 @@ int gnttab_map_frame(struct domain *d, u
put_page(pg);
}
- grant_write_unlock(gt);
+ if ( rc )
+ grant_write_unlock(d->grant_table);
return rc;
}
+void gnttab_map_frame_end(struct domain *d, mfn_t mfn)
+{
+ put_page(mfn_to_page(mfn));
+
+ grant_write_unlock(d->grant_table);
+}
+
static void gnttab_usage_print(struct domain *rd)
{
int first = 1;
--- a/xen/include/xen/grant_table.h
+++ b/xen/include/xen/grant_table.h
@@ -60,8 +60,13 @@ int gnttab_release_mappings(struct domai
int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref,
gfn_t *gfn, uint16_t *status);
-int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
- mfn_t *mfn);
+/*
+ * These need to be used as a pair, as the first (in the success case) returns
+ * with a lock and page reference held which the second needs to drop.
+ */
+int gnttab_map_frame_begin(struct domain *d, unsigned long idx, gfn_t gfn,
+ mfn_t *mfn);
+void gnttab_map_frame_end(struct domain *d, mfn_t mfn);
unsigned int gnttab_resource_max_frames(const struct domain *d, unsigned int id);
@@ -100,12 +105,14 @@ static inline int mem_sharing_gref_to_gf
return -EINVAL;
}
-static inline int gnttab_map_frame(struct domain *d, unsigned long idx,
- gfn_t gfn, mfn_t *mfn)
+static inline int gnttab_map_frame_begin(struct domain *d, unsigned long idx,
+ gfn_t gfn, mfn_t *mfn)
{
return -EINVAL;
}
+static inline void gnttab_map_frame_end(struct domain *d, mfn_t mfn) {}
+
static inline unsigned int gnttab_resource_max_frames(
const struct domain *d, unsigned int id)
{

View file

@ -1,43 +0,0 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/amd: Mitigate AMD-SN-7052
This is XSA-490 / CVE-2025-54518.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 1bb0766ebf13..b5bf2b732e8f 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -1116,11 +1116,25 @@ static void amd_check_bp_cfg(void)
{
uint64_t val, new = 0;
- /*
- * AMD Erratum #1485. Set bit 5, as instructed.
- */
- if (!cpu_has_hypervisor && boot_cpu_data.x86 == 0x19 && is_zen4_uarch())
- new |= (1 << 5);
+ if (!cpu_has_hypervisor) {
+ /*
+ * AMD Erratum #1485. If SMT is enabled and STIBP disabled,
+ * the CPU may fetch incorrect instruction bytes.
+ *
+ * Set bit 5, as instructed.
+ */
+ if (boot_cpu_data.x86 == 0x19 && is_zen4_uarch())
+ new |= (1 << 5);
+
+ /*
+ * AMD SB-7052. CPU OP Cache corruption, causing instructions
+ * to be executed at a higher privilege.
+ *
+ * Set bit 33, as instructed.
+ */
+ if (boot_cpu_data.x86 == 0x17 && is_zen2_uarch())
+ new |= (1UL << 33);
+ }
/*
* On hardware supporting SRSO_MSR_FIX, activate BP_SPEC_REDUCE by

View file

@ -1,211 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/HVM: add locking to I/O port translation list traversal
XEN_DOMCTL_ioport_mapping is usable by DM stubdoms, and hence we can't
assume the list to be left unaltered while the guest (really: the
hypervisor on behalf of the guest) is accessing it.
This is XSA-491 / CVE-2026-42487.
Fixes: 192c4dabc344 ("domctl and p2m changes for PCI passthru")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -663,6 +663,7 @@ long arch_do_domctl(
"ioport_map:add: dom%d gport=%x mport=%x nr=%x\n",
d->domain_id, fgp, fmp, np);
+ write_lock(&hvm->g2m_ioport_lock);
list_for_each_entry(g2m_ioport, &hvm->g2m_ioport_list, list)
if (g2m_ioport->mport == fmp )
{
@@ -684,11 +685,14 @@ long arch_do_domctl(
g2m_ioport->np = np;
list_add_tail(&g2m_ioport->list, &hvm->g2m_ioport_list);
}
+ write_unlock(&hvm->g2m_ioport_lock);
if ( !ret )
ret = ioports_permit_access(d, fmp, fmp + np - 1);
if ( ret && !found && g2m_ioport )
{
+ write_lock(&hvm->g2m_ioport_lock);
list_del(&g2m_ioport->list);
+ write_unlock(&hvm->g2m_ioport_lock);
xfree(g2m_ioport);
}
}
@@ -697,6 +701,8 @@ long arch_do_domctl(
printk(XENLOG_G_INFO
"ioport_map:remove: dom%d gport=%x mport=%x nr=%x\n",
d->domain_id, fgp, fmp, np);
+
+ write_lock(&hvm->g2m_ioport_lock);
list_for_each_entry(g2m_ioport, &hvm->g2m_ioport_list, list)
if ( g2m_ioport->mport == fmp )
{
@@ -704,6 +710,8 @@ long arch_do_domctl(
xfree(g2m_ioport);
break;
}
+ write_unlock(&hvm->g2m_ioport_lock);
+
ret = ioports_deny_access(d, fmp, fmp + np - 1);
if ( ret && is_hardware_domain(currd) )
printk(XENLOG_ERR
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -160,7 +160,6 @@ void hvmemul_cancel(struct vcpu *v)
hvio->mmio_insn_bytes = 0;
hvio->mmio_access = (struct npfec){};
hvio->mmio_retry = false;
- hvio->g2m_ioport = NULL;
hvmemul_cache_disable(v);
}
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -610,6 +610,7 @@ int hvm_domain_initialise(struct domain
spin_lock_init(&d->arch.hvm.irq_lock);
spin_lock_init(&d->arch.hvm.uc_lock);
spin_lock_init(&d->arch.hvm.write_map.lock);
+ rwlock_init(&d->arch.hvm.g2m_ioport_lock);
rwlock_init(&d->arch.hvm.mmcfg_lock);
INIT_LIST_HEAD(&d->arch.hvm.write_map.list);
INIT_LIST_HEAD(&d->arch.hvm.g2m_ioport_list);
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -143,36 +143,56 @@ bool handle_pio(uint16_t port, unsigned
return true;
}
-static bool cf_check g2m_portio_accept(
- const struct hvm_io_handler *handler, const ioreq_t *p)
+/* NB: Returns with the lock held in the success case. */
+static const struct g2m_ioport *g2m_portio_find_and_lock(struct hvm_domain *hvm,
+ uint64_t addr,
+ uint32_t size)
{
- struct vcpu *curr = current;
- const struct hvm_domain *hvm = &curr->domain->arch.hvm;
- struct hvm_vcpu_io *hvio = &curr->arch.hvm.hvm_io;
- struct g2m_ioport *g2m_ioport;
- unsigned int start, end;
+ const struct g2m_ioport *g2m_ioport;
+
+ read_lock(&hvm->g2m_ioport_lock);
list_for_each_entry( g2m_ioport, &hvm->g2m_ioport_list, list )
{
- start = g2m_ioport->gport;
- end = start + g2m_ioport->np;
- if ( (p->addr >= start) && (p->addr + p->size <= end) )
- {
- hvio->g2m_ioport = g2m_ioport;
- return 1;
- }
+ unsigned int start = g2m_ioport->gport;
+
+ if ( addr >= start && addr + size <= start + g2m_ioport->np )
+ return g2m_ioport;
}
- return 0;
+ read_unlock(&hvm->g2m_ioport_lock);
+
+ return NULL;
+}
+
+static bool cf_check g2m_portio_accept(
+ const struct hvm_io_handler *handler, const ioreq_t *p)
+{
+ struct hvm_domain *hvm = &current->domain->arch.hvm;
+ const struct g2m_ioport *g2m_ioport =
+ g2m_portio_find_and_lock(hvm, p->addr, p->size);
+
+ if ( !g2m_ioport )
+ return false;
+
+ read_unlock(&hvm->g2m_ioport_lock);
+
+ return true;
}
static int cf_check g2m_portio_read(
const struct hvm_io_handler *handler, uint64_t addr, uint32_t size,
uint64_t *data)
{
- struct hvm_vcpu_io *hvio = &current->arch.hvm.hvm_io;
- const struct g2m_ioport *g2m_ioport = hvio->g2m_ioport;
- unsigned int mport = (addr - g2m_ioport->gport) + g2m_ioport->mport;
+ struct hvm_domain *hvm = &current->domain->arch.hvm;
+ const struct g2m_ioport *g2m_ioport =
+ g2m_portio_find_and_lock(hvm, addr, size);
+ unsigned int mport;
+
+ if ( !g2m_ioport )
+ return X86EMUL_RETRY;
+
+ mport = addr - g2m_ioport->gport + g2m_ioport->mport;
switch ( size )
{
@@ -189,6 +209,8 @@ static int cf_check g2m_portio_read(
BUG();
}
+ read_unlock(&hvm->g2m_ioport_lock);
+
return X86EMUL_OKAY;
}
@@ -196,9 +218,15 @@ static int cf_check g2m_portio_write(
const struct hvm_io_handler *handler, uint64_t addr, uint32_t size,
uint64_t data)
{
- struct hvm_vcpu_io *hvio = &current->arch.hvm.hvm_io;
- const struct g2m_ioport *g2m_ioport = hvio->g2m_ioport;
- unsigned int mport = (addr - g2m_ioport->gport) + g2m_ioport->mport;
+ struct hvm_domain *hvm = &current->domain->arch.hvm;
+ const struct g2m_ioport *g2m_ioport =
+ g2m_portio_find_and_lock(hvm, addr, size);
+ unsigned int mport;
+
+ if ( !g2m_ioport )
+ return X86EMUL_RETRY;
+
+ mport = addr - g2m_ioport->gport + g2m_ioport->mport;
switch ( size )
{
@@ -215,6 +243,8 @@ static int cf_check g2m_portio_write(
BUG();
}
+ read_unlock(&hvm->g2m_ioport_lock);
+
return X86EMUL_OKAY;
}
--- a/xen/arch/x86/include/asm/hvm/domain.h
+++ b/xen/arch/x86/include/asm/hvm/domain.h
@@ -125,6 +125,7 @@ struct hvm_domain {
/* List of guest to machine IO ports mapping. */
struct list_head g2m_ioport_list;
+ rwlock_t g2m_ioport_lock;
/* List of MMCFG regions trapped by Xen. */
struct list_head mmcfg_regions;
--- a/xen/arch/x86/include/asm/hvm/vcpu.h
+++ b/xen/arch/x86/include/asm/hvm/vcpu.h
@@ -54,8 +54,6 @@ struct hvm_vcpu_io {
unsigned long msix_unmask_address;
unsigned long msix_snoop_address;
unsigned long msix_snoop_gpa;
-
- const struct g2m_ioport *g2m_ioport;
};
struct nestedvcpu {

View file

@ -1,264 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: sched: use sequence counter to enlighten vcpu_runstate_get()
Subsequently XEN_DOMCTL_getdomaininfo will want to invoke the function
without holding a lock, thus allowing parallel execution of potentially
many instances. As was learned from 228ab9992ffb ("domctl: improve
locking during domain destruction"), reverted by d0887cc6b16e, such
parallelism can result in severe lock contention on any (previously)
inner lock. To avoid taking that risk replace the use of the scheduler
lock in vcpu_runstate_get() by a newly introduced sequence counter.
Convert the "no lock if current" property to "use a local counter
instance", thus guaranteeing the loop to exit after the first iteration.
Skeleton and commentary of the seqcount implementation based on /
derived from Linux 6.11-rc.
To have runstate_seq placed next to runstate in struct vcpu, without
introducing a new obvious padding hole, yet while keeping the latter
adjacent to runstate_guest{,_area} as well, move runstate down a little.
This is part of XSA-492.
Requested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -281,13 +281,18 @@ static inline void vcpu_runstate_change(
}
delta = new_entry_time - v->runstate.state_entry_time;
- if ( delta > 0 )
+
+ /* Serialization: ->schedule_lock (see ASSERT() above). */
+ with_seq_write(&v->runstate_seq)
{
- v->runstate.time[v->runstate.state] += delta;
- v->runstate.state_entry_time = new_entry_time;
- }
+ if ( delta > 0 )
+ {
+ v->runstate.time[v->runstate.state] += delta;
+ v->runstate.state_entry_time = new_entry_time;
+ }
- v->runstate.state = new_state;
+ v->runstate.state = new_state;
+ }
}
void sched_guest_idle(void (*idle) (void), unsigned int cpu)
@@ -307,30 +312,18 @@ void sched_guest_idle(void (*idle) (void
void vcpu_runstate_get(const struct vcpu *v,
struct vcpu_runstate_info *runstate)
{
- spinlock_t *lock;
- s_time_t delta;
- struct sched_unit *unit;
+ struct seqcount seq = SEQCNT_ZERO();
+ const struct seqcount *s = likely(v == current) ? &seq : &v->runstate_seq;
- rcu_read_lock(&sched_res_rculock);
-
- /*
- * Be careful in case of an idle vcpu: the assignment to a unit might
- * change even with the scheduling lock held, so be sure to use the
- * correct unit for locking in order to avoid triggering an ASSERT() in
- * the unlock function.
- */
- unit = is_idle_vcpu(v) ? get_sched_res(v->processor)->sched_unit_idle
- : v->sched_unit;
- lock = likely(v == current) ? NULL : unit_schedule_lock_irq(unit);
- memcpy(runstate, &v->runstate, sizeof(*runstate));
- delta = NOW() - runstate->state_entry_time;
- if ( delta > 0 )
- runstate->time[runstate->state] += delta;
-
- if ( unlikely(lock != NULL) )
- unit_schedule_unlock_irq(lock, unit);
+ until_seq_read(s)
+ {
+ s_time_t delta;
- rcu_read_unlock(&sched_res_rculock);
+ *runstate = v->runstate;
+ delta = NOW() - runstate->state_entry_time;
+ if ( delta > 0 )
+ runstate->time[runstate->state] += delta;
+ }
}
uint64_t get_cpu_idle_time(unsigned int cpu)
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -16,6 +16,7 @@
#include <xen/radix-tree.h>
#include <xen/multicall.h>
#include <xen/nospec.h>
+#include <xen/seqcount.h>
#include <xen/tasklet.h>
#include <xen/mm.h>
#include <xen/smp.h>
@@ -198,7 +199,6 @@ struct vcpu
struct sched_unit *sched_unit;
- struct vcpu_runstate_info runstate;
#ifndef CONFIG_COMPAT
# define runstate_guest(v) ((v)->runstate_guest)
XEN_GUEST_HANDLE(vcpu_runstate_info_t) runstate_guest; /* guest address */
@@ -210,6 +210,8 @@ struct vcpu
} runstate_guest; /* guest address */
#endif
struct guest_area runstate_guest_area;
+ struct vcpu_runstate_info runstate;
+ struct seqcount runstate_seq;
unsigned int new_state;
/* Has the FPU been initialised? */
--- /dev/null
+++ b/xen/include/xen/seqcount.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef XEN_SEQCOUNT_H
+#define XEN_SEQCOUNT_H
+
+#include <xen/lib.h>
+#include <xen/nospec.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * Sequence counters (seqcount_t)
+ *
+ * This is the raw counting mechanism, without any writer protection.
+ *
+ * Write side critical sections must be serialized (and non-preemptible).
+ *
+ * If readers can be invoked from interrupt contexts, interrupts must also
+ * be respectively disabled before entering the write section.
+ *
+ * This mechanism can't be used if the protected data contains pointers,
+ * as the writer can invalidate a pointer that a reader is following.
+ */
+struct seqcount {
+ unsigned int sequence;
+};
+
+/*
+ * SEQCNT_ZERO() - initializer for seqcount_t
+ * @name: Name of the struct seqcount instance
+ */
+#define SEQCNT_ZERO() { .sequence = 0 }
+
+static inline unsigned int seqprop_sequence(const struct seqcount *s)
+{
+ return ACCESS_ONCE(s->sequence);
+}
+
+/*
+ * read_seqcount_begin() - begin a seqcount read critical section
+ * @s: Pointer to struct seqcount
+ *
+ * Return: count to be passed to read_seqcount_retry()
+ */
+static inline unsigned int _read_seqcount_begin(const struct seqcount *s)
+{
+ unsigned int seq;
+
+ while ((seq = seqprop_sequence(s)) & 1)
+ cpu_relax();
+
+ smp_rmb();
+
+ return seq;
+}
+
+static always_inline unsigned int read_seqcount_begin(const struct seqcount *s)
+{
+ unsigned int seq = _read_seqcount_begin(s);
+
+ block_lock_speculation();
+
+ return seq;
+}
+
+/*
+ * read_seqcount_retry() - end a seqcount read critical section
+ * @s: Pointer to struct seqcount
+ * @start: count, from read_seqcount_begin()
+ *
+ * read_seqcount_retry closes the read critical section of given struct
+ * seqcount. If the critical section was invalid, it must be ignored
+ * (and typically retried).
+ *
+ * Return: true if a read section retry is required, else false
+ */
+static inline bool _read_seqcount_retry(const struct seqcount *s,
+ unsigned int start)
+{
+ smp_rmb();
+ return unlikely(seqprop_sequence(s) != start);
+}
+
+static always_inline bool read_seqcount_retry(const struct seqcount *s,
+ unsigned int start)
+{
+ return lock_evaluate_nospec(_read_seqcount_retry(s, start));
+}
+
+/* Loops until a consistent count has been observed across the loop body. */
+#define until_seq_read(seq) \
+ for ( unsigned int retry_ = 1, count_; \
+ retry_ && (count_ = read_seqcount_begin(seq), true); \
+ retry_ = read_seqcount_retry(seq, count_) )
+
+/*
+ * write_seqcount_begin() - start a struct seqcount write side critical section
+ * @s: Pointer to struct seqcount
+ *
+ * Context: sequence counter write side sections must be serialized.
+ * If readers can be invoked from interrupt context, interrupts must be
+ * respectively disabled.
+ */
+static inline void write_seqcount_begin(struct seqcount *s)
+{
+ add_sized(&s->sequence, 1);
+ smp_wmb();
+}
+
+/*
+ * write_seqcount_end() - end a struct seqcount write side critical section
+ * @s: Pointer to seqcount
+ */
+static inline void write_seqcount_end(struct seqcount *s)
+{
+ smp_wmb();
+ add_sized(&s->sequence, 1);
+}
+
+/*
+ * Not really a loop, but we need write_seqcount_{begin,end}() in the correct
+ * position.
+ */
+#define with_seq_write(seq) \
+ for ( bool once_ = true; \
+ once_ && (write_seqcount_begin(seq), true); \
+ (write_seqcount_end(seq), once_ = false) )
+
+#endif /* XEN_SEQCOUNT_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

View file

@ -1,104 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_getdomaininfo without acquiring domctl lock
getdomaininfo() is not called under consistently the same lock. Thus,
with caller side locking irrelevant, it can as well be called with the
domctl lock not held. (Callers not pausing the domain they want to
retrieve information for already need to be aware that not all of the
data returned can be relied on as being consistent; most data will also
be stale by the time the caller gets to look at it.)
Move the handling not only ahead of acquiring the lock, but also ahead
of the XSM check, leveraging that the sub-op has its own hook.
While moving, convert an assignment to an assertion: The domain in
question was determined from the field which previously was "updated".
This is part of XSA-492.
Fixes: 5513bd0b4675 ("add xenstore domain flag to hypervisor")
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -318,6 +318,26 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
break;
}
+ /* Handle sub-ops not requiring the domctl lock. */
+ switch ( op->cmd )
+ {
+ case XEN_DOMCTL_getdomaininfo:
+ ret = xsm_getdomaininfo(XSM_XS_PRIV, d);
+ if ( !ret )
+ {
+ getdomaininfo(d, &op->u.getdomaininfo);
+
+ ASSERT(op->domain == op->u.getdomaininfo.domain);
+ copyback = true;
+ }
+
+ goto domctl_out_unlock_domonly;
+
+ default:
+ /* Everything else handled further down. */
+ break;
+ }
+
ret = xsm_domctl(XSM_OTHER, d, op->cmd,
/* SSIDRef only applicable for cmd == createdomain */
op->u.createdomain.ssidref);
@@ -516,17 +536,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
copyback = 1;
break;
- case XEN_DOMCTL_getdomaininfo:
- ret = xsm_getdomaininfo(XSM_XS_PRIV, d);
- if ( ret )
- break;
-
- getdomaininfo(d, &op->u.getdomaininfo);
-
- op->domain = op->u.getdomaininfo.domain;
- copyback = 1;
- break;
-
case XEN_DOMCTL_getvcpucontext:
{
vcpu_guest_context_u c = { .nat = NULL };
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -172,9 +172,13 @@ static XSM_INLINE int cf_check xsm_domct
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
return xsm_default_action(XSM_DM_PRIV, current->domain, d);
- case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
return xsm_default_action(XSM_XS_PRIV, current->domain, d);
+
+ case XEN_DOMCTL_getdomaininfo:
+ ASSERT_UNREACHABLE();
+ return -EILSEQ;
+
default:
return xsm_default_action(XSM_PRIV, current->domain, d);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -682,8 +682,12 @@ static int cf_check flask_domctl(struct
*/
return avc_current_has_perm(ssidref, SECCLASS_DOMAIN, DOMAIN__CREATE, NULL);
- /* These have individual XSM hooks (common/domctl.c) */
+ /* These have individual XSM hooks and don't make it here. */
case XEN_DOMCTL_getdomaininfo:
+ ASSERT_UNREACHABLE();
+ return -EILSEQ;
+
+ /* These have individual XSM hooks (common/domctl.c) */
case XEN_DOMCTL_scheduler_op:
case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_iomem_permission:

View file

@ -1,87 +0,0 @@
From: Daniel P. Smith <dpsmith@apertussolutions.com>
Subject: domctl: protect locking for get_domain_state
When DOMID_INVALID is passed, the dom exec handler lock is being taken
without any check that the domain is even allowed to take the lock. This
allows for an unauthorized domain to DoS the get_domain_state domctl op.
Move to consider the op effectively being called against the hypervisor.
Thus it is the target of the call being invoked to identify the last
domain with a state change. The subsequent check of whether the source
domain is allowed the state of the last domain to change state is still
relevant.
This is part of XSA-492.
Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/tools/flask/policy/modules/xenstore.te
+++ b/tools/flask/policy/modules/xenstore.te
@@ -14,6 +14,7 @@ allow xenstore_t xen_t:xen writeconsole;
# Xenstore queries domaininfo on all domains
allow xenstore_t domain_type:domain getdomaininfo;
allow xenstore_t domain_type:domain2 get_domain_state;
+allow xenstore_t domxen_t:domain2 get_domain_state;
# As a shortcut, the following 3 rules are used instead of adding a domain_comms
# rule between xenstore_t and every domain type that talks to xenstore
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -216,12 +216,8 @@ int get_domain_state(struct xen_domctl_g
if ( info->pad0 )
return -EINVAL;
- if ( d )
+ if ( d != dom_xen )
{
- rc = xsm_get_domain_state(XSM_XS_PRIV, d);
- if ( rc )
- return rc;
-
set_domain_state_info(info, d);
return 0;
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -304,13 +304,19 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
fallthrough;
case XEN_DOMCTL_test_assign_device:
case XEN_DOMCTL_vm_event_op:
- case XEN_DOMCTL_get_domain_state:
if ( op->domain == DOMID_INVALID )
{
d = NULL;
break;
}
fallthrough;
+ case XEN_DOMCTL_get_domain_state:
+ if ( op->domain == DOMID_INVALID )
+ {
+ d = dom_xen;
+ break;
+ }
+ fallthrough;
default:
d = rcu_lock_domain_by_id(op->domain);
if ( !d )
@@ -863,7 +869,9 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
break;
case XEN_DOMCTL_get_domain_state:
- ret = get_domain_state(&op->u.get_domain_state, d, &op->domain);
+ ret = xsm_get_domain_state(XSM_XS_PRIV, d);
+ if ( !ret )
+ ret = get_domain_state(&op->u.get_domain_state, d, &op->domain);
if ( !ret )
copyback = true;
break;
@@ -876,7 +884,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
domctl_lock_release();
domctl_out_unlock_domonly:
- if ( d && d != dom_io )
+ if ( d && !is_system_domain(d) )
rcu_unlock_domain(d);
if ( copyback && __copy_to_guest(u_domctl, op, 1) )

View file

@ -1,81 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_get_domain_state without acquiring domctl lock
get_domain_state() uses its own locking. Thus, with caller side locking
irrelevant, it can as well be called with the domctl lock not held.
Move the handling not only ahead of acquiring the lock, but also ahead
of the XSM check, leveraging that the sub-op has its own hook.
This is part of XSA-492.
Fixes: 3ad3df1bd0aa ("xen: add new domctl get_domain_state")
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -339,6 +339,14 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
goto domctl_out_unlock_domonly;
+ case XEN_DOMCTL_get_domain_state:
+ ret = xsm_get_domain_state(XSM_XS_PRIV, d);
+ if ( !ret )
+ ret = get_domain_state(&op->u.get_domain_state, d, &op->domain);
+ if ( !ret )
+ copyback = true;
+ goto domctl_out_unlock_domonly;
+
default:
/* Everything else handled further down. */
break;
@@ -868,14 +876,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
ret = -EOPNOTSUPP;
break;
- case XEN_DOMCTL_get_domain_state:
- ret = xsm_get_domain_state(XSM_XS_PRIV, d);
- if ( !ret )
- ret = get_domain_state(&op->u.get_domain_state, d, &op->domain);
- if ( !ret )
- copyback = true;
- break;
-
default:
ret = arch_do_domctl(op, d, u_domctl);
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -172,10 +172,9 @@ static XSM_INLINE int cf_check xsm_domct
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
return xsm_default_action(XSM_DM_PRIV, current->domain, d);
- case XEN_DOMCTL_get_domain_state:
- return xsm_default_action(XSM_XS_PRIV, current->domain, d);
case XEN_DOMCTL_getdomaininfo:
+ case XEN_DOMCTL_get_domain_state:
ASSERT_UNREACHABLE();
return -EILSEQ;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -684,6 +684,7 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks and don't make it here. */
case XEN_DOMCTL_getdomaininfo:
+ case XEN_DOMCTL_get_domain_state:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -694,7 +695,6 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_set_target:
case XEN_DOMCTL_vm_event_op:
- case XEN_DOMCTL_get_domain_state:
/* These have individual XSM hooks (arch/../domctl.c) */
case XEN_DOMCTL_bind_pt_irq:

View file

@ -1,156 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domain: locking for iomem_caps accesses
In order to be able to pull at least the XEN_DOMCTL_iomem_mapping handling
out of the domctl-locked region, a separate (per-domain) lock is needed to
synchronize in particular with XEN_DOMCTL_iomem_permission.
Locking is added only as far as domctl-s are affected. Uses presently
outside of the domctl lock may want dealing with subsequently (perhaps
limited to non-__init code).
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -518,10 +518,15 @@ static int late_hwdom_init(struct domain
* may be modified after this hypercall returns if a more complex
* device model is desired.
*/
+ write_lock(&dom0->caps_lock);
rangeset_swap(d->irq_caps, dom0->irq_caps);
rangeset_swap(d->iomem_caps, dom0->iomem_caps);
#ifdef CONFIG_X86
rangeset_swap(d->arch.ioport_caps, dom0->arch.ioport_caps);
+#endif
+ write_unlock(&dom0->caps_lock);
+
+#ifdef CONFIG_X86
setup_io_bitmap(d);
setup_io_bitmap(dom0);
#endif
@@ -873,6 +878,7 @@ struct domain *domain_create(domid_t dom
rspin_lock_init_prof(d, domain_lock);
rspin_lock_init_prof(d, page_alloc_lock);
spin_lock_init(&d->hypercall_deadlock_mutex);
+ rwlock_init(&d->caps_lock);
INIT_PAGE_LIST_HEAD(&d->page_list);
INIT_PAGE_LIST_HEAD(&d->extra_page_list);
INIT_PAGE_LIST_HEAD(&d->xenpage_list);
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -267,6 +267,35 @@ static struct vnuma_info *vnuma_init(con
return ERR_PTR(ret);
}
+void iocaps_double_lock(struct domain *d, bool write)
+{
+ struct domain *currd = current->domain;
+
+ if ( d->domain_id > currd->domain_id )
+ read_lock(&currd->caps_lock);
+
+ if ( write )
+ write_lock(&d->caps_lock);
+ else
+ read_lock(&d->caps_lock);
+
+ if ( d->domain_id < currd->domain_id )
+ read_lock(&currd->caps_lock);
+}
+
+void iocaps_double_unlock(struct domain *d, bool write)
+{
+ struct domain *currd = current->domain;
+
+ if ( d != currd )
+ read_unlock(&currd->caps_lock);
+
+ if ( write )
+ write_unlock(&d->caps_lock);
+ else
+ read_unlock(&d->caps_lock);
+}
+
static bool is_stable_domctl(uint32_t cmd)
{
return cmd == XEN_DOMCTL_get_domain_state;
@@ -687,6 +716,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
break;
+ iocaps_double_lock(d, true);
+
if ( !iomem_access_permitted(current->domain,
mfn, mfn + nr_mfns - 1) ||
xsm_iomem_permission(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, allow) )
@@ -695,6 +726,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
else
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
+
+ iocaps_double_unlock(d, true);
break;
}
@@ -719,19 +752,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
break;
#endif
+ iocaps_double_lock(d, false);
+
ret = -EPERM;
if ( !iomem_access_permitted(current->domain, mfn, mfn_end) ||
- !iomem_access_permitted(d, mfn, mfn_end) )
- break;
-
- ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add);
- if ( ret )
- break;
-
- if ( !paging_mode_translate(d) )
- break;
-
- if ( add )
+ !iomem_access_permitted(d, mfn, mfn_end) ||
+ (ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add)) ||
+ !paging_mode_translate(d) )
+ /* Nothing. */;
+ else if ( add )
{
printk(XENLOG_G_DEBUG
"memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
@@ -755,6 +784,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
"memory_map: error %ld removing dom%d access to [%lx,%lx]\n",
ret, d->domain_id, mfn, mfn_end);
}
+
+ iocaps_double_unlock(d, false);
break;
}
--- a/xen/include/xen/iocap.h
+++ b/xen/include/xen/iocap.h
@@ -12,6 +12,9 @@
#include <asm/iocap.h>
#include <asm/p2m.h>
+void iocaps_double_lock(struct domain *d, bool write);
+void iocaps_double_unlock(struct domain *d, bool write);
+
static inline int iomem_permit_access(struct domain *d, unsigned long s,
unsigned long e)
{
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -536,6 +536,7 @@ struct domain
#endif
/* I/O capabilities (access to IRQs and memory-mapped I/O). */
+ rwlock_t caps_lock;
struct rangeset *iomem_caps;
struct rangeset *irq_caps;

View file

@ -1,84 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/domain: locking for ioport_caps accesses
In order to be able to pull at least the XEN_DOMCTL_ioport_mapping
handling out of the domctl-locked region, the new separate (per-domain)
lock is used to synchronize in particular with
XEN_DOMCTL_ioport_permission.
Locking is added only as far as domctl-s are affected. Uses presently
outside of the domctl lock may want dealing with subsequently (perhaps
limited to non-__init code).
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -233,6 +233,8 @@ long arch_do_domctl(
unsigned int np = domctl->u.ioport_permission.nr_ports;
int allow = domctl->u.ioport_permission.allow_access;
+ iocaps_double_lock(d, true);
+
if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
ret = -EINVAL;
else if ( !ioports_access_permitted(currd, fp, fp + np - 1) ||
@@ -242,6 +244,8 @@ long arch_do_domctl(
ret = ioports_permit_access(d, fp, fp + np - 1);
else
ret = ioports_deny_access(d, fp, fp + np - 1);
+
+ iocaps_double_unlock(d, true);
break;
}
@@ -648,16 +652,13 @@ long arch_do_domctl(
break;
}
- ret = -EPERM;
- if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) )
- break;
-
- ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add);
- if ( ret )
- break;
-
hvm = &d->arch.hvm;
- if ( add )
+ iocaps_double_lock(d, true);
+
+ if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) ||
+ (ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add)) )
+ ret = ret ?: -EPERM;
+ else if ( add )
{
printk(XENLOG_G_INFO
"ioport_map:add: dom%d gport=%x mport=%x nr=%x\n",
@@ -718,6 +720,8 @@ long arch_do_domctl(
"ioport_map: error %ld denying dom%d access to [%x,%x]\n",
ret, d->domain_id, fmp, fmp + np - 1);
}
+
+ iocaps_double_unlock(d, true);
break;
}
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -2339,9 +2339,12 @@ void __hwdom_init setup_io_bitmap(struct
return;
bitmap_fill(d->arch.hvm.io_bitmap, 0x10000);
+
+ read_lock(&d->caps_lock);
if ( rangeset_report_ranges(d->arch.ioport_caps, 0, 0x10000,
io_bitmap_cb, d) )
BUG();
+ read_unlock(&d->caps_lock);
/*
* We need to trap 4-byte accesses to 0xcf8 (see admin_io_okay(),

View file

@ -1,202 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domain: locking for irq_caps accesses
In order to be able to pull at least the XEN_DOMCTL_{,un}bind_pt_irq
handling out of the domctl-locked region, a separate (per-domain) lock is
needed to synchronize in particular with XEN_DOMCTL_{irq,gsi}_permission.
Locking is added only as far as domctl-s are affected. Uses presently
outside of the domctl lock may want dealing with subsequently (perhaps
limited to non-__init code).
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Julien Grall <julien@xen.org>
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -76,6 +76,7 @@ long arch_do_domctl(struct xen_domctl *d
case XEN_DOMCTL_bind_pt_irq:
{
int rc;
+ struct domain *currd = current->domain;
struct xen_domctl_bind_pt_irq *bind = &domctl->u.bind_pt_irq;
uint32_t irq = bind->u.spi.spi;
uint32_t virq = bind->machine_irq;
@@ -107,21 +108,26 @@ long arch_do_domctl(struct xen_domctl *d
if ( rc )
return rc;
- if ( !irq_access_permitted(current->domain, irq) )
- return -EPERM;
+ read_lock(&currd->caps_lock);
- if ( !vgic_reserve_virq(d, virq) )
- return -EBUSY;
-
- rc = route_irq_to_guest(d, virq, irq, "routed IRQ");
- if ( rc )
- vgic_free_virq(d, virq);
+ if ( !irq_access_permitted(currd, irq) )
+ rc = -EPERM;
+ else if ( !vgic_reserve_virq(d, virq) )
+ rc = -EBUSY;
+ else
+ {
+ rc = route_irq_to_guest(d, virq, irq, "routed IRQ");
+ if ( rc )
+ vgic_free_virq(d, virq);
+ }
+ read_unlock(&currd->caps_lock);
return rc;
}
case XEN_DOMCTL_unbind_pt_irq:
{
int rc;
+ struct domain *currd = current->domain;
struct xen_domctl_bind_pt_irq *bind = &domctl->u.bind_pt_irq;
uint32_t irq = bind->u.spi.spi;
uint32_t virq = bind->machine_irq;
@@ -138,16 +144,15 @@ long arch_do_domctl(struct xen_domctl *d
if ( rc )
return rc;
- if ( !irq_access_permitted(current->domain, irq) )
- return -EPERM;
-
- rc = release_guest_irq(d, virq);
- if ( rc )
- return rc;
+ read_lock(&currd->caps_lock);
- vgic_free_virq(d, virq);
+ if ( !irq_access_permitted(currd, irq) )
+ rc = -EPERM;
+ else if ( !(rc = release_guest_irq(d, virq)) )
+ vgic_free_virq(d, virq);
- return 0;
+ read_unlock(&currd->caps_lock);
+ return rc;
}
case XEN_DOMCTL_vuart_op:
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -267,16 +267,17 @@ long arch_do_domctl(
break;
}
- ret = -EPERM;
+ iocaps_double_lock(d, true);
+
if ( !irq_access_permitted(currd, irq) ||
xsm_irq_permission(XSM_HOOK, d, irq, flags) )
- break;
-
- if ( flags )
+ ret = -EPERM;
+ else if ( flags )
ret = irq_permit_access(d, irq);
else
ret = irq_deny_access(d, irq);
+ iocaps_double_unlock(d, true);
break;
}
@@ -579,20 +580,27 @@ long arch_do_domctl(
break;
irq = domain_pirq_to_irq(d, bind->machine_irq);
- ret = -EPERM;
- if ( irq <= 0 || !irq_access_permitted(currd, irq) )
- break;
+ if ( irq <= 0 )
+ ret = -EPERM;
- ret = -ESRCH;
- if ( is_iommu_enabled(d) )
+ read_lock(&currd->caps_lock);
+
+ if ( !irq_access_permitted(currd, irq) )
+ ret = -EPERM;
+ else if ( is_iommu_enabled(d) )
{
pcidevs_lock();
ret = pt_irq_create_bind(d, bind);
pcidevs_unlock();
+
+ if ( ret < 0 )
+ printk(XENLOG_G_ERR "pt_irq_create_bind failed (%ld) for %pd\n",
+ ret, d);
}
- if ( ret < 0 )
- printk(XENLOG_G_ERR "pt_irq_create_bind failed (%ld) for dom%d\n",
- ret, d->domain_id);
+ else
+ ret = -ESRCH;
+
+ read_unlock(&currd->caps_lock);
break;
}
@@ -605,23 +613,26 @@ long arch_do_domctl(
if ( !is_hvm_domain(d) )
break;
- ret = -EPERM;
- if ( irq <= 0 || !irq_access_permitted(currd, irq) )
- break;
-
ret = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
if ( ret )
break;
- if ( is_iommu_enabled(d) )
+ read_lock(&currd->caps_lock);
+
+ if ( !irq_access_permitted(currd, irq) )
+ ret = -EPERM;
+ else if ( is_iommu_enabled(d) )
{
pcidevs_lock();
ret = pt_irq_destroy_bind(d, bind);
pcidevs_unlock();
+
+ if ( ret < 0 )
+ printk(XENLOG_G_ERR "pt_irq_destroy_bind failed (%ld) for %pd\n",
+ ret, d);
}
- if ( ret < 0 )
- printk(XENLOG_G_ERR "pt_irq_destroy_bind failed (%ld) for dom%d\n",
- ret, d->domain_id);
+
+ read_unlock(&currd->caps_lock);
break;
}
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -695,6 +695,9 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
ret = -EINVAL;
break;
}
+
+ iocaps_double_lock(d, true);
+
irq = pirq_access_permitted(current->domain, pirq);
if ( !irq || xsm_irq_permission(XSM_HOOK, d, irq, allow) )
ret = -EPERM;
@@ -702,6 +705,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
ret = irq_permit_access(d, irq);
else
ret = irq_deny_access(d, irq);
+
+ iocaps_double_unlock(d, true);
break;
}
#endif

View file

@ -1,85 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: XSM/Flask: split the .iomem_mapping() hook
It's used twice in entirely different situations. The use in do_domctl()
wants to become an ordinary XSM_DM_PRIV invocation, while the one in vPCI
code need to remain XSM_HOOK (it may plausibly become XSM_TARGET). For
Flask, the same backing function will continue to be used for the time
being.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
--- a/xen/drivers/vpci/header.c
+++ b/xen/drivers/vpci/header.c
@@ -67,7 +67,7 @@ static int cf_check map_range(
return -EPERM;
}
- rc = xsm_iomem_mapping(XSM_HOOK, map->d, map_mfn, m_end, map->map);
+ rc = xsm_iomem_mapping_vpci(XSM_HOOK, map->d, map_mfn, m_end, map->map);
if ( rc )
{
printk(XENLOG_G_WARNING
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -580,6 +580,13 @@ static XSM_INLINE int cf_check xsm_iomem
return xsm_default_action(action, current->domain, d);
}
+static XSM_INLINE int cf_check xsm_iomem_mapping_vpci(
+ XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, current->domain, d);
+}
+
static XSM_INLINE int cf_check xsm_pci_config_permission(
XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf, uint16_t start,
uint16_t end, uint8_t access)
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -118,6 +118,8 @@ struct xsm_ops {
uint8_t allow);
int (*iomem_mapping)(struct domain *d, uint64_t s, uint64_t e,
uint8_t allow);
+ int (*iomem_mapping_vpci)(struct domain *d, uint64_t s, uint64_t e,
+ uint8_t allow);
int (*pci_config_permission)(struct domain *d, uint32_t machine_bdf,
uint16_t start, uint16_t end, uint8_t access);
@@ -523,6 +525,12 @@ static inline int xsm_iomem_mapping(
return alternative_call(xsm_ops.iomem_mapping, d, s, e, allow);
}
+static inline int xsm_iomem_mapping_vpci(
+ xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+{
+ return alternative_call(xsm_ops.iomem_mapping_vpci, d, s, e, allow);
+}
+
static inline int xsm_pci_config_permission(
xsm_default_t def, struct domain *d, uint32_t machine_bdf, uint16_t start,
uint16_t end, uint8_t access)
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -76,6 +76,7 @@ static const struct xsm_ops __initconst_
.irq_permission = xsm_irq_permission,
.iomem_permission = xsm_iomem_permission,
.iomem_mapping = xsm_iomem_mapping,
+ .iomem_mapping_vpci = xsm_iomem_mapping_vpci,
.pci_config_permission = xsm_pci_config_permission,
.get_vnumainfo = xsm_get_vnumainfo,
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1950,6 +1950,7 @@ static const struct xsm_ops __initconst_
.irq_permission = flask_irq_permission,
.iomem_permission = flask_iomem_permission,
.iomem_mapping = flask_iomem_mapping,
+ .iomem_mapping_vpci = flask_iomem_mapping,
.pci_config_permission = flask_pci_config_permission,
.resource_plug_core = flask_resource_plug_core,

View file

@ -1,194 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_memory_mapping without acquiring domctl lock
With dedicated locking added, the domctl lock isn't required here anymore.
Move the re-purposed dedicated XSM check as early as possible.
Minimal "modernization": Switch "add" to bool and use %pd in log messages.
This is part of XSA-492.
Fixes: fda49f9b3fbb ("Add build option to allow more hypercalls from stubdoms")
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -376,6 +376,66 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
copyback = true;
goto domctl_out_unlock_domonly;
+ case XEN_DOMCTL_memory_mapping:
+ {
+ unsigned long gfn = op->u.memory_mapping.first_gfn;
+ unsigned long mfn = op->u.memory_mapping.first_mfn;
+ unsigned long nr_mfns = op->u.memory_mapping.nr_mfns;
+ unsigned long mfn_end = mfn + nr_mfns - 1;
+ bool add = op->u.memory_mapping.add_mapping;
+
+ ret = -EINVAL;
+ if ( mfn_end < mfn || /* Wrap? */
+ ((mfn | mfn_end) >> (paddr_bits - PAGE_SHIFT)) ||
+ (gfn + nr_mfns - 1) < gfn ) /* Wrap? */
+ goto domctl_out_unlock_domonly;
+
+ ret = xsm_iomem_mapping(XSM_DM_PRIV, d, mfn, mfn_end, add);
+ if ( ret || !paging_mode_translate(d) )
+ goto domctl_out_unlock_domonly;
+
+#ifndef CONFIG_X86 /* XXX ARM!? */
+ ret = -E2BIG;
+ /* Must break hypercall up as this could take a while. */
+ if ( nr_mfns > 64 )
+ goto domctl_out_unlock_domonly;
+#endif
+
+ iocaps_double_lock(d, false);
+
+ ret = -EPERM;
+ if ( !iomem_access_permitted(current->domain, mfn, mfn_end) ||
+ !iomem_access_permitted(d, mfn, mfn_end) )
+ /* Nothing. */;
+ else if ( add )
+ {
+ printk(XENLOG_G_DEBUG
+ "memory_map:add: %pd gfn=%lx mfn=%lx nr=%lx\n",
+ d, gfn, mfn, nr_mfns);
+
+ ret = map_mmio_regions(d, _gfn(gfn), nr_mfns, _mfn(mfn));
+ if ( ret < 0 )
+ printk(XENLOG_G_WARNING
+ "memory_map:fail: %pd gfn=%lx mfn=%lx nr=%lx ret:%ld\n",
+ d, gfn, mfn, nr_mfns, ret);
+ }
+ else
+ {
+ printk(XENLOG_G_DEBUG
+ "memory_map:remove: %pd gfn=%lx mfn=%lx nr=%lx\n",
+ d, gfn, mfn, nr_mfns);
+
+ ret = unmap_mmio_regions(d, _gfn(gfn), nr_mfns, _mfn(mfn));
+ if ( ret < 0 && is_hardware_domain(current->domain) )
+ printk(XENLOG_ERR
+ "memory_map: error %ld removing %pd access to [%lx,%lx]\n",
+ ret, d, mfn, mfn_end);
+ }
+
+ iocaps_double_unlock(d, false);
+ goto domctl_out_unlock_domonly;
+ }
+
default:
/* Everything else handled further down. */
break;
@@ -736,64 +796,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
break;
}
- case XEN_DOMCTL_memory_mapping:
- {
- unsigned long gfn = op->u.memory_mapping.first_gfn;
- unsigned long mfn = op->u.memory_mapping.first_mfn;
- unsigned long nr_mfns = op->u.memory_mapping.nr_mfns;
- unsigned long mfn_end = mfn + nr_mfns - 1;
- int add = op->u.memory_mapping.add_mapping;
-
- ret = -EINVAL;
- if ( mfn_end < mfn || /* wrap? */
- ((mfn | mfn_end) >> (paddr_bits - PAGE_SHIFT)) ||
- (gfn + nr_mfns - 1) < gfn ) /* wrap? */
- break;
-
-#ifndef CONFIG_X86 /* XXX ARM!? */
- ret = -E2BIG;
- /* Must break hypercall up as this could take a while. */
- if ( nr_mfns > 64 )
- break;
-#endif
-
- iocaps_double_lock(d, false);
-
- ret = -EPERM;
- if ( !iomem_access_permitted(current->domain, mfn, mfn_end) ||
- !iomem_access_permitted(d, mfn, mfn_end) ||
- (ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add)) ||
- !paging_mode_translate(d) )
- /* Nothing. */;
- else if ( add )
- {
- printk(XENLOG_G_DEBUG
- "memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
- d->domain_id, gfn, mfn, nr_mfns);
-
- ret = map_mmio_regions(d, _gfn(gfn), nr_mfns, _mfn(mfn));
- if ( ret < 0 )
- printk(XENLOG_G_WARNING
- "memory_map:fail: dom%d gfn=%lx mfn=%lx nr=%lx ret:%ld\n",
- d->domain_id, gfn, mfn, nr_mfns, ret);
- }
- else
- {
- printk(XENLOG_G_DEBUG
- "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
- d->domain_id, gfn, mfn, nr_mfns);
-
- ret = unmap_mmio_regions(d, _gfn(gfn), nr_mfns, _mfn(mfn));
- if ( ret < 0 && is_hardware_domain(current->domain) )
- printk(XENLOG_ERR
- "memory_map: error %ld removing dom%d access to [%lx,%lx]\n",
- ret, d->domain_id, mfn, mfn_end);
- }
-
- iocaps_double_unlock(d, false);
- break;
- }
-
case XEN_DOMCTL_settimeoffset:
domain_set_time_offset(d, op->u.settimeoffset.time_offset_seconds);
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -168,13 +168,13 @@ static XSM_INLINE int cf_check xsm_domct
switch ( cmd )
{
case XEN_DOMCTL_ioport_mapping:
- case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
return xsm_default_action(XSM_DM_PRIV, current->domain, d);
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_memory_mapping:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -576,7 +576,7 @@ static XSM_INLINE int cf_check xsm_iomem
static XSM_INLINE int cf_check xsm_iomem_mapping(
XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -685,6 +685,7 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks and don't make it here. */
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_memory_mapping:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -692,7 +693,6 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_scheduler_op:
case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_iomem_permission:
- case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_set_target:
case XEN_DOMCTL_vm_event_op:

View file

@ -1,97 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_ioport_mapping without acquiring domctl lock
With dedicated locking added, the domctl lock isn't required here anymore.
As the handling is in arch-specific code (x86 only), almost no code is
being moved, but a 2nd (extensible to other sub-ops) invocation of
arch_do_domctl() is being added. Move just the re-purposed dedicated XSM
check as early as possible.
In flask_domctl() don't put #ifdef around the moved case label.
This is part of XSA-492.
Fixes: fda49f9b3fbb ("Add build option to allow more hypercalls from stubdoms")
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -663,12 +663,15 @@ long arch_do_domctl(
break;
}
+ ret = xsm_ioport_mapping(XSM_DM_PRIV, d, fmp, fmp + np - 1, add);
+ if ( ret )
+ break;
+
hvm = &d->arch.hvm;
iocaps_double_lock(d, true);
- if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) ||
- (ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add)) )
- ret = ret ?: -EPERM;
+ if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) )
+ ret = -EPERM;
else if ( add )
{
printk(XENLOG_G_INFO
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -436,6 +436,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
goto domctl_out_unlock_domonly;
}
+ case XEN_DOMCTL_ioport_mapping:
+ ret = arch_do_domctl(op, d, u_domctl);
+ goto domctl_out_unlock_domonly;
+
default:
/* Everything else handled further down. */
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -167,13 +167,13 @@ static XSM_INLINE int cf_check xsm_domct
XSM_ASSERT_ACTION(XSM_OTHER);
switch ( cmd )
{
- case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
return xsm_default_action(XSM_DM_PRIV, current->domain, d);
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_memory_mapping:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -772,7 +772,7 @@ static XSM_INLINE int cf_check xsm_iopor
static XSM_INLINE int cf_check xsm_ioport_mapping(
XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -685,6 +685,7 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks and don't make it here. */
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_memory_mapping:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -703,7 +704,6 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks (arch/x86/domctl.c) */
case XEN_DOMCTL_shadow_op:
case XEN_DOMCTL_ioport_permission:
- case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_gsi_permission:
#endif
#ifdef CONFIG_HAS_PASSTHROUGH

View file

@ -1,128 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_{,un}bind_pt_irq without acquiring domctl lock
With dedicated locking added, the domctl lock isn't required here anymore.
(It also already isn't used when pt_irq_{create,destroy}_bind() are
invoked for PVH Dom0.) As the handling is in arch-specific code, no code
is being moved, but the 2nd (extensible to other sub-ops like the ones
here) invocation of arch_do_domctl() is being re-used.
This is part of XSA-492.
Fixes: fda49f9b3fbb ("Add build option to allow more hypercalls from stubdoms")
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Acked-by: Julien Grall <julien@xen.org>
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -104,7 +104,7 @@ long arch_do_domctl(struct xen_domctl *d
if ( rc )
return rc;
- rc = xsm_bind_pt_irq(XSM_HOOK, d, bind);
+ rc = xsm_bind_pt_irq(XSM_DM_PRIV, d, bind);
if ( rc )
return rc;
@@ -140,7 +140,7 @@ long arch_do_domctl(struct xen_domctl *d
if ( irq != virq )
return -EINVAL;
- rc = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
+ rc = xsm_unbind_pt_irq(XSM_DM_PRIV, d, bind);
if ( rc )
return rc;
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -575,7 +575,7 @@ long arch_do_domctl(
if ( !is_hvm_domain(d) )
break;
- ret = xsm_bind_pt_irq(XSM_HOOK, d, bind);
+ ret = xsm_bind_pt_irq(XSM_DM_PRIV, d, bind);
if ( ret )
break;
@@ -613,7 +613,7 @@ long arch_do_domctl(
if ( !is_hvm_domain(d) )
break;
- ret = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
+ ret = xsm_unbind_pt_irq(XSM_DM_PRIV, d, bind);
if ( ret )
break;
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -437,6 +437,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
}
case XEN_DOMCTL_ioport_mapping:
+ case XEN_DOMCTL_bind_pt_irq:
+ case XEN_DOMCTL_unbind_pt_irq:
ret = arch_do_domctl(op, d, u_domctl);
goto domctl_out_unlock_domonly;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -168,13 +168,11 @@ static XSM_INLINE int cf_check xsm_domct
switch ( cmd )
{
case XEN_DOMCTL_bind_pt_irq:
- case XEN_DOMCTL_unbind_pt_irq:
- return xsm_default_action(XSM_DM_PRIV, current->domain, d);
-
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_memory_mapping:
+ case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -541,14 +539,14 @@ static XSM_INLINE int cf_check xsm_unmap
static XSM_INLINE int cf_check xsm_bind_pt_irq(
XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
static XSM_INLINE int cf_check xsm_unbind_pt_irq(
XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -683,10 +683,12 @@ static int cf_check flask_domctl(struct
return avc_current_has_perm(ssidref, SECCLASS_DOMAIN, DOMAIN__CREATE, NULL);
/* These have individual XSM hooks and don't make it here. */
+ case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_memory_mapping:
+ case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
return -EILSEQ;
@@ -697,9 +699,6 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_set_target:
case XEN_DOMCTL_vm_event_op:
- /* These have individual XSM hooks (arch/../domctl.c) */
- case XEN_DOMCTL_bind_pt_irq:
- case XEN_DOMCTL_unbind_pt_irq:
#ifdef CONFIG_X86
/* These have individual XSM hooks (arch/x86/domctl.c) */
case XEN_DOMCTL_shadow_op:

View file

@ -1,172 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_io{mem,port}_permission without acquiring domctl lock
With dedicated locking added, the domctl lock isn't required here anymore.
As the I/O port handling is in arch-specific code (x86 only), no code is
being moved, but the 2nd invocation of arch_do_domctl() is re-used. Move
the re-purposed dedicated XSM checks as early as possible.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -233,12 +233,17 @@ long arch_do_domctl(
unsigned int np = domctl->u.ioport_permission.nr_ports;
int allow = domctl->u.ioport_permission.allow_access;
+ ret = -EINVAL;
+ if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
+ break;
+
+ ret = xsm_ioport_permission(XSM_PRIV, d, fp, fp + np - 1, allow);
+ if ( ret )
+ break;
+
iocaps_double_lock(d, true);
- if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
- ret = -EINVAL;
- else if ( !ioports_access_permitted(currd, fp, fp + np - 1) ||
- xsm_ioport_permission(XSM_HOOK, d, fp, fp + np - 1, allow) )
+ if ( !ioports_access_permitted(currd, fp, fp + np - 1) )
ret = -EPERM;
else if ( allow )
ret = ioports_permit_access(d, fp, fp + np - 1);
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -376,6 +376,34 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
copyback = true;
goto domctl_out_unlock_domonly;
+ case XEN_DOMCTL_iomem_permission:
+ {
+ unsigned long mfn = op->u.iomem_permission.first_mfn;
+ unsigned long nr_mfns = op->u.iomem_permission.nr_mfns;
+ bool allow = op->u.iomem_permission.allow_access;
+
+ ret = -EINVAL;
+ if ( (mfn + nr_mfns - 1) < mfn ) /* Wrap? */
+ goto domctl_out_unlock_domonly;
+
+ ret = xsm_iomem_permission(XSM_PRIV, d, mfn, mfn + nr_mfns - 1, allow);
+ if ( ret )
+ goto domctl_out_unlock_domonly;
+
+ iocaps_double_lock(d, true);
+
+ if ( !iomem_access_permitted(current->domain,
+ mfn, mfn + nr_mfns - 1) )
+ ret = -EPERM;
+ else if ( allow )
+ ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
+ else
+ ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
+
+ iocaps_double_unlock(d, true);
+ goto domctl_out_unlock_domonly;
+ }
+
case XEN_DOMCTL_memory_mapping:
{
unsigned long gfn = op->u.memory_mapping.first_gfn;
@@ -436,6 +464,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
goto domctl_out_unlock_domonly;
}
+ case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
@@ -777,31 +806,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
}
#endif
- case XEN_DOMCTL_iomem_permission:
- {
- unsigned long mfn = op->u.iomem_permission.first_mfn;
- unsigned long nr_mfns = op->u.iomem_permission.nr_mfns;
- int allow = op->u.iomem_permission.allow_access;
-
- ret = -EINVAL;
- if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
- break;
-
- iocaps_double_lock(d, true);
-
- if ( !iomem_access_permitted(current->domain,
- mfn, mfn + nr_mfns - 1) ||
- xsm_iomem_permission(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, allow) )
- ret = -EPERM;
- else if ( allow )
- ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
- else
- ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
-
- iocaps_double_unlock(d, true);
- break;
- }
-
case XEN_DOMCTL_settimeoffset:
domain_set_time_offset(d, op->u.settimeoffset.time_offset_seconds);
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -170,7 +170,9 @@ static XSM_INLINE int cf_check xsm_domct
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_iomem_permission:
case XEN_DOMCTL_ioport_mapping:
+ case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
@@ -567,7 +569,7 @@ static XSM_INLINE int cf_check xsm_irq_p
static XSM_INLINE int cf_check xsm_iomem_permission(
XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
@@ -763,7 +765,7 @@ static XSM_INLINE int cf_check xsm_priv_
static XSM_INLINE int cf_check xsm_ioport_permission(
XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -686,7 +686,9 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_iomem_permission:
case XEN_DOMCTL_ioport_mapping:
+ case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
@@ -695,14 +697,12 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks (common/domctl.c) */
case XEN_DOMCTL_scheduler_op:
case XEN_DOMCTL_irq_permission:
- case XEN_DOMCTL_iomem_permission:
case XEN_DOMCTL_set_target:
case XEN_DOMCTL_vm_event_op:
#ifdef CONFIG_X86
/* These have individual XSM hooks (arch/x86/domctl.c) */
case XEN_DOMCTL_shadow_op:
- case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_gsi_permission:
#endif
#ifdef CONFIG_HAS_PASSTHROUGH

View file

@ -1,163 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_{irq,gsi}_permission without acquiring domctl lock
With dedicated locking added, the domctl lock isn't required here anymore.
As the GSI handling is in arch-specific code (x86 only), no code is being
moved there; the 2nd invocation of arch_do_domctl() is re-used. Move the
re-purposed (XSM_HOOK -> XSM_PRIV, as xsm_domctl() is now bypassed)
dedicated XSM checks as early as possible.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -272,10 +272,13 @@ long arch_do_domctl(
break;
}
+ ret = xsm_irq_permission(XSM_PRIV, d, irq, flags);
+ if ( ret )
+ break;
+
iocaps_double_lock(d, true);
- if ( !irq_access_permitted(currd, irq) ||
- xsm_irq_permission(XSM_HOOK, d, irq, flags) )
+ if ( !irq_access_permitted(currd, irq) )
ret = -EPERM;
else if ( flags )
ret = irq_permit_access(d, irq);
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -464,8 +464,41 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
goto domctl_out_unlock_domonly;
}
+#ifdef CONFIG_HAS_PIRQ
+ case XEN_DOMCTL_irq_permission:
+ {
+ unsigned int pirq = op->u.irq_permission.pirq, irq;
+ bool allow = op->u.irq_permission.allow_access;
+
+ ret = -EINVAL;
+ if ( pirq >= current->domain->nr_pirqs )
+ goto domctl_out_unlock_domonly;
+
+ irq = domain_pirq_to_irq(current->domain, pirq);
+
+ ret = -EPERM;
+ if ( irq )
+ ret = xsm_irq_permission(XSM_PRIV, d, irq, allow);
+ if ( ret )
+ goto domctl_out_unlock_domonly;
+
+ iocaps_double_lock(d, true);
+
+ if ( !irq_access_permitted(current->domain, irq) )
+ ret = -EPERM;
+ else if ( allow )
+ ret = irq_permit_access(d, irq);
+ else
+ ret = irq_deny_access(d, irq);
+
+ iocaps_double_unlock(d, true);
+ goto domctl_out_unlock_domonly;
+ }
+#endif
+
case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_ioport_mapping:
+ case XEN_DOMCTL_gsi_permission:
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_unbind_pt_irq:
ret = arch_do_domctl(op, d, u_domctl);
@@ -779,33 +812,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
}
break;
-#ifdef CONFIG_HAS_PIRQ
- case XEN_DOMCTL_irq_permission:
- {
- unsigned int pirq = op->u.irq_permission.pirq, irq;
- int allow = op->u.irq_permission.allow_access;
-
- if ( pirq >= current->domain->nr_pirqs )
- {
- ret = -EINVAL;
- break;
- }
-
- iocaps_double_lock(d, true);
-
- irq = pirq_access_permitted(current->domain, pirq);
- if ( !irq || xsm_irq_permission(XSM_HOOK, d, irq, allow) )
- ret = -EPERM;
- else if ( allow )
- ret = irq_permit_access(d, irq);
- else
- ret = irq_deny_access(d, irq);
-
- iocaps_double_unlock(d, true);
- break;
- }
-#endif
-
case XEN_DOMCTL_settimeoffset:
domain_set_time_offset(d, op->u.settimeoffset.time_offset_seconds);
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -170,9 +170,11 @@ static XSM_INLINE int cf_check xsm_domct
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_gsi_permission:
case XEN_DOMCTL_iomem_permission:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_ioport_permission:
+ case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
@@ -562,7 +564,7 @@ static XSM_INLINE int cf_check xsm_unmap
static XSM_INLINE int cf_check xsm_irq_permission(
XSM_DEFAULT_ARG struct domain *d, int pirq, uint8_t allow)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -686,9 +686,11 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
case XEN_DOMCTL_get_domain_state:
+ case XEN_DOMCTL_gsi_permission:
case XEN_DOMCTL_iomem_permission:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_ioport_permission:
+ case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_memory_mapping:
case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
@@ -696,14 +698,12 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks (common/domctl.c) */
case XEN_DOMCTL_scheduler_op:
- case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_set_target:
case XEN_DOMCTL_vm_event_op:
#ifdef CONFIG_X86
/* These have individual XSM hooks (arch/x86/domctl.c) */
case XEN_DOMCTL_shadow_op:
- case XEN_DOMCTL_gsi_permission:
#endif
#ifdef CONFIG_HAS_PASSTHROUGH
/*

View file

@ -1,179 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl/XSM: drop vm_event_control hook
Integrate the checking with xsm_domctl(). Care needs to be taken with the
GET_VERSION sub-op, which may be invoked with DOMID_INVALID, and which has
been (and continues to be) bypassing XSM checking.
Since the latter two parameters were unused, monitor_domctl() invoking the
hook was actually redundant with the earlier xsm_domctl() (as can be seen
nicely from the hunks changing xsm/flask/hooks.c).
As a positive side effect, permissions are then checked at the same early
point with and without Flask.
While folding XEN_DOMCTL_monitor_op and XEN_DOMCTL_vm_event_op in
flask_domctl(), also fold in XEN_DOMCTL_set_access_required.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -496,6 +496,23 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
}
#endif
+ case XEN_DOMCTL_vm_event_op:
+ if ( op->u.vm_event_op.op == XEN_VM_EVENT_GET_VERSION )
+ {
+ /* No XSM check (and potentially d == NULL) here. */
+ ret = vm_event_domctl(d, &op->u.vm_event_op);
+ if ( !ret )
+ copyback = true;
+ goto domctl_out_unlock_domonly;
+ }
+ if ( !d )
+ {
+ ret = -ESRCH;
+ goto domctl_out_unlock_domonly;
+ }
+ /* Other sub-ops handled further down. */
+ break;
+
case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_gsi_permission:
--- a/xen/common/monitor.c
+++ b/xen/common/monitor.c
@@ -30,16 +30,11 @@
int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *mop)
{
- int rc;
bool requested_status = false;
if ( unlikely(current->domain == d) ) /* no domain_pause() */
return -EPERM;
- rc = xsm_vm_event_control(XSM_PRIV, d, mop->op, mop->event);
- if ( unlikely(rc) )
- return rc;
-
switch ( mop->op )
{
case XEN_DOMCTL_MONITOR_OP_ENABLE:
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -603,11 +603,10 @@ int vm_event_domctl(struct domain *d, st
/* All other subops need to target a real domain. */
if ( unlikely(d == NULL) )
- return -ESRCH;
-
- rc = xsm_vm_event_control(XSM_PRIV, d, vec->mode, vec->op);
- if ( rc )
- return rc;
+ {
+ ASSERT_UNREACHABLE();
+ return -EILSEQ;
+ }
if ( unlikely(d == current->domain) ) /* no domain_pause() */
{
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -652,13 +652,6 @@ static XSM_INLINE int cf_check xsm_hvm_a
}
}
-static XSM_INLINE int cf_check xsm_vm_event_control(
- XSM_DEFAULT_ARG struct domain *d, int mode, int op)
-{
- XSM_ASSERT_ACTION(XSM_PRIV);
- return xsm_default_action(action, current->domain, d);
-}
-
#ifdef CONFIG_VM_EVENT
static XSM_INLINE int cf_check xsm_mem_access(XSM_DEFAULT_ARG struct domain *d)
{
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -157,8 +157,6 @@ struct xsm_ops {
int (*hvm_altp2mhvm_op)(struct domain *d, uint64_t mode, uint32_t op);
int (*get_vnumainfo)(struct domain *d);
- int (*vm_event_control)(struct domain *d, int mode, int op);
-
#ifdef CONFIG_VM_EVENT
int (*mem_access)(struct domain *d);
#endif
@@ -657,12 +655,6 @@ static inline int xsm_get_vnumainfo(xsm_
return alternative_call(xsm_ops.get_vnumainfo, d);
}
-static inline int xsm_vm_event_control(
- xsm_default_t def, struct domain *d, int mode, int op)
-{
- return alternative_call(xsm_ops.vm_event_control, d, mode, op);
-}
-
#ifdef CONFIG_VM_EVENT
static inline int xsm_mem_access(xsm_default_t def, struct domain *d)
{
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -116,8 +116,6 @@ static const struct xsm_ops __initconst_
.remove_from_physmap = xsm_remove_from_physmap,
.map_gmfn_foreign = xsm_map_gmfn_foreign,
- .vm_event_control = xsm_vm_event_control,
-
#ifdef CONFIG_VM_EVENT
.mem_access = xsm_mem_access,
#endif
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -699,7 +699,6 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks (common/domctl.c) */
case XEN_DOMCTL_scheduler_op:
case XEN_DOMCTL_set_target:
- case XEN_DOMCTL_vm_event_op:
#ifdef CONFIG_X86
/* These have individual XSM hooks (arch/x86/domctl.c) */
@@ -793,9 +792,8 @@ static int cf_check flask_domctl(struct
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__TRIGGER);
case XEN_DOMCTL_set_access_required:
- return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__VM_EVENT);
-
case XEN_DOMCTL_monitor_op:
+ case XEN_DOMCTL_vm_event_op:
return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__VM_EVENT);
case XEN_DOMCTL_debug_op:
@@ -1368,11 +1366,6 @@ static int cf_check flask_hvm_altp2mhvm_
return current_has_perm(d, SECCLASS_HVM, HVM__ALTP2MHVM_OP);
}
-static int cf_check flask_vm_event_control(struct domain *d, int mode, int op)
-{
- return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__VM_EVENT);
-}
-
#ifdef CONFIG_VM_EVENT
static int cf_check flask_mem_access(struct domain *d)
{
@@ -1971,8 +1964,6 @@ static const struct xsm_ops __initconst_
.do_xsm_op = do_flask_op,
.get_vnumainfo = flask_get_vnumainfo,
- .vm_event_control = flask_vm_event_control,
-
#ifdef CONFIG_VM_EVENT
.mem_access = flask_mem_access,
#endif

View file

@ -1,108 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl/XSM: pass full struct xen_domctl to xsm_domctl()
Subsequently some sub-ops will want to inspect their sub-sub-ops. Plus
this way we don't need to pass SSIDref separately anymore for
domain_create.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -735,7 +735,7 @@ long do_paging_domctl_cont(
if ( d == NULL )
return -ESRCH;
- ret = xsm_domctl(XSM_OTHER, d, op.cmd, 0 /* SSIDref not applicable */);
+ ret = xsm_domctl(XSM_OTHER, d, &op);
if ( !ret )
{
if ( domctl_lock_acquire() )
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -526,9 +526,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
break;
}
- ret = xsm_domctl(XSM_OTHER, d, op->cmd,
- /* SSIDRef only applicable for cmd == createdomain */
- op->u.createdomain.ssidref);
+ ret = xsm_domctl(XSM_OTHER, d, op);
if ( ret )
goto domctl_out_unlock_domonly;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -162,10 +162,10 @@ static XSM_INLINE int cf_check xsm_set_t
}
static XSM_INLINE int cf_check xsm_domctl(
- XSM_DEFAULT_ARG struct domain *d, unsigned int cmd, uint32_t ssidref)
+ XSM_DEFAULT_ARG struct domain *d, struct xen_domctl *op)
{
XSM_ASSERT_ACTION(XSM_OTHER);
- switch ( cmd )
+ switch ( op->cmd )
{
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -61,7 +61,7 @@ struct xsm_ops {
int (*sysctl_scheduler_op)(int op);
#endif
int (*set_target)(struct domain *d, struct domain *e);
- int (*domctl)(struct domain *d, unsigned int cmd, uint32_t ssidref);
+ int (*domctl)(struct domain *d, struct xen_domctl *op);
int (*sysctl)(int cmd);
int (*readconsole)(uint32_t clear);
@@ -260,9 +260,9 @@ static inline int xsm_set_target(
}
static inline int xsm_domctl(xsm_default_t def, struct domain *d,
- unsigned int cmd, uint32_t ssidref)
+ struct xen_domctl *op)
{
- return alternative_call(xsm_ops.domctl, d, cmd, ssidref);
+ return alternative_call(xsm_ops.domctl, d, op);
}
static inline int xsm_sysctl(xsm_default_t def, int cmd)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -667,10 +667,9 @@ static int cf_check flask_set_target(str
return rc;
}
-static int cf_check flask_domctl(struct domain *d, unsigned int cmd,
- uint32_t ssidref)
+static int cf_check flask_domctl(struct domain *d, struct xen_domctl *op)
{
- switch ( cmd )
+ switch ( op->cmd )
{
case XEN_DOMCTL_createdomain:
/*
@@ -680,7 +679,8 @@ static int cf_check flask_domctl(struct
* Note that d is NULL because we haven't even allocated memory for it
* this early in XEN_DOMCTL_createdomain.
*/
- return avc_current_has_perm(ssidref, SECCLASS_DOMAIN, DOMAIN__CREATE, NULL);
+ return avc_current_has_perm(op->u.createdomain.ssidref, SECCLASS_DOMAIN,
+ DOMAIN__CREATE, NULL);
/* These have individual XSM hooks and don't make it here. */
case XEN_DOMCTL_bind_pt_irq:
@@ -855,7 +855,7 @@ static int cf_check flask_domctl(struct
return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_LLC_COLORS);
default:
- return avc_unknown_permission("domctl", cmd);
+ return avc_unknown_permission("domctl", op->cmd);
}
}

View file

@ -1,112 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl/XSM: drop scheduler_op hook
Integrate the checking with xsm_domctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -2074,10 +2074,6 @@ long sched_adjust(struct domain *d, stru
{
long ret;
- ret = xsm_domctl_scheduler_op(XSM_HOOK, d, op->cmd);
- if ( ret )
- return ret;
-
if ( op->sched_id != dom_scheduler(d)->sched_id )
return -EINVAL;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -141,13 +141,6 @@ static XSM_INLINE int cf_check xsm_getdo
return xsm_default_action(action, current->domain, d);
}
-static XSM_INLINE int cf_check xsm_domctl_scheduler_op(
- XSM_DEFAULT_ARG struct domain *d, int cmd)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
static XSM_INLINE int cf_check xsm_sysctl_scheduler_op(XSM_DEFAULT_ARG int cmd)
{
XSM_ASSERT_ACTION(XSM_HOOK);
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -56,7 +56,6 @@ struct xsm_ops {
struct xen_domctl_getdomaininfo *info);
int (*domain_create)(struct domain *d, uint32_t ssidref);
int (*getdomaininfo)(struct domain *d);
- int (*domctl_scheduler_op)(struct domain *d, int op);
#ifdef CONFIG_SYSCTL
int (*sysctl_scheduler_op)(int op);
#endif
@@ -240,12 +239,6 @@ static inline int xsm_get_domain_state(x
return alternative_call(xsm_ops.get_domain_state, d);
}
-static inline int xsm_domctl_scheduler_op(
- xsm_default_t def, struct domain *d, int cmd)
-{
- return alternative_call(xsm_ops.domctl_scheduler_op, d, cmd);
-}
-
#ifdef CONFIG_SYSCTL
static inline int xsm_sysctl_scheduler_op(xsm_default_t def, int cmd)
{
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -18,7 +18,6 @@ static const struct xsm_ops __initconst_
.security_domaininfo = xsm_security_domaininfo,
.domain_create = xsm_domain_create,
.getdomaininfo = xsm_getdomaininfo,
- .domctl_scheduler_op = xsm_domctl_scheduler_op,
#ifdef CONFIG_SYSCTL
.sysctl_scheduler_op = xsm_sysctl_scheduler_op,
#endif
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -609,7 +609,7 @@ static int cf_check flask_getdomaininfo(
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETDOMAININFO);
}
-static int cf_check flask_domctl_scheduler_op(struct domain *d, int op)
+static int flask_domctl_scheduler_op(struct domain *d, int op)
{
switch ( op )
{
@@ -697,7 +697,6 @@ static int cf_check flask_domctl(struct
return -EILSEQ;
/* These have individual XSM hooks (common/domctl.c) */
- case XEN_DOMCTL_scheduler_op:
case XEN_DOMCTL_set_target:
#ifdef CONFIG_X86
@@ -745,6 +744,9 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_setdomainhandle:
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETDOMAINHANDLE);
+ case XEN_DOMCTL_scheduler_op:
+ return flask_domctl_scheduler_op(d, op->u.scheduler_op.cmd);
+
case XEN_DOMCTL_set_ext_vcpucontext:
case XEN_DOMCTL_set_vcpu_msrs:
case XEN_DOMCTL_setvcpucontext:
@@ -1884,7 +1886,6 @@ static const struct xsm_ops __initconst_
.security_domaininfo = flask_security_domaininfo,
.domain_create = flask_domain_create,
.getdomaininfo = flask_getdomaininfo,
- .domctl_scheduler_op = flask_domctl_scheduler_op,
#ifdef CONFIG_SYSCTL
.sysctl_scheduler_op = flask_sysctl_scheduler_op,
#endif

View file

@ -1,124 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl/XSM: drop shadow_control_op hook
Integrate the checking with xsm_domctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -677,10 +677,6 @@ int paging_domctl(struct domain *d, stru
return -EBUSY;
}
- rc = xsm_shadow_control(XSM_HOOK, d, sc->op);
- if ( rc )
- return rc;
-
/* Code to handle log-dirty. Note that some log dirty operations
* piggy-back on shadow operations. For example, when
* XEN_DOMCTL_SHADOW_OP_OFF is called, it first checks whether log dirty
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -682,13 +682,6 @@ static XSM_INLINE int cf_check xsm_do_mc
return xsm_default_action(action, current->domain, NULL);
}
-static XSM_INLINE int cf_check xsm_shadow_control(
- XSM_DEFAULT_ARG struct domain *d, uint32_t op)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
static XSM_INLINE int cf_check xsm_mem_sharing_op(
XSM_DEFAULT_ARG struct domain *d, struct domain *cd, int op)
{
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -172,7 +172,6 @@ struct xsm_ops {
#ifdef CONFIG_X86
int (*do_mca)(void);
- int (*shadow_control)(struct domain *d, uint32_t op);
int (*mem_sharing_op)(struct domain *d, struct domain *cd, int op);
int (*apic)(struct domain *d, int cmd);
int (*machine_memory_map)(void);
@@ -680,12 +679,6 @@ static inline int xsm_do_mca(xsm_default
return alternative_call(xsm_ops.do_mca);
}
-static inline int xsm_shadow_control(
- xsm_default_t def, struct domain *d, uint32_t op)
-{
- return alternative_call(xsm_ops.shadow_control, d, op);
-}
-
static inline int xsm_mem_sharing_op(
xsm_default_t def, struct domain *d, struct domain *cd, int op)
{
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -130,7 +130,6 @@ static const struct xsm_ops __initconst_
.platform_op = xsm_platform_op,
#ifdef CONFIG_X86
.do_mca = xsm_do_mca,
- .shadow_control = xsm_shadow_control,
.mem_sharing_op = xsm_mem_sharing_op,
.apic = xsm_apic,
.machine_memory_map = xsm_machine_memory_map,
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -40,6 +40,7 @@
#ifdef CONFIG_X86
#include <asm/pv/shim.h>
+static int flask_shadow_control(struct domain *d, unsigned int op);
#else
#define pv_shim false
#endif
@@ -699,10 +700,6 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks (common/domctl.c) */
case XEN_DOMCTL_set_target:
-#ifdef CONFIG_X86
- /* These have individual XSM hooks (arch/x86/domctl.c) */
- case XEN_DOMCTL_shadow_op:
-#endif
#ifdef CONFIG_HAS_PASSTHROUGH
/*
* These have individual XSM hooks
@@ -787,6 +784,11 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_get_address_size:
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETADDRSIZE);
+#ifdef CONFIG_X86
+ case XEN_DOMCTL_shadow_op:
+ return flask_shadow_control(d, op->u.shadow_op.op);
+#endif
+
case XEN_DOMCTL_mem_sharing_op:
return current_has_perm(d, SECCLASS_HVM, HVM__MEM_SHARING);
@@ -1603,7 +1605,7 @@ static int cf_check flask_do_mca(void)
return domain_has_xen(current->domain, XEN__MCA_OP);
}
-static int cf_check flask_shadow_control(struct domain *d, uint32_t op)
+static int flask_shadow_control(struct domain *d, unsigned int op)
{
uint32_t perm;
@@ -1999,7 +2001,6 @@ static const struct xsm_ops __initconst_
.platform_op = flask_platform_op,
#ifdef CONFIG_X86
.do_mca = flask_do_mca,
- .shadow_control = flask_shadow_control,
.mem_sharing_op = flask_mem_sharing_op,
.apic = flask_apic,
.machine_memory_map = flask_machine_memory_map,

View file

@ -1,94 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_get_device_group without acquiring domctl lock
iommu_get_device_group() uses its own locking. Thus, with caller side
locking irrelevant, it can as well be called with the domctl lock not
held.
Move the handling not only ahead of acquiring the lock, but also ahead
of the XSM check, leveraging that the sub-op has its own hook.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -513,6 +513,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
/* Other sub-ops handled further down. */
break;
+ case XEN_DOMCTL_get_device_group:
+ ret = iommu_do_domctl(op, d, u_domctl);
+ goto domctl_out_unlock_domonly;
+
case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_ioport_mapping:
case XEN_DOMCTL_gsi_permission:
@@ -918,7 +922,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
case XEN_DOMCTL_assign_device:
case XEN_DOMCTL_test_assign_device:
case XEN_DOMCTL_deassign_device:
- case XEN_DOMCTL_get_device_group:
ret = iommu_do_domctl(op, d, u_domctl);
break;
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1620,7 +1620,7 @@ static int iommu_get_device_group(
if ( (pdev->seg != seg) || ((b == bus) && (df == devfn)) )
continue;
- if ( xsm_get_device_group(XSM_HOOK, (seg << 16) | (b << 8) | df) )
+ if ( xsm_get_device_group(XSM_PRIV, (seg << 16) | (b << 8) | df) )
continue;
sdev_id = iommu_call(ops, get_device_group_id, seg, b, df);
@@ -1690,7 +1690,7 @@ int iommu_do_pci_domctl(
u32 max_sdevs;
XEN_GUEST_HANDLE_64(uint32) sdevs;
- ret = xsm_get_device_group(XSM_HOOK, domctl->u.get_device_group.machine_sbdf);
+ ret = xsm_get_device_group(XSM_PRIV, domctl->u.get_device_group.machine_sbdf);
if ( ret )
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -162,6 +162,7 @@ static XSM_INLINE int cf_check xsm_domct
{
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
+ case XEN_DOMCTL_get_device_group:
case XEN_DOMCTL_get_domain_state:
case XEN_DOMCTL_gsi_permission:
case XEN_DOMCTL_iomem_permission:
@@ -401,7 +402,7 @@ static XSM_INLINE int cf_check xsm_get_v
static XSM_INLINE int cf_check xsm_get_device_group(
XSM_DEFAULT_ARG uint32_t machine_bdf)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -686,6 +686,7 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks and don't make it here. */
case XEN_DOMCTL_bind_pt_irq:
case XEN_DOMCTL_getdomaininfo:
+ case XEN_DOMCTL_get_device_group:
case XEN_DOMCTL_get_domain_state:
case XEN_DOMCTL_gsi_permission:
case XEN_DOMCTL_iomem_permission:
@@ -705,7 +706,6 @@ static int cf_check flask_domctl(struct
* These have individual XSM hooks
* (drivers/passthrough/{pci,device_tree.c)
*/
- case XEN_DOMCTL_get_device_group:
case XEN_DOMCTL_test_assign_device:
case XEN_DOMCTL_assign_device:
case XEN_DOMCTL_deassign_device:

View file

@ -1,378 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl/XSM: drop {,de}assign_{,dt}device hooks
Integrate the checking with xsm_domctl(). As a positive side effect,
permissions are then checked at the same early point with and without
Flask. As the DT device path needs fetching earlier (but must not be
double fetched), cache it in a private field of the public interface
struct.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -325,6 +325,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
case XEN_DOMCTL_deassign_device:
if ( op->domain == DOMID_IO )
{
+#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY
+ if ( op->u.assign_device.dev == XEN_DOMCTL_DEV_DT )
+ op->u.assign_device.u.dt.dev = NULL;
+#endif
d = dom_io;
break;
}
@@ -332,6 +336,11 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
return -ESRCH;
fallthrough;
case XEN_DOMCTL_test_assign_device:
+#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY
+ if ( op->u.assign_device.dev == XEN_DOMCTL_DEV_DT )
+ op->u.assign_device.u.dt.dev = NULL;
+ fallthrough;
+#endif
case XEN_DOMCTL_vm_event_op:
if ( op->domain == DOMID_INVALID )
{
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -340,15 +340,15 @@ int iommu_do_dt_domctl(struct xen_domctl
if ( (d && d->is_dying) || domctl->u.assign_device.flags )
break;
- ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
- domctl->u.assign_device.u.dt.size,
- &dev);
- if ( ret )
- break;
-
- ret = xsm_assign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev));
- if ( ret )
- break;
+ dev = domctl->u.assign_device.u.dt.dev;
+ if ( !dev )
+ {
+ ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
+ domctl->u.assign_device.u.dt.size,
+ &dev);
+ if ( ret )
+ break;
+ }
if ( domctl->cmd == XEN_DOMCTL_test_assign_device )
{
@@ -396,15 +396,15 @@ int iommu_do_dt_domctl(struct xen_domctl
if ( domctl->u.assign_device.flags )
break;
- ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
- domctl->u.assign_device.u.dt.size,
- &dev);
- if ( ret )
- break;
-
- ret = xsm_deassign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev));
- if ( ret )
- break;
+ dev = domctl->u.assign_device.u.dt.dev;
+ if ( !dev )
+ {
+ ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
+ domctl->u.assign_device.u.dt.size,
+ &dev);
+ if ( ret )
+ break;
+ }
if ( d == dom_io )
{
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1740,10 +1740,6 @@ int iommu_do_pci_domctl(
machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
- ret = xsm_assign_device(XSM_HOOK, d, machine_sbdf);
- if ( ret )
- break;
-
seg = machine_sbdf >> 16;
bus = PCI_BUS(machine_sbdf);
devfn = PCI_DEVFN(machine_sbdf);
@@ -1785,10 +1781,6 @@ int iommu_do_pci_domctl(
machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
- ret = xsm_deassign_device(XSM_HOOK, d, machine_sbdf);
- if ( ret )
- break;
-
seg = machine_sbdf >> 16;
bus = PCI_BUS(machine_sbdf);
devfn = PCI_DEVFN(machine_sbdf);
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -575,7 +575,10 @@ struct xen_domctl_assign_device {
} pci;
struct {
uint32_t size; /* Length of the path */
- XEN_GUEST_HANDLE_64(char) path; /* path to the device tree node */
+ XEN_GUEST_HANDLE_64(char) path; /* Path to the device tree node */
+#ifdef __XEN__
+ struct dt_device_node *dev; /* Resolved device node of the above */
+#endif
} dt;
} u;
};
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -405,40 +405,8 @@ static XSM_INLINE int cf_check xsm_get_d
XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
-
-static XSM_INLINE int cf_check xsm_assign_device(
- XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int cf_check xsm_deassign_device(
- XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
#endif /* HAS_PASSTHROUGH && HAS_PCI */
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
-static XSM_INLINE int cf_check xsm_assign_dtdevice(
- XSM_DEFAULT_ARG struct domain *d, const char *dtpath)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int cf_check xsm_deassign_dtdevice(
- XSM_DEFAULT_ARG struct domain *d, const char *dtpath)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
-#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE_DISCOVERY */
-
static XSM_INLINE int cf_check xsm_resource_plug_core(XSM_DEFAULT_VOID)
{
XSM_ASSERT_ACTION(XSM_HOOK);
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -124,13 +124,6 @@ struct xsm_ops {
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
int (*get_device_group)(uint32_t machine_bdf);
- int (*assign_device)(struct domain *d, uint32_t machine_bdf);
- int (*deassign_device)(struct domain *d, uint32_t machine_bdf);
-#endif
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
- int (*assign_dtdevice)(struct domain *d, const char *dtpath);
- int (*deassign_dtdevice)(struct domain *d, const char *dtpath);
#endif
int (*resource_plug_core)(void);
@@ -533,35 +526,8 @@ static inline int xsm_get_device_group(x
{
return alternative_call(xsm_ops.get_device_group, machine_bdf);
}
-
-static inline int xsm_assign_device(
- xsm_default_t def, struct domain *d, uint32_t machine_bdf)
-{
- return alternative_call(xsm_ops.assign_device, d, machine_bdf);
-}
-
-static inline int xsm_deassign_device(
- xsm_default_t def, struct domain *d, uint32_t machine_bdf)
-{
- return alternative_call(xsm_ops.deassign_device, d, machine_bdf);
-}
#endif /* HAS_PASSTHROUGH && HAS_PCI) */
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
-static inline int xsm_assign_dtdevice(
- xsm_default_t def, struct domain *d, const char *dtpath)
-{
- return alternative_call(xsm_ops.assign_dtdevice, d, dtpath);
-}
-
-static inline int xsm_deassign_dtdevice(
- xsm_default_t def, struct domain *d, const char *dtpath)
-{
- return alternative_call(xsm_ops.deassign_dtdevice, d, dtpath);
-}
-
-#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE_DISCOVERY */
-
static inline int xsm_resource_plug_pci(xsm_default_t def, uint32_t machine_bdf)
{
return alternative_call(xsm_ops.resource_plug_pci, machine_bdf);
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -81,13 +81,6 @@ static const struct xsm_ops __initconst_
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
.get_device_group = xsm_get_device_group,
- .assign_device = xsm_assign_device,
- .deassign_device = xsm_deassign_device,
-#endif
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
- .assign_dtdevice = xsm_assign_dtdevice,
- .deassign_dtdevice = xsm_deassign_dtdevice,
#endif
.resource_plug_core = xsm_resource_plug_core,
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -45,6 +45,17 @@ static int flask_shadow_control(struct d
#define pv_shim false
#endif
+#ifdef CONFIG_HAS_PASSTHROUGH
+#ifdef CONFIG_HAS_PCI
+static int flask_assign_device(struct domain *d, unsigned int machine_bdf);
+static int flask_deassign_device(struct domain *d, unsigned int machine_bdf);
+#endif
+#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY
+static int flask_assign_dtdevice(struct domain *d, const char *dtpath);
+static int flask_deassign_dtdevice(struct domain *d, const char *dtpath);
+#endif
+#endif /* CONFIG_HAS_PASSTHROUGH */
+
static uint32_t domain_sid(const struct domain *dom)
{
struct domain_security_struct *dsec = dom->ssid;
@@ -700,16 +711,6 @@ static int cf_check flask_domctl(struct
/* These have individual XSM hooks (common/domctl.c) */
case XEN_DOMCTL_set_target:
-
-#ifdef CONFIG_HAS_PASSTHROUGH
- /*
- * These have individual XSM hooks
- * (drivers/passthrough/{pci,device_tree.c)
- */
- case XEN_DOMCTL_test_assign_device:
- case XEN_DOMCTL_assign_device:
- case XEN_DOMCTL_deassign_device:
-#endif
return 0;
case XEN_DOMCTL_destroydomain:
@@ -789,6 +790,49 @@ static int cf_check flask_domctl(struct
return flask_shadow_control(d, op->u.shadow_op.op);
#endif
+#ifdef CONFIG_HAS_PASSTHROUGH
+
+ case XEN_DOMCTL_test_assign_device:
+ case XEN_DOMCTL_assign_device:
+ case XEN_DOMCTL_deassign_device:
+ switch ( op->u.assign_device.dev )
+ {
+#ifdef CONFIG_HAS_PCI
+ case XEN_DOMCTL_DEV_PCI:
+ return op->cmd != XEN_DOMCTL_deassign_device
+ ? flask_assign_device(
+ d, op->u.assign_device.u.pci.machine_sbdf)
+ : flask_deassign_device(
+ d, op->u.assign_device.u.pci.machine_sbdf);
+#endif
+
+#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY
+ case XEN_DOMCTL_DEV_DT:
+ {
+ struct dt_device_node *dev;
+ int ret = dt_find_node_by_gpath(op->u.assign_device.u.dt.path,
+ op->u.assign_device.u.dt.size,
+ &dev);
+
+ if ( ret )
+ return ret;
+
+ op->u.assign_device.u.dt.dev = dev;
+
+ return op->cmd != XEN_DOMCTL_deassign_device
+ ? flask_assign_dtdevice(d, dt_node_full_name(dev))
+ : flask_deassign_dtdevice(d, dt_node_full_name(dev));
+ }
+#endif
+
+ default:
+ /* Unknown type. */
+ break;
+ }
+ return avc_unknown_permission("assign_device", op->cmd);
+
+#endif /* CONFIG_HAS_PASSTHROUGH */
+
case XEN_DOMCTL_mem_sharing_op:
return current_has_perm(d, SECCLASS_HVM, HVM__MEM_SHARING);
@@ -1416,7 +1460,7 @@ static int flask_test_assign_device(uint
return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL);
}
-static int cf_check flask_assign_device(struct domain *d, uint32_t machine_bdf)
+static int flask_assign_device(struct domain *d, uint32_t machine_bdf)
{
uint32_t dsid, rsid;
int rc = -EPERM;
@@ -1446,7 +1490,7 @@ static int cf_check flask_assign_device(
return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
}
-static int cf_check flask_deassign_device(
+static int flask_deassign_device(
struct domain *d, uint32_t machine_bdf)
{
uint32_t rsid;
@@ -1478,7 +1522,7 @@ static int flask_test_assign_dtdevice(co
NULL);
}
-static int cf_check flask_assign_dtdevice(struct domain *d, const char *dtpath)
+static int flask_assign_dtdevice(struct domain *d, const char *dtpath)
{
uint32_t dsid, rsid;
int rc = -EPERM;
@@ -1508,7 +1552,7 @@ static int cf_check flask_assign_dtdevic
return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
}
-static int cf_check flask_deassign_dtdevice(
+static int flask_deassign_dtdevice(
struct domain *d, const char *dtpath)
{
uint32_t rsid;
@@ -1989,13 +2033,6 @@ static const struct xsm_ops __initconst_
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
.get_device_group = flask_get_device_group,
- .assign_device = flask_assign_device,
- .deassign_device = flask_deassign_device,
-#endif
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
- .assign_dtdevice = flask_assign_dtdevice,
- .deassign_dtdevice = flask_deassign_dtdevice,
#endif
.platform_op = flask_platform_op,

View file

@ -1,123 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: domctl: handle XEN_DOMCTL_set_target without acquiring domctl lock
The only locking required here is that between checking d->target and
setting it. To avoid the need for an explicit lock, use cmpxchgptr() to
update d->target.
Move the handling not only ahead of acquiring the lock, but also ahead
of the XSM check, leveraging that the sub-op has its own hook.
This is part of XSA-492.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -505,6 +505,30 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
}
#endif
+ case XEN_DOMCTL_set_target:
+ {
+ struct domain *e = get_domain_by_id(op->u.set_target.target);
+
+ ret = -ESRCH;
+ if ( !e )
+ goto domctl_out_unlock_domonly;
+
+ if ( d == e )
+ ret = -EINVAL;
+ else if ( !is_hvm_domain(e) )
+ ret = -EOPNOTSUPP;
+ else
+ ret = xsm_set_target(XSM_PRIV, d, e);
+
+ /* Hold reference on @e until we destroy @d. */
+ if ( !ret && cmpxchgptr(&d->target, NULL, e) )
+ ret = -EINVAL;
+
+ if ( ret )
+ put_domain(e);
+ goto domctl_out_unlock_domonly;
+ }
+
case XEN_DOMCTL_vm_event_op:
if ( op->u.vm_event_op.op == XEN_VM_EVENT_GET_VERSION )
{
@@ -844,36 +868,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe
domain_set_time_offset(d, op->u.settimeoffset.time_offset_seconds);
break;
- case XEN_DOMCTL_set_target:
- {
- struct domain *e;
-
- ret = -ESRCH;
- e = get_domain_by_id(op->u.set_target.target);
- if ( e == NULL )
- break;
-
- ret = -EINVAL;
- if ( (d == e) || (d->target != NULL) )
- {
- put_domain(e);
- break;
- }
-
- ret = -EOPNOTSUPP;
- if ( is_hvm_domain(e) )
- ret = xsm_set_target(XSM_HOOK, d, e);
- if ( ret )
- {
- put_domain(e);
- break;
- }
-
- /* Hold reference on @e until we destroy @d. */
- d->target = e;
- break;
- }
-
case XEN_DOMCTL_subscribe:
d->suspend_evtchn = op->u.subscribe.port;
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -150,7 +150,7 @@ static XSM_INLINE int cf_check xsm_sysct
static XSM_INLINE int cf_check xsm_set_target(
XSM_DEFAULT_ARG struct domain *d, struct domain *e)
{
- XSM_ASSERT_ACTION(XSM_HOOK);
+ XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
@@ -170,6 +170,7 @@ static XSM_INLINE int cf_check xsm_domct
case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_memory_mapping:
+ case XEN_DOMCTL_set_target:
case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
return -EILSEQ;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -705,14 +705,11 @@ static int cf_check flask_domctl(struct
case XEN_DOMCTL_ioport_permission:
case XEN_DOMCTL_irq_permission:
case XEN_DOMCTL_memory_mapping:
+ case XEN_DOMCTL_set_target:
case XEN_DOMCTL_unbind_pt_irq:
ASSERT_UNREACHABLE();
return -EILSEQ;
- /* These have individual XSM hooks (common/domctl.c) */
- case XEN_DOMCTL_set_target:
- return 0;
-
case XEN_DOMCTL_destroydomain:
return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__DESTROY);

View file

@ -1,311 +0,0 @@
From 2e21b5301765de353c06081eee953255bf327176 Mon Sep 17 00:00:00 2001
From: Michal Orzel <michal.orzel@amd.com>
Date: Tue, 14 Apr 2026 10:11:24 +0200
Subject: xen/arm64: flushtlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI
The ARM64_WORKAROUND_REPEAT_TLBI workaround is used to mitigate several
errata where broadcast TLBI;DSB sequences don't provide all the
architecturally required synchronization. The workaround performs more
work than necessary, and can have significant overhead. This patch
optimizes the workaround, as explained below.
1. All relevant errata only affect the ordering and/or completion of
memory accesses which have been translated by an invalidated TLB
entry. The actual invalidation of TLB entries is unaffected.
2. The existing workaround is applied to both broadcast and local TLB
invalidation, whereas for all relevant errata it is only necessary to
apply a workaround for broadcast invalidation.
3. The existing workaround replaces every TLBI with a TLBI;DSB;TLBI
sequence, whereas for all relevant errata it is only necessary to
execute a single additional TLBI;DSB sequence after any number of
TLBIs are completed by a DSB.
For example, for a sequence of batched TLBIs:
TLBI <op1>[, <arg1>]
TLBI <op2>[, <arg2>]
TLBI <op3>[, <arg3>]
DSB ISH
... the existing workaround will expand this to:
TLBI <op1>[, <arg1>]
DSB ISH // additional
TLBI <op1>[, <arg1>] // additional
TLBI <op2>[, <arg2>]
DSB ISH // additional
TLBI <op2>[, <arg2>] // additional
TLBI <op3>[, <arg3>]
DSB ISH // additional
TLBI <op3>[, <arg3>] // additional
DSB ISH
... whereas it is sufficient to have:
TLBI <op1>[, <arg1>]
TLBI <op2>[, <arg2>]
TLBI <op3>[, <arg3>]
DSB ISH
TLBI <opX>[, <argX>] // additional
DSB ISH // additional
Using a single additional TLBI and DSB at the end of the sequence can
have significantly lower overhead as each DSB which completes a TLBI
must synchronize with other PEs in the system, with potential
performance effects both locally and system-wide.
4. The existing workaround repeats each specific TLBI operation, whereas
for all relevant errata it is sufficient for the additional TLBI to
use *any* operation which will be broadcast, regardless of which
translation regime or stage of translation the operation applies to.
For example, for a single TLBI:
TLBI ALLE2IS
DSB ISH
... the existing workaround will expand this to:
TLBI ALLE2IS
DSB ISH
TLBI ALLE2IS // additional
DSB ISH // additional
... whereas it is sufficient to have:
TLBI ALLE2IS
DSB ISH
TLBI VALE1IS, XZR // additional
DSB ISH // additional
As the additional TLBI doesn't have to match a specific earlier TLBI,
the additional TLBI can be implemented in separate code, with no
memory of the earlier TLBIs. The additional TLBI can also use a
cheaper TLBI operation.
5. The existing workaround is applied to both Stage-1 and Stage-2 TLB
invalidation, whereas for all relevant errata it is only necessary to
apply a workaround for Stage-1 invalidation.
Architecturally, TLBI operations which invalidate only Stage-2
information (e.g. IPAS2E1IS) are not required to invalidate TLB
entries which combine information from Stage-1 and Stage-2
translation table entries, and consequently may not complete memory
accesses translated by those combined entries. In these cases,
completion of memory accesses is only guaranteed after subsequent
invalidation of Stage-1 information (e.g. VMALLE1IS).
Rework the workaround logic as follows:
- add TLB_HELPER_LOCAL() to be used for local TLB ops without a
workaround,
- modify TLB_HELPER() workaround to use tlbi vale2is, xzr as a second
TLBI,
- drop TLB_HELPER_VA(). It's used only by __flush_xen_tlb_one_local
which is local and does not need workaround and by
__flush_xen_tlb_one. In the latter case, since it's used in a loop,
we don't need a workaround in the middle. Add __tlb_repeat_sync with
a workaround to be used at the end after DSB and before final ISB,
- TLBI VALE2IS passing XZR is used as an additional TLBI. While there is
an identity mapping there, it's used very rarely. The performance
impact is therefore negligible. If things change in the future, we
can revisit the decision.
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>
(cherry picked from commit 7c502d7591519135765b8041cbd1c70e56e5a0b9)
diff --git a/xen/arch/arm/include/asm/arm32/flushtlb.h b/xen/arch/arm/include/asm/arm32/flushtlb.h
index 61c25a318998..5483be08fbbe 100644
--- a/xen/arch/arm/include/asm/arm32/flushtlb.h
+++ b/xen/arch/arm/include/asm/arm32/flushtlb.h
@@ -57,6 +57,9 @@ static inline void __flush_xen_tlb_one(vaddr_t va)
asm volatile(STORE_CP32(0, TLBIMVAHIS) : : "r" (va) : "memory");
}
+/* Only for ARM64_WORKAROUND_REPEAT_TLBI */
+static inline void __tlb_repeat_sync(void) {}
+
#endif /* __ASM_ARM_ARM32_FLUSHTLB_H__ */
/*
* Local variables:
diff --git a/xen/arch/arm/include/asm/arm64/flushtlb.h b/xen/arch/arm/include/asm/arm64/flushtlb.h
index 3b99c11b50d1..1606b26bf28a 100644
--- a/xen/arch/arm/include/asm/arm64/flushtlb.h
+++ b/xen/arch/arm/include/asm/arm64/flushtlb.h
@@ -12,9 +12,14 @@
* ARM64_WORKAROUND_REPEAT_TLBI:
* Modification of the translation table for a virtual address might lead to
* read-after-read ordering violation.
- * The workaround repeats TLBI+DSB ISH operation for all the TLB flush
- * operations. While this is strictly not necessary, we don't want to
- * take any risk.
+ * The workaround repeats TLBI+DSB ISH operation for broadcast TLB flush
+ * operations. The workaround is not needed for local operations.
+ *
+ * It is sufficient for the additional TLBI to use *any* operation which will
+ * be broadcast, regardless of which translation regime or stage of translation
+ * the operation applies to. TLBI VALE2IS is used passing XZR. While there is
+ * an identity mapping there, it's only used during suspend/resume, CPU on/off,
+ * so the impact (performance if any) is negligible.
*
* For Xen page-tables the ISB will discard any instructions fetched
* from the old mappings.
@@ -26,69 +31,90 @@
* Note that for local TLB flush, using non-shareable (nsh) is sufficient
* (see D5-4929 in ARM DDI 0487H.a). Although, the memory barrier in
* for the workaround is left as inner-shareable to match with Linux
- * v6.1-rc8.
+ * v6.19.
*/
-#define TLB_HELPER(name, tlbop, sh) \
+#define TLB_HELPER_LOCAL(name, tlbop) \
static inline void name(void) \
{ \
asm_inline volatile ( \
- "dsb " # sh "st;" \
+ "dsb nshst;" \
"tlbi " # tlbop ";" \
- ALTERNATIVE( \
- "nop; nop;", \
- "dsb ish;" \
- "tlbi " # tlbop ";", \
- ARM64_WORKAROUND_REPEAT_TLBI, \
- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
- "dsb " # sh ";" \
+ "dsb nsh;" \
"isb;" \
: : : "memory"); \
}
-/*
- * FLush TLB by VA. This will likely be used in a loop, so the caller
- * is responsible to use the appropriate memory barriers before/after
- * the sequence.
- *
- * See above about the ARM64_WORKAROUND_REPEAT_TLBI sequence.
- */
-#define TLB_HELPER_VA(name, tlbop) \
-static inline void name(vaddr_t va) \
-{ \
- asm_inline volatile ( \
- "tlbi " # tlbop ", %0;" \
- ALTERNATIVE( \
- "nop; nop;", \
- "dsb ish;" \
- "tlbi " # tlbop ", %0;", \
- ARM64_WORKAROUND_REPEAT_TLBI, \
- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
- : : "r" (va >> PAGE_SHIFT) : "memory"); \
+#define TLB_HELPER(name, tlbop) \
+static inline void name(void) \
+{ \
+ asm_inline volatile ( \
+ "dsb ishst;" \
+ "tlbi " # tlbop ";" \
+ ALTERNATIVE( \
+ "nop; nop;", \
+ "dsb ish;" \
+ "tlbi vale2is, xzr;", \
+ ARM64_WORKAROUND_REPEAT_TLBI, \
+ CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
+ "dsb ish;" \
+ "isb;" \
+ : : : "memory"); \
}
/* Flush local TLBs, current VMID only. */
-TLB_HELPER(flush_guest_tlb_local, vmalls12e1, nsh)
+TLB_HELPER_LOCAL(flush_guest_tlb_local, vmalls12e1)
/* Flush innershareable TLBs, current VMID only */
-TLB_HELPER(flush_guest_tlb, vmalls12e1is, ish)
+TLB_HELPER(flush_guest_tlb, vmalls12e1is)
/* Flush local TLBs, all VMIDs, non-hypervisor mode */
-TLB_HELPER(flush_all_guests_tlb_local, alle1, nsh)
+TLB_HELPER_LOCAL(flush_all_guests_tlb_local, alle1)
/* Flush innershareable TLBs, all VMIDs, non-hypervisor mode */
-TLB_HELPER(flush_all_guests_tlb, alle1is, ish)
+TLB_HELPER(flush_all_guests_tlb, alle1is)
/* Flush all hypervisor mappings from the TLB of the local processor. */
-TLB_HELPER(flush_xen_tlb_local, alle2, nsh)
+TLB_HELPER_LOCAL(flush_xen_tlb_local, alle2)
+
+#undef TLB_HELPER_LOCAL
+#undef TLB_HELPER
+
+/*
+ * FLush TLB by VA. This will likely be used in a loop, so the caller
+ * is responsible to use the appropriate memory barriers before/after
+ * the sequence.
+ */
/* Flush TLB of local processor for address va. */
-TLB_HELPER_VA(__flush_xen_tlb_one_local, vae2)
+static inline void __flush_xen_tlb_one_local(vaddr_t va)
+{
+ asm_inline volatile (
+ "tlbi vae2, %0" : : "r" (va >> PAGE_SHIFT) : "memory");
+}
/* Flush TLB of all processors in the inner-shareable domain for address va. */
-TLB_HELPER_VA(__flush_xen_tlb_one, vae2is)
+static inline void __flush_xen_tlb_one(vaddr_t va)
+{
+ asm_inline volatile (
+ "tlbi vae2is, %0" : : "r" (va >> PAGE_SHIFT) : "memory");
+}
-#undef TLB_HELPER
-#undef TLB_HELPER_VA
+/*
+ * ARM64_WORKAROUND_REPEAT_TLBI:
+ * For all relevant erratas it is only necessary to execute a single
+ * additional TLBI;DSB sequence after any number of TLBIs are completed by DSB.
+ */
+static inline void __tlb_repeat_sync(void)
+{
+ asm_inline volatile (
+ ALTERNATIVE(
+ "nop; nop;",
+ "tlbi vale2is, xzr;"
+ "dsb ish;",
+ ARM64_WORKAROUND_REPEAT_TLBI,
+ CONFIG_ARM64_WORKAROUND_REPEAT_TLBI)
+ : : : "memory");
+}
#endif /* __ASM_ARM_ARM64_FLUSHTLB_H__ */
/*
diff --git a/xen/arch/arm/include/asm/flushtlb.h b/xen/arch/arm/include/asm/flushtlb.h
index e45fb6d97b02..c292c3c00d29 100644
--- a/xen/arch/arm/include/asm/flushtlb.h
+++ b/xen/arch/arm/include/asm/flushtlb.h
@@ -65,6 +65,7 @@ static inline void flush_xen_tlb_range_va(vaddr_t va,
va += PAGE_SIZE;
}
dsb(ish); /* Ensure the TLB invalidation has completed */
+ __tlb_repeat_sync();
isb();
}
diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h
index 19c0ec63a59a..feafc14ebfda 100644
--- a/xen/arch/arm/include/asm/mmu/layout.h
+++ b/xen/arch/arm/include/asm/mmu/layout.h
@@ -23,6 +23,10 @@
*
* Reserved to identity map Xen
*
+ * Note: As part of ARM64_WORKAROUND_REPEAT_TLBI, VA 0 is used for an extra
+ * TLBI operation given its rare use (only identity mapping) and thus
+ * negligible performance impact.
+ *
* 0x00000a0000000000 - 0x00000a7fffffffff (512GB, L0 slot [20])
* (Relative offsets)
* 0 - 2M Unmapped

View file

@ -1,71 +0,0 @@
From 7e70b87512c966248b1e8453d9ac54c643c06f44 Mon Sep 17 00:00:00 2001
From: Michal Orzel <michal.orzel@amd.com>
Date: Fri, 22 May 2026 09:35:55 +0200
Subject: xen/arm: Sync missing definitions for Arm CPUs with Linux
Synchronize with Linux kernel 7.0 definitions for the following CPUs:
- Cortex-A76AE,
- Cortex-A78AE,
- Cortex-X1C,
- Cortex-X3,
- Neoverse-V2,
- Cortex-X4,
- Neoverse-V3AE,
- Neoverse-V3,
- Cortex-X925.
These will be used for errata detection in subsequent patches.
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Julien Grall <julien@xen.org>
diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
index ec23fd098b63..907778683b08 100644
--- a/xen/arch/arm/include/asm/processor.h
+++ b/xen/arch/arm/include/asm/processor.h
@@ -89,13 +89,22 @@
#define ARM_CPU_PART_CORTEX_A76 0xD0B
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
#define ARM_CPU_PART_CORTEX_A77 0xD0D
+#define ARM_CPU_PART_CORTEX_A76AE 0xD0E
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
#define ARM_CPU_PART_CORTEX_A78 0xD41
+#define ARM_CPU_PART_CORTEX_A78AE 0xD42
#define ARM_CPU_PART_CORTEX_X1 0xD44
#define ARM_CPU_PART_CORTEX_A710 0xD47
#define ARM_CPU_PART_CORTEX_X2 0xD48
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
+#define ARM_CPU_PART_CORTEX_X1C 0xD4C
+#define ARM_CPU_PART_CORTEX_X3 0xD4E
+#define ARM_CPU_PART_NEOVERSE_V2 0xD4F
+#define ARM_CPU_PART_CORTEX_X4 0xD82
+#define ARM_CPU_PART_NEOVERSE_V3AE 0xD83
+#define ARM_CPU_PART_NEOVERSE_V3 0xD84
+#define ARM_CPU_PART_CORTEX_X925 0xD85
#define MIDR_CORTEX_A12 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A12)
#define MIDR_CORTEX_A17 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A17)
@@ -110,13 +119,22 @@
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
+#define MIDR_CORTEX_A76AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76AE)
#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
+#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
+#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
+#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3)
+#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2)
+#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4)
+#define MIDR_NEOVERSE_V3AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3AE)
+#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
+#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
/* MPIDR Multiprocessor Affinity Register */
#define _MPIDR_UP (30)

View file

@ -1,37 +0,0 @@
From c0f7b40fdbb986b3cf470ed51f3878261e33f9cb Mon Sep 17 00:00:00 2001
From: Michal Orzel <michal.orzel@amd.com>
Date: Fri, 22 May 2026 09:35:56 +0200
Subject: xen/arm: Add C1-Ultra definitions
Add processor definitions for C1-Ultra. These will be used for errata
detection in subsequent patches.
These values can be found in the C1-Ultra TRM:
https://developer.arm.com/documentation/108014/0100/
... in section A.5.1 ("MIDR_EL1, Main ID Register").
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Julien Grall <julien@xen.org>
diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
index 907778683b08..72745cca62bc 100644
--- a/xen/arch/arm/include/asm/processor.h
+++ b/xen/arch/arm/include/asm/processor.h
@@ -105,6 +105,7 @@
#define ARM_CPU_PART_NEOVERSE_V3AE 0xD83
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
#define ARM_CPU_PART_CORTEX_X925 0xD85
+#define ARM_CPU_PART_C1_ULTRA 0xD8C
#define MIDR_CORTEX_A12 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A12)
#define MIDR_CORTEX_A17 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A17)
@@ -135,6 +136,7 @@
#define MIDR_NEOVERSE_V3AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3AE)
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
+#define MIDR_C1_ULTRA MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_ULTRA)
/* MPIDR Multiprocessor Affinity Register */
#define _MPIDR_UP (30)

View file

@ -1,37 +0,0 @@
From 6af67aeca418bffb807424eb3415fab59e581733 Mon Sep 17 00:00:00 2001
From: Michal Orzel <michal.orzel@amd.com>
Date: Fri, 22 May 2026 09:35:57 +0200
Subject: xen/arm: Add C1-Premium definitions
Add processor definitions for C1-Premium. These will be used for errata
detection in subsequent patches.
These values can be found in the C1-Premium TRM:
https://developer.arm.com/documentation/109416/0100/
... in section A.5.1 ("MIDR_EL1, Main ID Register").
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Julien Grall <julien@xen.org>
diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
index 72745cca62bc..25c5762c6706 100644
--- a/xen/arch/arm/include/asm/processor.h
+++ b/xen/arch/arm/include/asm/processor.h
@@ -106,6 +106,7 @@
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
#define ARM_CPU_PART_CORTEX_X925 0xD85
#define ARM_CPU_PART_C1_ULTRA 0xD8C
+#define ARM_CPU_PART_C1_PREMIUM 0xD90
#define MIDR_CORTEX_A12 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A12)
#define MIDR_CORTEX_A17 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A17)
@@ -137,6 +138,7 @@
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
#define MIDR_C1_ULTRA MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_ULTRA)
+#define MIDR_C1_PREMIUM MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_PREMIUM)
/* MPIDR Multiprocessor Affinity Register */
#define _MPIDR_UP (30)

View file

@ -1,404 +0,0 @@
From 579016a359741044c9076bf0884e1dbab00ab080 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Mon, 16 Mar 2026 11:03:22 +0100
Subject: [PATCH] x86/mm: accurately track which vCPU page-tables are loaded
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Neither current nor curr_vcpu per-CPU fields accurately track which
page-tables are loaded. There are corner cases when dealing with shadow
paging failures that switch to the idle vCPU page-tables without changing
current or curr_vcpu per-CPU fields.
Introduce a new per-CPU field that attempts to track which vCPU page-tables
are loaded. Update such tracking when cr3 is changed, and do so in a
region with interrupts disabled, as to avoid handling interrupts with a
mismatch between the vCPU tracking field and the loaded page-tables.
As a result of this newly more accurate tracking the mapcache override
functionality can be removed: the dom0 PV builder was the only user of it,
and it's updated here to properly signal which vCPU page-tables are loaded
in the calls to switch_cr3_cr4().
Note the EFI page-tables have the Xen owned L4 slots copied from the idle
page-tables, so for the effects of the mapcache the EFI page-tables could
use the idle mapcache if it had one. Pass the idle vCPU in the
switch_cr3_cr4() call that switches to the runtime EFI page-tables.
There are known issues with the use of mapcache in NMI context.  This patch
does not alter the behaviour.
This is CVE-2026-42488 / XSA-494.
Fixes: fb0ff49fe9f7 ("x86/shadow: defer releasing of PV's top-level shadow reference")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/domain_page.c | 48 ++++++++++++----------------
xen/arch/x86/flushtlb.c | 5 ++-
xen/arch/x86/include/asm/domain.h | 1 -
xen/arch/x86/include/asm/flushtlb.h | 2 +-
xen/arch/x86/include/asm/processor.h | 3 ++
xen/arch/x86/mm.c | 4 +--
xen/arch/x86/pv/dom0_build.c | 12 +++----
xen/arch/x86/pv/domain.c | 13 ++++++--
xen/arch/x86/smpboot.c | 1 +
xen/common/efi/common-stub.c | 5 ---
xen/common/efi/runtime.c | 21 +++++-------
xen/include/xen/efi.h | 1 -
12 files changed, 54 insertions(+), 62 deletions(-)
diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
index eac5e3304fb8..72c00194f315 100644
--- a/xen/arch/x86/domain_page.c
+++ b/xen/arch/x86/domain_page.c
@@ -18,48 +18,40 @@
#include <asm/hardirq.h>
#include <asm/setup.h>
-static DEFINE_PER_CPU(struct vcpu *, override);
-
static inline struct vcpu *mapcache_current_vcpu(void)
{
- /* In the common case we use the mapcache of the running VCPU. */
- struct vcpu *v = this_cpu(override) ?: current;
-
- /*
- * When current isn't properly set up yet, this is equivalent to
- * running in an idle vCPU (callers must check for NULL).
- */
- if ( !v )
- return NULL;
+ struct vcpu *v = this_cpu(pgtable_vcpu);
+ struct vcpu *curr = current;
/*
- * When using efi runtime page tables, we have the equivalent of the idle
- * domain's page tables but current may point at another domain's VCPU.
- * Return NULL as though current is not properly set up yet.
+ * During early boot pgtable_vcpu is not set, callers must handle NULL.
+ * Non-PV domains don't have a mapcache, the directmap covers all physical
+ * address space.
*/
- if ( efi_rs_using_pgtables() )
+ if ( !v || !is_pv_vcpu(v) )
return NULL;
/*
- * If guest_table is NULL, and we are running a paravirtualised guest,
- * then it means we are running on the idle domain's page table and must
- * therefore use its mapcache.
+ * If we are in a lazy context-switch state from a PV vCPU do a full switch
+ * to the idle vCPU now, otherwise an incoming FLUSH_VCPU_STATE IPI would
+ * change the page tables under our feet an invalidate any in-use mapcache
+ * entries.
*/
- if ( unlikely(pagetable_is_null(v->arch.guest_table)) && is_pv_vcpu(v) )
+ if ( unlikely(this_cpu(curr_vcpu) != curr) )
{
- /* If we really are idling, perform lazy context switch now. */
- if ( (v = idle_vcpu[smp_processor_id()]) == current )
- sync_local_execstate();
+ ASSERT(curr == idle_vcpu[smp_processor_id()]);
+ sync_local_execstate();
/* We must now be running on the idle page table. */
ASSERT(cr3_pa(read_cr3()) == __pa(idle_pg_table));
}
- return v;
-}
-
-void __init mapcache_override_current(struct vcpu *v)
-{
- this_cpu(override) = v;
+ /*
+ * At this point we can guarantee Xen is not in lazy context switch: either
+ * the code above will have synced the state, or an incoming
+ * FLUSH_VCPU_STATE IPI has done so behind our back. Use ACCESS_ONCE to
+ * ensure the compiler never returns the locally cached pgtable_vcpu value.
+ */
+ return ACCESS_ONCE(this_cpu(pgtable_vcpu));
}
#define mapcache_l2_entry(e) ((e) >> PAGETABLE_ORDER)
diff --git a/xen/arch/x86/flushtlb.c b/xen/arch/x86/flushtlb.c
index 09e676c151fa..928bca66b433 100644
--- a/xen/arch/x86/flushtlb.c
+++ b/xen/arch/x86/flushtlb.c
@@ -111,7 +111,9 @@ static void do_tlb_flush(void)
local_irq_restore(flags);
}
-void switch_cr3_cr4(unsigned long cr3, unsigned long cr4)
+DEFINE_PER_CPU(struct vcpu *, pgtable_vcpu);
+
+void switch_cr3_cr4(struct vcpu *v, unsigned long cr3, unsigned long cr4)
{
unsigned long flags, old_cr4;
u32 t = 0;
@@ -155,6 +157,7 @@ void switch_cr3_cr4(unsigned long cr3, unsigned long cr4)
if ( (old_cr4 & X86_CR4_PCIDE) > (cr4 & X86_CR4_PCIDE) )
cr3 |= X86_CR3_NOFLUSH;
write_cr3(cr3);
+ this_cpu(pgtable_vcpu) = v;
if ( old_cr4 != cr4 )
write_cr4(cr4);
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index 828f42c3e448..10d2b9fe2546 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -75,7 +75,6 @@ struct mapcache_domain {
int mapcache_domain_init(struct domain *d);
int mapcache_vcpu_init(struct vcpu *v);
-void mapcache_override_current(struct vcpu *v);
/* x86/64: toggle guest between kernel and user modes. */
void toggle_guest_mode(struct vcpu *v);
diff --git a/xen/arch/x86/include/asm/flushtlb.h b/xen/arch/x86/include/asm/flushtlb.h
index 7bcbca2b7f31..345677eb72ae 100644
--- a/xen/arch/x86/include/asm/flushtlb.h
+++ b/xen/arch/x86/include/asm/flushtlb.h
@@ -104,7 +104,7 @@ static inline void invlpg(const void *p)
}
/* Write pagetable base and implicitly tick the tlbflush clock. */
-void switch_cr3_cr4(unsigned long cr3, unsigned long cr4);
+void switch_cr3_cr4(struct vcpu *v, unsigned long cr3, unsigned long cr4);
/* flush_* flag fields: */
/*
diff --git a/xen/arch/x86/include/asm/processor.h b/xen/arch/x86/include/asm/processor.h
index 2e087c625770..d2cacdfedb74 100644
--- a/xen/arch/x86/include/asm/processor.h
+++ b/xen/arch/x86/include/asm/processor.h
@@ -328,6 +328,9 @@ DECLARE_PER_CPU(struct tss_page, tss_page);
DECLARE_PER_CPU(root_pgentry_t *, root_pgt);
+/* vCPU of the currently loaded page-tables. */
+DECLARE_PER_CPU(struct vcpu *, pgtable_vcpu);
+
extern void write_ptbase(struct vcpu *v);
/* PAUSE (encoding: REP NOP) is a good thing to insert into busy-wait loops. */
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 2b23bf2e7a75..d02c9862d387 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -535,7 +535,7 @@ void write_ptbase(struct vcpu *v)
cpu_info->pv_cr3 = __pa(this_cpu(root_pgt));
if ( new_cr4 & X86_CR4_PCIDE )
cpu_info->pv_cr3 |= get_pcid_bits(v, true);
- switch_cr3_cr4(v->arch.cr3, new_cr4);
+ switch_cr3_cr4(v, v->arch.cr3, new_cr4);
}
else
{
@@ -543,7 +543,7 @@ void write_ptbase(struct vcpu *v)
cpu_info->use_pv_cr3 = false;
cpu_info->xen_cr3 = 0;
/* switch_cr3_cr4() serializes. */
- switch_cr3_cr4(v->arch.cr3, new_cr4);
+ switch_cr3_cr4(v, v->arch.cr3, new_cr4);
cpu_info->pv_cr3 = 0;
}
}
diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index 37729091dfaa..42bc530c0f0d 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -828,8 +828,7 @@ static int __init dom0_construct(const struct boot_domain *bd)
update_cr3(v);
/* We run on dom0's page tables for the final part of the build process. */
- switch_cr3_cr4(cr3_pa(v->arch.cr3), read_cr4());
- mapcache_override_current(v);
+ switch_cr3_cr4(v, cr3_pa(v->arch.cr3), read_cr4());
/* Copy the OS image and free temporary buffer. */
elf.dest_base = (void*)vkern_start;
@@ -838,8 +837,7 @@ static int __init dom0_construct(const struct boot_domain *bd)
rc = elf_load_binary(&elf);
if ( rc < 0 )
{
- mapcache_override_current(NULL);
- switch_cr3_cr4(current->arch.cr3, read_cr4());
+ switch_cr3_cr4(current, current->arch.cr3, read_cr4());
printk("Failed to load the kernel binary\n");
goto out;
}
@@ -850,8 +848,7 @@ static int __init dom0_construct(const struct boot_domain *bd)
if ( (parms.virt_hypercall < v_start) ||
(parms.virt_hypercall >= v_end) )
{
- mapcache_override_current(NULL);
- switch_cr3_cr4(current->arch.cr3, read_cr4());
+ switch_cr3_cr4(current, current->arch.cr3, read_cr4());
printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
return -EINVAL;
}
@@ -992,8 +989,7 @@ static int __init dom0_construct(const struct boot_domain *bd)
#endif
/* Return to idle domain's page tables. */
- mapcache_override_current(NULL);
- switch_cr3_cr4(current->arch.cr3, read_cr4());
+ switch_cr3_cr4(current, current->arch.cr3, read_cr4());
update_domain_wallclock_time(d);
diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
index ef4f442e7332..d9e52f5f88f3 100644
--- a/xen/arch/x86/pv/domain.c
+++ b/xen/arch/x86/pv/domain.c
@@ -451,6 +451,8 @@ static void _toggle_guest_pt(struct vcpu *v)
pagetable_t old_shadow;
unsigned long cr3;
+ ASSERT(local_irq_is_enabled());
+
v->arch.flags ^= TF_kernel_mode;
guest_update = v->arch.flags & TF_kernel_mode;
old_shadow = update_cr3(v);
@@ -473,15 +475,22 @@ static void _toggle_guest_pt(struct vcpu *v)
{
cr3 &= ~X86_CR3_NOFLUSH;
+ local_irq_disable();
if ( unlikely(mfn_eq(pagetable_get_mfn(old_shadow),
maddr_to_mfn(cr3))) )
{
- cr3 = idle_vcpu[v->processor]->arch.cr3;
/* Also suppress runstate/time area updates below. */
guest_update = false;
+
+ cr3 = idle_vcpu[v->processor]->arch.cr3;
+ this_cpu(pgtable_vcpu) = idle_vcpu[v->processor];
}
+
+ write_cr3(cr3);
+ local_irq_enable();
}
- write_cr3(cr3);
+ else
+ write_cr3(cr3);
if ( !pagetable_is_null(old_shadow) )
shadow_put_top_level(v->domain, old_shadow);
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 27628800a821..b37feab3bef4 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -1063,6 +1063,7 @@ static int cpu_smpboot_alloc(unsigned int cpu)
info->current_vcpu = idle_vcpu[cpu]; /* set_current() */
per_cpu(curr_vcpu, cpu) = idle_vcpu[cpu];
+ per_cpu(pgtable_vcpu, cpu) = idle_vcpu[cpu];
gdt = per_cpu(gdt, cpu) ?: alloc_xenheap_pages(0, memflags);
if ( gdt == NULL )
diff --git a/xen/common/efi/common-stub.c b/xen/common/efi/common-stub.c
index 77f138a6c574..7b12005bea3f 100644
--- a/xen/common/efi/common-stub.c
+++ b/xen/common/efi/common-stub.c
@@ -7,11 +7,6 @@ bool efi_enabled(unsigned int feature)
return false;
}
-bool efi_rs_using_pgtables(void)
-{
- return false;
-}
-
unsigned long efi_get_time(void)
{
BUG();
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index 30d649ca5c1b..feb09acf754c 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -49,7 +49,6 @@ const CHAR16 *__read_mostly efi_fw_vendor;
const EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
static DEFINE_SPINLOCK(efi_rs_lock);
-static unsigned int efi_rs_on_cpu = NR_CPUS;
#endif
UINTN __read_mostly efi_memmap_size;
@@ -92,6 +91,11 @@ struct efi_rs_state efi_rs_enter(void)
if ( mfn_eq(efi_l4_mfn, INVALID_MFN) )
return state;
+ /*
+ * If in lazy idle context switch state sync now to avoid an incoming
+ * FLUSH_VCPU_STATE IPI changing the loaded page-tables.
+ */
+ sync_local_execstate();
state.cr3 = read_cr3();
save_fpu_enable();
asm volatile ( "fnclex; fldcw %0" :: "m" (fcw) );
@@ -99,8 +103,6 @@ struct efi_rs_state efi_rs_enter(void)
spin_lock(&efi_rs_lock);
- efi_rs_on_cpu = smp_processor_id();
-
/* prevent fixup_page_fault() from doing anything */
irq_enter();
@@ -115,7 +117,8 @@ struct efi_rs_state efi_rs_enter(void)
lgdt(&gdt_desc);
}
- switch_cr3_cr4(mfn_to_maddr(efi_l4_mfn), read_cr4());
+ switch_cr3_cr4(idle_vcpu[smp_processor_id()], mfn_to_maddr(efi_l4_mfn),
+ read_cr4());
/*
* At the time of writing (2022), no UEFI firwmare is CET-IBT compatible.
@@ -143,7 +146,7 @@ void efi_rs_leave(struct efi_rs_state *state)
if ( state->msr_s_cet )
wrmsrl(MSR_S_CET, state->msr_s_cet);
- switch_cr3_cr4(state->cr3, read_cr4());
+ switch_cr3_cr4(curr, state->cr3, read_cr4());
if ( is_pv_vcpu(curr) && !is_idle_vcpu(curr) )
{
struct desc_ptr gdt_desc = {
@@ -154,18 +157,10 @@ void efi_rs_leave(struct efi_rs_state *state)
lgdt(&gdt_desc);
}
irq_exit();
- efi_rs_on_cpu = NR_CPUS;
spin_unlock(&efi_rs_lock);
vcpu_restore_fpu_nonlazy(curr, true);
}
-bool efi_rs_using_pgtables(void)
-{
- return !mfn_eq(efi_l4_mfn, INVALID_MFN) &&
- (smp_processor_id() == efi_rs_on_cpu) &&
- (read_cr3() == mfn_to_maddr(efi_l4_mfn));
-}
-
unsigned long efi_get_time(void)
{
EFI_TIME time;
diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h
index 723cb8085270..9953197ee553 100644
--- a/xen/include/xen/efi.h
+++ b/xen/include/xen/efi.h
@@ -40,7 +40,6 @@ extern bool efi_secure_boot;
void efi_init_memory(void);
bool efi_boot_mem_unused(unsigned long *start, unsigned long *end);
-bool efi_rs_using_pgtables(void);
unsigned long efi_get_time(void);
void efi_halt_system(void);
void efi_reset_system(bool warm);
--
2.53.0