Compare commits

..

110 commits

Author SHA1 Message Date
Python Maint
c8af4d85b6 Rebuilt for Python 3.15.0b4 ABI change 2026-07-22 10:47:19 +02:00
Fedora Release Engineering
5bd254f006 Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild 2026-07-17 09:07:32 +00:00
Jerry James
87e40ff1ba OCaml 5.5.0 rebuild 2026-07-09 11:46:55 -06:00
Yaakov Selkowitz
1e49e52adb Rebuilt for openssl 4.0 2026-06-18 16:36:54 -04:00
Michael Young
0c18c23c4c 4 security updates
x86 HVM I/O port list traversal [XSA-491, CVE-2026-42487]
domctl lock open to abuse [XSA-492, CVE-2026-42489, CVE-2026-42490]
Arm: Completion of memory accesses not guaranteed by completion of a TLBI
	 [XSA-493, CVE-2025-10263]
x86: mismatched mapcache metadata [XSA-494, CVE-2026-42488]
2026-06-18 21:14:50 +01:00
Yaakov Selkowitz
124455e632 Rebuilt for openssl 4.0 2026-06-12 20:07:37 -04:00
Python Maint
f67d5718e2 Rebuilt for Python 3.15 2026-06-03 19:38:16 +02:00
Michael Young
b448fd6e2f x86: CPU Opcode Cache corruption [XSA-490,CVE-2025-54518] 2026-05-12 20:57:06 +01:00
Michael Young
cf70d8c84e 4 security patches
+- oxenstored keeps quota related use counts across domain destruction
+       [XSA-483, CVE-2026-23556]
+- Xenstored DoS via XS_RESET_WATCHES command [XSA-484, CVE-2026-23557]
+- grant table v2 race in status page mapping [XSA-486, CVE-2026-23558]
+- x86: Floating Point Divider State Sampling [XSA-488, CVE-2025-54505]
2026-04-28 21:20:56 +01:00
Adam Williamson
18cf277715 Revert "Make licenses package noarch"
This reverts commit 545511922a.
Turns out we can't do this because different license files show
up on x86_64 and aarch64 (there are more on x86_64 as we build
more stuff there).
2026-03-27 15:59:15 -07:00
Adam Williamson
545511922a Make licenses package noarch
It only has licenses in it, after all.

Signed-off-by: Adam Williamson <awilliam@redhat.com>
2026-03-27 14:13:04 -07:00
Michael Young
30cb19d1ba update to xen 4.21.1 2026-03-26 20:52:44 +00:00
Michael Young
fbec0bc65a 2 security updates
Use after free of paging structures in EPT [XSA-480, CVE-2026-23554]
Xenstored DoS by unprivileged domain [XSA-481, CVE-2026-23555]
2026-03-17 19:57:45 +00:00
Richard W.M. Jones
2b36f2e8ca OCaml 5.4.1 rebuild 2026-02-20 16:06:05 +00:00
Michael Young
d409186bf5 2 security updates
x86: buffer overrun with shadow paging + tracing [XSA-477, CVE-2025-58150]
x86: incomplete IBPB for vCPU isolation [XSA-479, CVE-2026-23553]
2026-01-28 22:25:55 +00:00
Fedora Release Engineering
461c19a5ca Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild 2026-01-17 20:34:16 +00:00
Jerry James
ca06290682 Fix a changelog entry 2026-01-13 20:56:05 -07:00
Michael Young
aa9dce01d1 update to xen 4.21.0 2026-01-07 20:11:57 +00:00
Michael Young
b27c4b799d update to xen 4.20.2 2025-11-14 18:46:13 +00:00
Michael Young
310309c8d5 teecr32_el1 and teehbr32_el1 support dropped in binutils 2.45.50-5.fc44
Incorrect removal of permissions on PCI device unplug
	[XSA-476, CVE-2025-58149]
x86: Incorrect input sanitisation in Viridian hypercalls
	[XSA-475, CVE-2025-58147, CVE-2025-58148]
2025-10-26 12:39:49 +00:00
Richard W.M. Jones
932125ac66 OCaml 5.4.0 rebuild 2025-10-15 17:21:56 +01:00
Python Maint
d001d8f7cf Rebuilt for Python 3.14.0rc3 bytecode 2025-09-19 15:03:51 +02:00
Michael Young
8bc3f5aa32 2 security updates
Mutiple vulnerabilities in the Viridian interface [XSA-472,
	CVE-2025-27466, CVE-2025-58142, CVE-2025-58143]
Arm issues with page refcounting [XSA-473, CVE-2025-58144, CVE-2025-58145]
2025-09-10 23:41:07 +01:00
Michael Young
ca8c5d5135 tools/xl: don't crash on NULL command line 2025-09-02 20:20:57 +01:00
Python Maint
39101b511c Rebuilt for Python 3.14.0rc2 bytecode 2025-08-15 15:23:19 +02:00
Fedora Release Engineering
e2d4d104a0 Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild 2025-07-25 20:44:23 +00:00
Michael Young
d382b68b39 update to xen 4.20.1
includes fixes for
x86: Incorrect stubs exception handling for flags recovery [XSA-470,
        CVE-2025-27465]
