From d00aad3b132fc21e263ac71bf74a4df7bd30aad5 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Tue, 14 Jul 2026 13:13:12 +0200 Subject: [PATCH] xen/dmop: check number of input buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hypercall requires at least one input buffer, as both arch-specific implementations of dm_op() unconditionally assume ->buf[0] to be valid (and not stack rubble). Additionally, XEN_DMOP_modified_memory requires two input buffers, yet the code was assuming the second buffer to always be provided by the user when checking for the number of extents. In case the caller sets nr_bufs to 1, the code in modified_memory() will read stack garbage as the size of the buffer, thus allowing the caller some degree of insight on the contents of the stack by probing whether the hypercall returns -EINVAL or -EFAULT as a result of such bogus call. This is XSA-506 / CVE-2026-62433. Fixes: e3b93b3c5954 ("dmop: add xendevicemodel_modified_memory_bulk()") Fixes: 85cb15dfe4d1 ("x86/hvm/dmop: only copy what is needed to/from the guest") Signed-off-by: Roger Pau Monné Reviewed-by: Andrew Cooper Reviewed-by: Jan Beulich (cherry picked from commit aef948a300da3f10ca5d033177dbd794afc45e2b) --- xen/arch/x86/hvm/dm.c | 9 +++++++++ xen/common/dm.c | 3 +++ 2 files changed, 12 insertions(+) diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c index 066498e07e..1f44fff12a 100644 --- a/xen/arch/x86/hvm/dm.c +++ b/xen/arch/x86/hvm/dm.c @@ -494,6 +494,12 @@ int dm_op(const struct dmop_args *op_args) struct xen_dm_op_modified_memory *data = &op.u.modified_memory; + if ( op_args->nr_bufs != 2 ) + { + rc = -EINVAL; + break; + } + rc = modified_memory(d, op_args, data); const_op = !rc; break; @@ -655,6 +661,9 @@ int compat_dm_op( unsigned int i; int rc; + if ( !nr_bufs ) + return -ENODATA; + if ( nr_bufs > ARRAY_SIZE(args.buf) ) return -E2BIG; diff --git a/xen/common/dm.c b/xen/common/dm.c index 201b652deb..8689728ab7 100644 --- a/xen/common/dm.c +++ b/xen/common/dm.c @@ -26,6 +26,9 @@ long do_dm_op( struct dmop_args args; int rc; + if ( !nr_bufs ) + return -ENODATA; + if ( nr_bufs > ARRAY_SIZE(args.buf) ) return -E2BIG;