The directory and Rock Ridge / SUSP walk in iso9660_dir() derives several
lengths directly from attacker-controlled on-disk fields without validating
them. libfsimage is used by pygrub, which parses the filesystem of an
untrusted guest disk image from dom0, so these are reachable across a trust
boundary.
Five related problems are addressed:
* The directory record loop advances by
idr = (char *)idr + idr->length.l
and only stops on length.l == 0. A record whose length is smaller than
the fixed part of the on-disk layout cannot hold its own mandatory
fields, yet the body still reads name_len/extent/size and computes the
System Use area length from it. Require length to cover at least the
fixed record (sizeof(*idr) - sizeof(idr->name)) before entering the body.
This is CVE-2026-42494.
* The System Use area length is computed before the inner loop as
rr_len = idr->length.l - idr->name_len.l
- sizeof(struct iso_directory_record) + sizeof(idr->name);
in unsigned arithmetic. If length.l is smaller than name_len.l plus the
fixed record size, rr_len underflows to a huge value and the whole SUSP
walk runs off the directory buffer. Guard the subtraction and treat such
records as having no System Use area.
This is CVE-2026-42495.
* Inside the loop, each entry is consumed with
rr_len -= rr_ptr.rr->len;
rr_ptr.ptr += rr_ptr.rr->len;
with no lower or upper bound on the entry's own len byte. A len of 0
spins forever; a len greater than the remaining rr_len underflows it and
walks past the buffer. Validate 4 <= len <= rr_len at the top of the
loop and stop on violation: a structurally broken entry stream cannot be
advanced reliably, so continuing is not meaningful.
This is CVE-2026-62423.
* The NM handler subtracted the 5-byte SUSP/NM header from len without a
lower-bound check, underflowing name_len (the original report). The
generic check above only guarantees len >= 4; NM has an extra flags byte,
so keep an NM-specific len >= 5 check.
This is CVE-2026-62424.
* The CE continuation resets rr_ptr/rr_len from ce.offset and ce.size, both
image-controlled, into the fixed single-sector RRCONT_BUF with no bounds
check. Reject a window that does not fit in the buffer.
This is CVE-2026-62425.
This is XSA-497.
Signed-off-by: Syed Abdul Khaliq <abdul@bugqore.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
As we ignore cachability aspects of insns, they're treated like simple
MOVs.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
The RTDS repl_budget trace record now contains the vCPU priority
level. Update xenalyze to account for the additional field and print
it when dumping the trace event.
Without this change, xenalyze interprets the record using the old
layout, causing the deadline and budget fields to be decoded from the
wrong offsets.
Fixes: 463b958317 ("xen:rtds: towards work conserving RTDS")
Signed-off-by: Ryoji Okamoto <okamoto@valinux.co.jp>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
AFL has pointed out that the op_bytes-is-not-0 assertion in common SIMD
handling can trigger for these insns. Indeed when the (relevant part of)
the controlling mask register is 0, no memory is accessed at all. Leave
op_bytes unaltered in this case, to engage the short-circuiting in common
SIMD handling when fault_suppression is true and op_bytes is 0.
While there also correct a related typo in the test harness.
Fixes: 65f82d4ce1 ("x86emul: support AVX512{F,_VBMI2} compress/expand insns")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Move the little bit that's still left in x86/x86_emulate.c into a __XEN__
conditional in x86/x86_emulate/x86_emulate.c. Move what are roughly the
test/fuzzing harness counterparts from there into the corresponding #else.
Interestingly more recent gcc takes issue with three static const arrays
which are unused when HVM=n (noticeable in particular in the shim build).
Apparently such are diagnosed only when present in the top-level file, but
not when living in an #include-d one.
Requested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
There is no need to store the page pointers simply to transcribe the same
information into iov later. Drop the guest_data intermediate array.
These days, linux has a maximum limit of 1024 iovs. Libc under the hood will
subdivide the submission if necessary, which is why our general case of 1026
submissions works.
xenforeignmemory_map() maps the requested guest memory contiguously, and
except for PV pagetable frames, we submit contiguously into the stream. When
safe to do, merge adjacent vectors by extending iov_len, reducing the
likelihood that libc needs to subdivide the submission.
Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Construct all of the headers together in one block, rather than a field at a
time. Initialise as many of the fields as possible at declaration time.
Start filling in iov[] earlier, to allow for future simplifications.
No practical change.
Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
For reasons which escape me, rec_pfns are allocated separately to the rest of
the batch allocations.
Allocate them all together. This will allow for future simplifications to be
performed in an incremental mannor.
No functional change.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Construct xc_sr_rhdr directly rather than in two halves.
Use size_t for combined_len, which allows the later size check to spot a few
more cases which might have truncated.
Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Nul-terminated strings are passed in all cases, so the strlen() can very
well be invoked by the function itself. In preparation for a hypervisor
change also include the nul terminator in the size calculation.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Reviewed-by: Daniel P. Smith <dpsmith@apertussolutions.com>
More similar to other implementation.
posix_memalign was adde in NetBSD 8.0, released on July 17, 2018
and went out of support on May 4, 2024.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
This was reported to the security team, demonstrating that code execution
could be achieved, but without a demonstration of a priviliege boundary being
bypassed.
Still, it's a high risk path with no obvious evidence of having been used even
for debugging, so remove the environment variable and use the build time
$(libdir)/xenfsimage path only.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
%4.4x and alike format specifiers can be expressed shorter as %04x or, as
e.g. dump_ioapic() has it, %.4x.
In dump_fpu()'s XMM register dumping, also move away from showing bogus
xmm03 and alike. The proper register name is xmm3 for that particular
example.
Also strip trailing whitespace from lines touched.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
In preparation for a hypervisor change also include the nul terminator in
the size calculations. (Note that xc_flask_getbool_byid() doesn't support
FLASK_GETBOOL's "ID being -1" variant of operation, and hence doesn't need
fiddling with.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
GCC 15.2 with Alpine Linux 3.24 fails with -Werror=nonnull, complaining that
we're calling bzero(NULL, 128).
This is a legitimate diagnostic. xenalyze has it's own error() function
shadowing the standard library one, and can in principle return when p is
NULL.
Extend the check in error() with ERR_MAX_TOLERABLE to short circuit the
variable tolerance check.
Suggested-by: Anthony PERARD <anthony.perard@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
The Arm zImage loader currently computes the kernel load address and
places the DTB/initrd in one local flow. The hardware-domain memory
allocator needs to reuse those placement rules before it chooses bank 0,
but open-coding the same calculations there would make the fix harder to
audit.
Split the existing logic into small helpers:
- kernel_zimage_place_in_bank() computes the zImage load address for a
given bank.
- first_bank_can_fit_modules() checks the aggregate first-bank
footprint.
- find_dtb_initrd_placement() chooses the DTB/initrd location within a
known bank and kernel range.
Rename place_modules() to place_dtb_initrd() so the code distinguishes
the kernel image from the DTB/initrd placement area. Also update the
comments linking the hypervisor and toolstack placement paths.
While moving the code, spell the 2MB alignment mask with MB(2) rather
than open-coding (2 << 20). This is mechanical and keeps the generated
value unchanged.
The caller still panics in the same cases as before, so this is intended
to be behavior preserving.
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
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>
Ocaml's lib directory layout changed in 5.0: the unix and dynlink
libraries have been moved out of the standard library directory into
subdirectories. The compiler still locates them automatically but emits
an ocaml_deprecated_auto_include alert when doing so.
This patch sets the paths explicitly with -I +unix and -I +dynlink to
silence the alert.
Signed-off-by: Guillaume Thouvenin <guillaume.thouvenin@vates.tech>
Reviewed-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Tested-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Adjust the mask calculation in case the last range is merged with the
previous one, as then the mask must be calculated from the previous range,
which the current one has been merged into.
Instead of fixing the off-by-one in place, move the calculation of the bit
change mask to the next loop, after the ranges have been merged. This
simplifies the logic by consolidating mask calculation in a single place,
possibly making it less error prone in the future.
Also add a test case that triggers the bug being fixed by this commit.
Fixes: c5c45bcbd6 ("pdx: introduce a new compression algorithm based on region offsets")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Right now lz4, unlike every other compression scheme, unconditionally uses
Xen's unsafe decompressor. Make it consistent with all other compression
schemes by using liblz4.
The unsafe decompression is still required for the MiniOS build, so rename
xg_dom_decompress_lz4.c to xg_dom_decompress_unsafe_lz4.c and drop the
non-MiniOS content.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
As with other compression libraries, group liblz4 into ZLIB_{CFLAGS,LIBS}.
Add the packages to the Debian Trixie build containers for coverage.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
The logic to populate memnodemap in populate_memnodemap() assumes that all
ranges are aligned to the hash shift, this however is only true for the
first address in a memory affinity node. Any subsequent ranges belonging
to the same node might not be aligned to the hash shift value.
Such lack of alignment causes issues to the logic in populate_memnodemap(),
as then the tail of the range might not be properly accounted for and setup
in memnodemap. Fix this by forcing the start address of all regions to
be aligned to the hash shift; if such alignment causes a region overlap it
would always be between regions on the same node, and hence will never
cause setup issues of the memnodemap array.
Introduce two additional test cases to the user-space NUMA setup unit
testing, first test case is the native memory affinity and memory map of
the system where this issue was found, second test case is a simplification
to demonstrate the original problem more clearly.
Fixes: 1666086b00 ("x86/NUMA: improve memnode_shift calculation for multi node system")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
NUMA setup, like PDX, requires certain amount of logic to configure the
internal structures and parameters for NUMA operation. Introduce some very
basic testing that allows building and testing NUMA setup logic in as a
user-space unit test. This allows feeding synthetic memory affinity and
map to the logic, allowing to reproduce bugs that would otherwise need
access to real systems with such a configuration.
For the time being introduce a single test case, based on a known working
NUMA setup for an AMD Turin system. Also the testing after setup is
currently limited to ensuring the start and end RAM region addresses fall
into a correctly setup memory block.
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Commit 23e2479ff9 ("xen/domain: introduce DOMID_ANY") broke at least:
* xenstored domains
* The Python bindings
* The Ocaml bindings (i.e XAPI, and therefore XenServer/XCP-ng)
by causing Xen to reject 0 (the wildcard sentinel since the start of Xen) and
DOMID_INVALID (since 4.21) without adjusting the callers of xc_domain_create().
Under other circumstances I'd revert, but xenstored has gained a dependent use
of DOMID_ANY.
Fix up the remaining in-tree callers of xc_domain_create(), which covers
init-xenstore-domain and the python bindings.
The Ocaml C bindings, like libxc itself, expose this ABI detail to their
caller, but in this case the caller is still internal to the bindings as a
whole. Adjust the default value in the internal transformation, adding
domid_any for legibility.
Leave a very clear message in CHANGELOG.md that all external callers need
altering.
Fixes: 23e2479ff9 ("xen/domain: introduce DOMID_ANY")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Pau Ruiz Safont <pau.safont@vates.tech>
xen_pfn_t is not an unsigned long on all architectures. In particular,
Arm32 builds see it as a 64-bit type, so printing it with %lx triggers
a -Werror=format build failure.
Use PRI_xen_pfn for the GFN diagnostics instead.
Fixes: 66c982a5d3 ("tests/paging-mempool: Extend to test P2M relocation")
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Init helpers sometimes fail to rebuild after switching branches,
which results in runtime faults.
Fix this by adding missing DEPS_INCLUDE to the Makefile.
Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
Reviewed-by: Denis Mukhin <dmukhin@ford.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
With unprivileged domains now capable to use the @releaseDomain watch,
there is no reason not to remove any node permissions which relate to
a domain which has been removed.
This resolves a complex scenario where a new domain could inherit the
permissions of an old one with the same domid.
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Currently the @releaseDomain watch is allowed for dom0 only. This is
problematic for guests which want to give other domains access to
Xenstore entries, as they have no simple way to tell when such a
domain is stopped.
Allow @releaseDomain to be usable by all domains as the default.
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Add support for using DOMID_ANY in node permissions to indicate that
all domains are allowed to access the node.
Add a new feature bit for indicating the support of DOMID_ANY.
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Add a new symbol DOMID_ANY to improve the readability of the code.
Update all relevant domid_alloc() call sites and harden the domid_alloc()
input value check.
Also, fix problem with passing invalid domain IDs in
XEN_DOMCTL_createdomain: turns out libxl__domain_make() (toolstack)
uses 0xffff as domain ID.
Fix failing tools tests too.
Amends: 2d50650607 ("xen/domain: unify domain ID allocation")
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
Very old glibc (2.4 in the observed case) declares strndup() only when
_GNU_SOURCE is defined.
Fixes: ad860c6454 ("tools/xl: add xl commands for xenstore quota operations")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
libxl_nocpuid.c needs the same treatment as libxl_cpuid.c
Fixes: f6c6f2679d ("libxl: Convert libxl__object_to_json() to json-c")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
XENMAPSPACE_gmfn_range was found to be buggy with overlapping ranges, and the
fix is sufficiently far from clear that yours truly decided a test was in
order.
XENMAPSPACE_gmfn_range is exposed by xendevicemodel_relocate_memory() so take
the opportunity to create a better example for others to copy.
The test works as follows. Populate 2M of RAM in the guest, marking the pages
so they can be identified later. Then construct four relocation test
cases (overlapping vs non-overlapping, forwards vs backwards) using the marks
in the guest pages to confirm that the P2M was adjusted correctly.
The use of XEN_DOMCTL_CDF_iommu forces xenmem_add_to_physmap() to limit the
iteration count to a maximum of 16. Use this to force a continuation and
exercise more of the logic.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
... ahead of extending it with a second test.
Rename run_tests() to test_paging_mempool_size() and have it return int so the
new run_tests() can decide whether to run subsequent tests or not.
Comment the parameters to xc_domain_populate_physmap_exact() to make it
clearer what's going on, and remove the page added to the physmap when the
test is done.
No practical change.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Provide support for this insn, which is a prereq to FRED. CPUID-wise,
while its and FRED's enumerators were already introduced, their dependency
still needs adding.
While adding a testcase, also add a SWAPGS one. In order to not affect
the behavior of pre-existing tests, install write_{segment,msr} hooks
only transiently.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Only the setup_virtual_bridge_port() function was used. As such merge
that with _setup_bridge_port() and leave that as the remaining function.
The last user of setup_physical_bridge_port() was removed in 9fabe55939
("tools/hotplug: Remove network-*").
Signed-off-by: Elliott Mitchell <ehem+xen@m5p.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
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: 1f9d04fb02 ("xenstored: allow guest to shutdown all its watches/transactions")
Signed-off-by: Juergen Gross <jgross@suse.com>
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>
create_node() is called only for issued xenstore commands. This means
that the "conn" parameter is never NULL.
Remove checking whether "conn" is not NULL.
Coverity ID: 1690859
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
ENODATA is not defined on FreeBSD:
xenpm.c:1380:17: error: use of undeclared identifier 'ENODATA'
1380 | errno = ENODATA;
| ^
1 error generated.
Fixes: edb657887a ("xenpm: Add get-core-temp subcommand")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Add a "-d <depth>" parameter to xenstore-watch, allowing to specify
the depth parameter of the XS_WATCH command.
Using "-d" without support of depth by xenstored will refuse to set
the watch(es).
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Add XENSTORE_SERVER_FEATURE_WATCHDEPTH to the available features now
that all needed support has been added.
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>