x86: Transitive Scheduler Attacks [XSA-471, CVE-2024-36350,
        CVE-2024-36357]
2025-07-15 21:03:56 +01:00
Jerry James
80e497a295 Rebuild to fix OCaml dependencies 2025-07-11 14:54:03 -06:00
Python Maint
41f5d9097f Rebuilt for Python 3.14 2025-06-02 21:24:59 +02:00
Michael Young
3a0543c8d6 x86: Indirect Target Selection [XSA-469, CVE-2024-28956] 2025-05-12 21:42:55 +01:00
Michael Young
88c9f05c39 update to xen-4.19.2
remove patches now included or superceded upstream
remove xen*.efi.elf files to avoid debuginfo failure
2025-04-07 21:00:32 +01:00
Michael Young
59fe5ad165 deadlock potential with VT-d and legacy PCI device pass-through
[XSA-467, CVE-2025-1713]
2025-02-27 18:20:39 +00:00
Michael Young
0e81fe4bff adjust file locations now /usr/sbin is a symlink to /usr/bin
remove debugedit fix as no longer needed
2025-01-24 22:32:04 +00:00
Fedora Release Engineering
0d1f7da88a Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild 2025-01-19 15:38:51 +00:00
Jerry James
5c740ce63a OCaml 5.3.0 rebuild for Fedora 42 2025-01-10 13:42:27 -07:00
Michael Young
d458004d8b work around debugedit bug to fix aarch64 builds 2025-01-09 21:24:58 +00:00
Andrea Perotti
ebbbc5ccb7 FIX #2335558: xen-hypervisor %post doesn't load all needed grub2 modules (elf.mod is missing) 2025-01-04 14:12:34 +01:00
Michael Young
2b88083cfc update to xen-4.19.1 2024-12-06 19:19:08 +00:00
Michael Young
a322535e9f add bugzilla references 2024-09-25 22:02:12 +01:00
Michael Young
417c2eb41a x86: Deadlock in vlapic_error() [XSA-462, CVE-2024-45817] 2024-09-24 16:48:07 +01:00
Miroslav Suchý
b5342a4b67 convert license to SPDX
This is part of https://fedoraproject.org/wiki/Changes/SPDX_Licenses_Phase_4
2024-09-04 22:52:13 +02:00
Michael Young
ef4574608a 2 security fixes
error handling in x86 IOMMU identity mapping [XSA-460, CVE-2024-31145]
PCI device pass-through with shared resources [XSA-461, CVE-2024-31146]
2024-08-14 22:07:13 +01:00
Michael Young
08778ae14d update to xen-4.19.0 2024-08-03 22:01:35 +01:00
Fedora Release Engineering
589e86cf56 Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild 2024-07-20 09:54:27 +00:00
Michael Young
1b82c01894 add bugzilla reference 2024-07-18 22:27:45 +01:00
Alejandro Vallejo
9e3a14be33 Split xen-runtime posttrans conditional
$(ls -A ...) expands before the whole condition is passed to `[`. This
means `-d <path>` does not gate the `ls` command being executed.

While it's benign, it causes ls's stderr to propagate to yum/dnf output,
which is somewhat disconcerting for the user.

Fix it by forcing ls into its own conditional.
2024-07-17 00:12:04 +01:00
Michael Young
269fa36c52 double unlock in x86 guest IRQ handling [XSA-458, CVE-2024-31143] 2024-07-16 21:23:30 +01:00
Python Maint
bac467190c Rebuilt for Python 3.13 2024-06-07 09:52:18 +02:00
Michael Young
254a309537 x86: Native Branch History Injection [XSA-456 version 3, CVE-2024-2201] 2024-06-03 21:39:12 +01:00
Michael Young
c762409b33 x86: Native Branch History Injection [XSA-456, CVE-2024-2201]
update to xen 4.18.2, remove patches now included upstream
2024-04-09 21:43:30 +01:00
Michael Young
4dc6f761c8 2 security updates
x86 HVM hypercalls may trigger Xen bug check [XSA-454, CVE-2023-46842]
x86: Incorrect logic for BTC/SRSO mitigations [XSA-455, CVE-2024-31142]
2024-04-09 19:25:08 +01:00
Michael Young
81b1db8227 update to xen-4.18.1 2024-03-20 19:12:09 +00:00
Michael Young
4d6e2c0007 2 security updates
x86: Register File Data Sampling [XSA-452, CVE-2023-28746]
GhostRace: Speculative Race Conditions [XSA-453, CVE-2024-2193]
2024-03-13 20:26:24 +00:00
Michael Young
ef85dabcd3 x86: shadow stack vs exceptions from emulation stubs
[XSA-451, CVE-2023-46841] (#2266326)
2024-02-27 20:02:19 +00:00
Michael Young
950832bad0 2 security updates + drop glibc32 requirement
pci: phantom functions assigned to incorrect contexts [XSA-449,
        CVE-2023-46839]
VT-d: Failure to quarantine devices in !HVM build [XSA-450,
        CVE-2023-46840]
2024-02-04 19:57:54 +00:00
Michael Young
b644c52cfa build fixes for gcc14, replace stubs-32.h requirement with glibc32 2024-02-03 09:47:57 +00:00
Fedora Release Engineering
869574bf2f Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild 2024-01-27 09:30:44 +00:00
Michael Young
343a901c21 arm32: The cache may not be properly cleaned/invalidated (take two)
[XSA-447, CVE-2023-46837]
rebuild for OCaml-5.1.1
2023-12-13 17:39:02 +00:00
Michael Young
99dc35fd60 update to xen-4.18.0 2023-11-29 19:15:48 +00:00
Michael Young
b5231bddba 2 security issues
x86/AMD: mismatch in IOMMU quarantine page table levels [XSA-445,
	CVE-2023-46835]
x86: BTC/SRSO fixes not fully effective [XSA-446, CVE-2023-46836]
2023-11-14 22:32:53 +00:00
Michael Young
ad078f957f 4 security issues
xenstored: A transaction conflict can crash C Xenstored [XSA-440,
        CVE-2023-34323]
x86/AMD: missing IOMMU TLB flushing [XSA-442, CVE-2023-34326]
Multiple vulnerabilities in libfsimage disk handling [XSA-443,
        CVE-2023-34325]
x86/AMD: Debug Mask handling [XSA-444, CVE-2023-34327,
        CVE-2023-34328]
2023-10-10 21:42:36 +01:00
Michael Young
7fa4a3eee6 rebuild for OCaml 5.1 2023-10-08 12:02:22 +01:00
Michael Young
afce7b2845 3 security issues
- arm32: The cache may not be properly cleaned/invalidated [XSA-437,
        CVE-2023-34321]
- top-level shadow reference dropped too early for 64-bit PV guests
        [XSA-438, CVE-2023-34322]
- x86/AMD: Divide speculative information leak [XSA-439, CVE-2023-20588]
2023-09-26 15:20:03 +01:00
Michael Young
9f61265760 update to xen-4.17.2 which includes security updates
x86/AMD: Speculative Return Stack Overflow [XSA-434, CVE-2023-20569]
x86/Intel: Gather Data Sampling [XSA-435, CVE-2022-40982]
remove patches now included upstream
2023-08-10 19:07:43 +01:00
Michael Young
c0ff82bee4 arm: Guests can trigger a deadlock on Cortex-A77 [XSA-436, CVE-2023-34320] 2023-08-01 21:16:33 +01:00
Michael Young
ca3f59d0e3 increment Release 2023-07-31 20:53:11 +01:00
Michael Young
eb85956ccc bugfix for x86/AMD: Zenbleed [XSA-433, CVE-2023-20593] 2023-07-31 20:47:37 +01:00
Michael Young
c09e550528 add CVE reference 2023-07-26 19:46:52 +01:00
Michael Young
baa6ba2e5a adjust OCaml patch condition so eln builds work 2023-07-26 00:01:08 +01:00
Michael Young
14c61e3105 x86/AMD: Zenbleed [XSA-433]
omit OCaml 5 patch on fc38
2023-07-24 22:15:29 +01:00
Fedora Release Engineering
7669a61055 Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2023-07-22 18:41:52 +00:00
Jerry James
70cfe51077 Add patch for OCaml 5.0.0 2023-07-10 15:55:49 -06:00
Michael Young
19ebd639fc work around a build problem with python 3.12 2023-06-27 20:32:48 +01:00
Python Maint
b65002c5bf Rebuilt for Python 3.12 2023-06-13 21:39:25 +02:00
Michael Young
f3cac52735 Mishandling of guest SSBD selection on AMD hardware
[XSA-431, CVE-2022-42336]
2023-05-16 19:21:37 +01:00
Michael Young
d6d8d8a393 update to xen-4.17.1
remove patches now included upstream
switch from patchN to patch N format for applying patches
2023-05-02 21:53:01 +01:00
Michael Young
e44f0d9ede x86 shadow paging arbitrary pointer dereference [XSA-430, CVE-2022-42335] 2023-04-25 21:24:14 +01:00
Michael Young
bf947f8f93 3 security issues (#2180425)
x86 shadow plus log-dirty mode use-after-free [XSA-427, CVE-2022-42332]
x86/HVM pinned cache attributes mis-handling [XSA-428, CVE-2022-42333,
	CVE-2022-42334]
x86: speculative vulnerability in 32bit SYSCALL path [XSA-429,
	CVE-2022-42331]
2023-03-21 17:20:08 +00:00
Michael Young
04f2270c6e use OVMF.fd from new edk2-ovmf-xen package
ovmf.bin file built from edk2-ovmf package no longer supports xen (#2170930)
2023-02-18 08:18:51 +00:00
Michael Young
cef4bbf959 x86: Cross-Thread Return Address Predictions [XSA-426, CVE-2022-27672] 2023-02-14 21:19:26 +00:00
Michael Young
d59e49c417 Guests can cause Xenstore crash via soft reset [XSA-425, CVE-2022-42330] 2023-01-25 17:36:04 +00:00
Michael Young
eadd06a27e now need BuildRequires for hostname 2023-01-24 23:45:25 +00:00
Fedora Release Engineering
e92b341446 Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2023-01-21 07:19:34 +00:00
Michael Young
0e3619e057 build fix for gcc13 2023-01-17 22:07:23 +00:00
Michael Young
8695caf85a fix clean up of init scripts if /etc/rc.d/init.d doesn't exist 2023-01-08 09:35:06 +00:00
Michael Young
766c47c1cb python3-setuptools BuildRequires is needed for python 3.12 2022-12-20 19:55:18 +00:00
Michael Young
a54439cc72 update to xen-4.17.0
rebase xen.fedora.systemd.patch and xen.canonicalize.patch
remove or adjust patches now included or superceded upstream
/var/lib/xenstored has moved to /run/xenstored
2022-12-13 20:46:36 +00:00
Michael Young
0aca66e99a x86: Multiple speculative security issues 2022-11-08 22:29:29 +00:00
Michael Young
97374c0faa several security updates
x86: unintended memory sharing between guests [XSA-412, CVE-2022-42327]
Xenstore: Guests can crash xenstored [XSA-414, CVE-2022-42309]
Xenstore: Guests can create orphaned Xenstore nodes [XSA-415,
	CVE-2022-42310]
Xenstore: guests can let run xenstored out of memory [XSA-326,
	CVE-2022-42311, CVE-2022-42312, CVE-2022-42313, CVE-2022-42314,
	CVE-2022-42315, CVE-2022-42316, CVE-2022-42317, CVE-2022-42318]
Xenstore: Guests can cause Xenstore to not free temporary memory
	[XSA-416, CVE-2022-42319]
Xenstore: Guests can get access to Xenstore nodes of deleted domains
	[XSA-417, CVE-2022-42320]
Xenstore: Guests can crash xenstored via exhausting the stack
	[XSA-418, CVE-2022-42321]
Xenstore: Cooperating guests can create arbitrary numbers of nodes
	[XSA-419, CVE-2022-42322, CVE-2022-42323]
Oxenstored 32->31 bit integer truncation issues [XSA-420, CVE-2022-42324]
Xenstore: Guests can create arbitrary number of nodes via transactions
	[XSA-421, CVE-2022-42325, CVE-2022-42326]
2022-11-01 17:09:30 +00:00
Michael Young
ca586624b1 add bug references 2022-10-18 19:15:03 +01:00
Michael Young
ebc4dec9e2 3 security fixes
Arm: unbounded memory consumption for 2nd-level page tables [XSA-409,
        CVE-2022-33747]
P2M pool freeing may take excessively long [XSA-410, CVE-2022-33746]
lock order inversion in transitive grant copy handling [XSA-411,
        CVE-2022-33748]
2022-10-14 20:50:36 +01:00
Michael Young
136d0a1506 update to xen-4.16.2 2022-09-17 16:52:46 +01:00
Michael Young
744bd15194 add bug reference 2022-08-01 19:39:42 +01:00
Michael Young
305416ce5a insufficient TLB flush for x86 PV guests in shadow mode
[XSA-408, CVE-2022-33745]
2022-07-26 19:35:01 +01:00
Fedora Release Engineering
abd09f4c10 Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2022-07-23 12:58:40 +00:00
Michael Young
ab3164079e Retbleed - arbitrary speculative code execution with return instructions
[XSA-407, CVE-2022-23816, CVE-2022-23825, CVE-2022-29900]
2022-07-12 21:34:09 +01:00
Michael Young
a743b10608 Add bug reference, fix CVE reference 2022-07-07 09:41:58 +01:00
Michael Young
9381fafa32 Linux disk/nic frontends data leaks
[XSA-403, CVE-2022-26365, CVE-2022-33740, CVE-2022-33741, CVE-2022-3374]
2022-07-06 12:30:05 +01:00
Michael Young
6cac8ee872 x86: MMIO Stale Data vulnerabilities
[XSA-404, CVE-2022-21123, CVE-2022-21125, CVE-2022-21166]
2022-06-21 23:12:54 +01:00
Python Maint
25f5ec29c8 Rebuilt for Python 3.11 2022-06-13 17:18:01 +02:00
Michael Young
161d5c0fe9 stop building for ix86 and armv7hl and 2 security updates
stop building for ix86 and armv7hl due to missing build dependency
x86 pv: Race condition in typeref acquisition [XSA-401, CVE-2022-26362]
x86 pv: Insufficient care with non-coherent mappings [ XSA-402,
        CVE-2022-26363, CVE-2022-26364]
2022-06-11 17:13:19 +01:00
Michael Young
7c54ce20c6 update to xen-4.16.1
strip .efi file to help EFI partitions with limited space
2022-04-14 21:06:05 +01:00
Michael Young
cac6545cdc 3 security update
Racy interactions between dirty vram tracking and paging log dirty
	hypercalls [XSA-397, CVE-2022-26356]
race in VT-d domain ID cleanup [XSA-399, CVE-2022-26357]
IOMMU: RMRR (VT-d) and unity map (AMD-Vi) handling issues [XSA-400,
	CVE-2022-26358, CVE-2022-26359, CVE-2022-26360, CVE-2022-26361]
additional patches so above applies cleanly
2022-04-05 22:06:41 +01:00
Michael Young
288b363e21 fix patch name 2022-03-21 10:12:29 +00:00
Michael Young
f1540fc363 fix build of xen*.efi file and package it in /usr/lib*/efi 2022-03-21 09:44:00 +00:00
Michael Young
d3847f2127 Multiple speculative security issues [XSA-398]
additional patches so above applies cleanly
2022-03-15 22:26:35 +00:00
Michael Young
a1bf0486e5 adjust build script and patches for gcc12 and package note support 2022-01-29 17:23:43 +00:00
Michael Young
6ccd000828 3 security updates
arm: guest_physmap_remove_page not removing the p2m mappings [XSA-393,
	CVE-2022-23033] (#2045044)
A PV guest could DoS Xen while unmapping a grant [XSA-394, CVE-2022-23034]
	(#2045042)
Insufficient cleanup of passed-through device IRQs [XSA-395,
	CVE-2022-23035] (#2045040)
2022-01-29 11:59:54 +00:00
Fedora Release Engineering
f752e6d4e7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2022-01-22 04:58:02 +00:00
Michael Young
8c923532c1 update to xen-4.16.0
don't build qemu-traditional or pv-grub by default (following upstream)
change grub module package dependencies from Suggests to Recommends
	and move to hypervisor package
rework seabios configure logic (bios.bin is no longer useful)
frontends vulnerable to backends [XSA-376] (document change only)
2022-01-10 19:46:29 +00:00
77 changed files with 5307 additions and 1919 deletions

3
.gitignore vendored
View file

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

View file

@ -1,11 +0,0 @@
--- 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

@ -1,11 +0,0 @@
--- 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

@ -1,48 +0,0 @@
--- 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

@ -1,12 +0,0 @@
--- 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

@ -1,63 +0,0 @@
--- 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

@ -1,37 +0,0 @@
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

@ -1,38 +0,0 @@
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

@ -1,44 +0,0 @@
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

@ -1,30 +0,0 @@
--- 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

@ -1,104 +0,0 @@
------------------------------------------------------------------------
*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

@ -1,56 +0,0 @@
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

@ -1,34 +0,0 @@
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

@ -1,45 +0,0 @@
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

@ -1,46 +0,0 @@
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

@ -1,31 +0,0 @@
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

@ -1,44 +0,0 @@
------------------------------------------------------------------------
*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

@ -1,68 +0,0 @@
------------------------------------------------------------------------
*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

@ -1,65 +0,0 @@
------------------------------------------------------------------------
*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

@ -1,76 +0,0 @@
------------------------------------------------------------------------
*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

@ -1,81 +0,0 @@
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

@ -1,37 +0,0 @@
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

@ -1,29 +0,0 @@
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

@ -1,34 +0,0 @@
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

@ -1,51 +0,0 @@
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

@ -1,51 +0,0 @@
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

@ -1,38 +0,0 @@
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

@ -1,31 +0,0 @@
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

@ -1,76 +0,0 @@
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,4 +4,5 @@ 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 (xen-4.15.4.tar.gz) = fa6a4991c0699025af163ed117f8d0523c0a482102464615025eb3575d755ffacec5df394e3fe01871cde6028678f654d99f8e3c2533b138765971a2a7994cb8
SHA512 (mini-os-4.21.0.tar.xz) = 7543774d15da84476d93d04154990923c82209cb3fa125574c0383652c5a310957200f54b63b34502161f9c3afce4907e0060d9036f3eaf3a7cb6b1b3119b546
SHA512 (xen-4.21.1.tar.xz) = 8dfe65255e202b3dacf9d0d7265636bc1f97627c11b08babc13a5b8e74c7c65e7e2c6a1513e28b3c713fe512edb6702a73b2bf667e2a8f2ce825b196a2cd5aab

View file

@ -1,45 +1,54 @@
--- 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
@@ -215,7 +215,7 @@
goto inval;
} else {
*relative = !strstarts(*path, "/");
- *path = canonicalize(conn, ctx, *path);
+ *path = xenstore_canonicalize(conn, ctx, *path);
if (!*path)
return errno;
if (!is_valid_nodename(*path))
@@ -305,7 +305,7 @@
--- 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 @@
if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
return EINVAL;
- node = canonicalize(conn, ctx, vec[0]);
+ node = xenstore_canonicalize(conn, ctx, vec[0]);
- node = canonicalize(conn, ctx, vec[0], true);
+ node = xenstore_canonicalize(conn, ctx, vec[0], true);
if (!node)
return ENOMEM;
return errno;
list_for_each_entry(watch, &conn->watches, list) {
--- 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 @@
--- 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 @@
return strings;
}
-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 *canonicalize(struct connection *conn, const void *ctx,
+const char *xenstore_canonicalize(struct connection *conn, const void *ctx,
const char *node, bool allow_special)
{
const char *prefix;
const char *name;
@@ -1303,7 +1303,7 @@
{
struct node *node;
@@ -874,7 +874,7 @@
if (!canonical_name)
canonical_name = &tmp_name;
- *canonical_name = canonicalize(conn, ctx, name);
+ *canonical_name = xenstore_canonicalize(conn, ctx, name);
- *canonical_name = canonicalize(conn, ctx, name, allow_special);
+ *canonical_name = xenstore_canonicalize(conn, ctx, name, allow_special);
if (!*canonical_name)
return NULL;
return get_node(conn, ctx, *canonical_name, perm);
--- 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
@@ -1320,7 +1320,7 @@
const char *tmp_name;
const struct node *node;
- tmp_name = canonicalize(conn, ctx, name, allow_special);
+ tmp_name = xenstore_canonicalize(conn, ctx, name, allow_special);
if (!tmp_name)
return NULL;
--- 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
@@ -18,7 +18,7 @@
}
}
@ -76,8 +85,8 @@
fprintf(stderr, "%s", line);
} while (strcmp(line, "Okay.\n") != 0);
--- 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
--- 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
@@ -6,7 +6,7 @@
#include <termios.h>
#include <unistd.h>
@ -96,14 +105,14 @@
seed = strtoul(line, 0, 0);
printf("Seed Okay.\n"); fflush(stdout);
--- xen-4.14.1/tools/xenstore/xenstored_core.h.orig 2020-12-17 16:47:25.000000000 +0000
+++ xen-4.14.1/tools/xenstore/xenstored_core.h 2020-12-17 20:13:10.806887309 +0000
@@ -153,7 +153,7 @@
--- 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. */
-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 *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. */
enum xs_perm_type perm_for_conn(struct connection *conn,

View file

@ -1,8 +0,0 @@
--- xen-4.11.0-rc7/tools/qemu-xen-traditional/i386-dm/qemu-ifup-Linux.orig 2017-09-15 19:37:27.000000000 +0100
+++ xen-4.11.0-rc7/tools/qemu-xen-traditional/i386-dm/qemu-ifup-Linux 2018-07-03 20:17:52.934780235 +0100
@@ -34,4 +34,4 @@
fi
ifconfig $1 0.0.0.0 up
-brctl addif $bridge $1 || true
+ip link set $1 master $bridge || true

13
xen.efi.build.patch Normal file
View file

@ -0,0 +1,13 @@
--- 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)

View file

@ -1,11 +0,0 @@
--- 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

@ -1,10 +0,0 @@
--- 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,7 +1,6 @@
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-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 @@
XEN_SYSTEMD_SERVICE += xen-qemu-dom0-disk-backend.service
XEN_SYSTEMD_SERVICE += xendomains.service
XEN_SYSTEMD_SERVICE += xen-watchdog.service
@ -10,16 +9,7 @@ diff -uN xen-4.5.0/tools/hotplug/Linux/systemd.orig/Makefile xen-4.5.0/tools/hot
+XEN_SYSTEMD_SERVICE += oxenstored.service
XEN_SYSTEMD_SERVICE += xendriverdomain.service
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"
ALL_XEN_SYSTEMD := $(XEN_SYSTEMD_MODULES) \
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
@ -59,27 +49,26 @@ 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.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 @@
--- 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 @@
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.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 @@
--- 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 :
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"
- 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"
fi

View file

@ -1,10 +0,0 @@
--- xen-4.13.0/tools/xenpmd/Makefile.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/xenpmd/Makefile 2020-01-22 22:13:16.564873608 +0000
@@ -3,6 +3,7 @@
CFLAGS += -Werror
CFLAGS += $(CFLAGS_libxenstore)
+CFLAGS += -Wno-error=format-truncation
LDLIBS += $(LDLIBS_libxenstore)

View file

@ -19,6 +19,6 @@ index 320e06f..618ae92 100644
{
- 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. */
if ( !opt_tboot_pa || (opt_tboot_pa & ~PAGE_MASK) )

10
xen.gcc12.fixes.patch Normal file
View file

@ -0,0 +1,10 @@
--- 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))

View file

@ -1,12 +0,0 @@
--- 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

@ -0,0 +1,88 @@
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

View file

@ -1,32 +1,50 @@
#
# Automatically generated file; DO NOT EDIT.
# Xen/x86 4.14.0-rc Configuration
# Xen/x86 4.20 Configuration
#
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=100101
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_INDIRECT_THUNK=y
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_TBOOT=y
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
#
@ -35,42 +53,55 @@ CONFIG_XEN_ALIGN_DEFAULT=y
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_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_HAS_MEM_PAGING=y
CONFIG_HAS_PDX=y
CONFIG_HAS_UBSAN=y
CONFIG_HAS_KEXEC=y
CONFIG_HAS_IOPORTS=y
CONFIG_HAS_SCHED_GRANULARITY=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_KEXEC=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_CRYPTO=y
# CONFIG_BOOT_TIME_CPUPOOLS is not set
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
@ -79,35 +110,63 @@ CONFIG_TRACEBUFFER=y
#
CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_NUMA=y
CONFIG_ACPI_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
#
# 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_64BIT=y
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
@ -115,8 +174,15 @@ CONFIG_HARDEN_BRANCH_PREDICTOR=y
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
@ -125,17 +191,18 @@ CONFIG_ALL_PLAT=y
# 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
# ARM32 settings
CONFIG_ALL32_PLAT=y
CONFIG_ARM32_HARDEN_BRANCH_PREDICTOR=y
CONFIG_ARM_32=y
CONFIG_HAS_EXYNOS4210=y
CONFIG_HAS_OMAP=y
# CONFIG_IPMMU_VMSA is not set

27
xen.json.nocpuid.patch Normal file
View file

@ -0,0 +1,27 @@
--- 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,42 +0,0 @@
--- xen-4.15.0/tools/ocaml/libs/xc/xenctrl_stubs.c.orig 2021-04-06 18:14:18.000000000 +0100
+++ xen-4.15.0/tools/ocaml/libs/xc/xenctrl_stubs.c 2021-04-11 21:38:22.684624663 +0100
@@ -43,7 +43,9 @@
#define _H(__h) ((xc_interface *)(__h))
#define _D(__d) ((uint32_t)Int_val(__d))
+#ifndef Val_none
#define Val_none (Val_int(0))
+#endif
#define string_of_option_array(array, index) \
((Field(array, index) == Val_none) ? NULL : String_val(Field(Field(array, index), 0)))
--- xen-4.15.0/tools/ocaml/libs/xl/xenlight_stubs.c.orig 2021-04-06 18:14:18.000000000 +0100
+++ xen-4.15.0/tools/ocaml/libs/xl/xenlight_stubs.c 2021-04-11 21:40:41.651115504 +0100
@@ -227,8 +227,12 @@
}
/* Option type support as per http://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php */
+#ifndef Val_none
#define Val_none Val_int(0)
+#endif
+#ifndef Some_val
#define Some_val(v) Field(v,0)
+#endif
static value Val_some(value v)
{
--- xen-4.15.0/tools/ocaml/libs/xentoollog/xentoollog_stubs.c.orig 2021-04-06 18:14:18.000000000 +0100
+++ xen-4.15.0/tools/ocaml/libs/xentoollog/xentoollog_stubs.c 2021-04-11 21:44:26.659529408 +0100
@@ -53,8 +53,12 @@
#include "_xtl_levels.inc"
/* Option type support as per http://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php */
+#ifndef Val_none
#define Val_none Val_int(0)
+#endif
+#ifndef Some_val
#define Some_val(v) Field(v,0)
+#endif
static value Val_some(value v)
{

22
xen.python3.12.patch Normal file
View file

@ -0,0 +1,22 @@
--- 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

939
xen.spec

File diff suppressed because it is too large Load diff

View file

@ -1,145 +0,0 @@
From 02d3a57d6466363b316b60ffbba414a4a2cb90c5 Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
Date: Thu, 25 Nov 2021 13:38:29 +0100
Subject: [PATCH] SUPPORT.md: limit support statement for Linux and Windows
frontends
Change the support state of Linux and Windows pv frontends from
"supported" to "supported with caveats" in order to reflect that the
frontends can probably be harmed by their respective backends.
Some of the Linux frontends have been hardened already.
This is XSA-376
Signed-off-by: Juergen Gross <jgross@suse.com>
---
SUPPORT.md | 57 +++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 48 insertions(+), 9 deletions(-)
diff --git a/SUPPORT.md b/SUPPORT.md
index 3a34933c89..6e3e305b01 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -411,7 +411,11 @@ Guest-side driver capable of speaking the Xen PV block protocol
Status, FreeBSD: Supported, Security support external
Status, NetBSD: Supported, Security support external
Status, OpenBSD: Supported, Security support external
- Status, Windows: Supported
+ Status, Windows: Supported, with caveats
+
+Windows frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### Netfront
@@ -421,20 +425,32 @@ Guest-side driver capable of speaking the Xen PV networking protocol
Status, FreeBSD: Supported, Security support external
Status, NetBSD: Supported, Security support external
Status, OpenBSD: Supported, Security support external
- Status, Windows: Supported
+ Status, Windows: Supported, with caveats
+
+Windows frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### PV Framebuffer (frontend)
Guest-side driver capable of speaking the Xen PV Framebuffer protocol
- Status, Linux (xen-fbfront): Supported
+ Status, Linux (xen-fbfront): Supported, with caveats
+
+Linux frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### PV display (frontend)
Guest-side driver capable of speaking the Xen PV display protocol
- Status, Linux: Supported (outside of "backend allocation" mode)
- Status, Linux: Experimental (in "backend allocation" mode)
+ Status, Linux, outside of "backend allocation" mode: Supported, with caveats
+ Status, Linux, "backend allocation" mode: Experimental
+
+Linux frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### PV Console (frontend)
@@ -443,7 +459,11 @@ Guest-side driver capable of speaking the Xen PV console protocol
Status, Linux (hvc_xen): Supported
Status, FreeBSD: Supported, Security support external
Status, NetBSD: Supported, Security support external
- Status, Windows: Supported
+ Status, Windows: Supported, with caveats
+
+Windows frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### PV keyboard (frontend)
@@ -451,11 +471,19 @@ Guest-side driver capable of speaking the Xen PV keyboard protocol.
Note that the "keyboard protocol" includes mouse / pointer /
multi-touch support as well.
- Status, Linux (xen-kbdfront): Supported
+ Status, Linux (xen-kbdfront): Supported, with caveats
+
+Linux frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### PV USB (frontend)
- Status, Linux: Supported
+ Status, Linux: Supported, with caveats
+
+Linux frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
### PV SCSI protocol (frontend)
@@ -464,6 +492,10 @@ multi-touch support as well.
NB that while the PV SCSI frontend is in Linux and tested regularly,
there is currently no xl support.
+Linux frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
+
### PV TPM (frontend)
Guest-side driver capable of speaking the Xen PV TPM protocol
@@ -486,7 +518,11 @@ Guest-side driver capable of making pv system calls
Guest-side driver capable of speaking the Xen PV sound protocol
- Status, Linux: Supported
+ Status, Linux: Supported, with caveats
+
+Linux frontend currently trusts the backend;
+bugs in the frontend which allow backend to cause mischief will not be
+considered security vulnerabilities.
## Virtual device support, host side
@@ -987,6 +1023,9 @@ are given the following labels:
This feature is security supported
by a different organization (not the XenProject).
+ The extent of support is defined by that organization.
+ It might be limited, e.g. like described in **Supported, with caveats**
+ below.
See **External security support** below.
* **Supported, with caveats**
--
2.26.2

30
xsa483.patch Normal file
View file

@ -0,0 +1,30 @@
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;

89
xsa484.patch Normal file
View file

@ -0,0 +1,89 @@
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

181
xsa486.patch Normal file
View file

@ -0,0 +1,181 @@
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)
{

43
xsa490-4.21.patch Normal file
View file

@ -0,0 +1,43 @@
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

211
xsa491-4.21.patch Normal file
View file

@ -0,0 +1,211 @@
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 {

264
xsa492-4.21-01.patch Normal file
View file

@ -0,0 +1,264 @@
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:
+ */

104
xsa492-4.21-02.patch Normal file
View file

@ -0,0 +1,104 @@
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:

87
xsa492-4.21-03.patch Normal file
View file

@ -0,0 +1,87 @@
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) )

81
xsa492-4.21-04.patch Normal file
View file

@ -0,0 +1,81 @@
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:

156
xsa492-4.21-05.patch Normal file
View file

@ -0,0 +1,156 @@
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;

84
xsa492-4.21-06.patch Normal file
View file

@ -0,0 +1,84 @@
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(),

202
xsa492-4.21-07.patch Normal file
View file

@ -0,0 +1,202 @@
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

85
xsa492-4.21-08.patch Normal file
View file

@ -0,0 +1,85 @@
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,

194
xsa492-4.21-09.patch Normal file
View file

@ -0,0 +1,194 @@
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:

97
xsa492-4.21-10.patch Normal file
View file

@ -0,0 +1,97 @@
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

128
xsa492-4.21-11.patch Normal file
View file

@ -0,0 +1,128 @@
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:

172
xsa492-4.21-12.patch Normal file
View file

@ -0,0 +1,172 @@
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

163
xsa492-4.21-13.patch Normal file
View file

@ -0,0 +1,163 @@
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
/*

179
xsa492-4.21-14.patch Normal file
View file

@ -0,0 +1,179 @@
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

108
xsa492-4.21-15.patch Normal file
View file

@ -0,0 +1,108 @@
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);
}
}

112
xsa492-4.21-16.patch Normal file
View file

@ -0,0 +1,112 @@
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

124
xsa492-4.21-17.patch Normal file
View file

@ -0,0 +1,124 @@
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,

94
xsa492-4.21-18.patch Normal file
View file

@ -0,0 +1,94 @@
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:

378
xsa492-4.21-19.patch Normal file
View file

@ -0,0 +1,378 @@
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,

123
xsa492-4.21-20.patch Normal file
View file

@ -0,0 +1,123 @@
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);

311
xsa493-4.21-01.patch Normal file
View file

@ -0,0 +1,311 @@
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

71
xsa493-4.21-02.patch Normal file
View file

@ -0,0 +1,71 @@
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)

37
xsa493-4.21-03.patch Normal file
View file

@ -0,0 +1,37 @@
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)

37
xsa493-4.21-04.patch Normal file
View file

@ -0,0 +1,37 @@
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)

404
xsa494-4.21.patch Normal file
View file

@ -0,0 +1,404 @@
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