[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v1] nestedsvm: Fix multi-byte IO port intercept check


  • To: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
  • Date: Fri, 11 Sep 2026 12:13:56 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yTOA312Mu0a3gMt/IzddjVv8a+YbDC1M4IugOsgTUbk=; b=R+Gptu/ulti0TSOwPfCiWt5u4fwtAlggP7n8hsQhBrhyLSgnZxElZB1dDsfMJveL2SM3oIr8SM55eyoIMS6J9q839x4rCXd//xV7fls3jMG4tRRnarJEK4SZk4ggr4WvCVpotYgxd2KL0DNC9gZseeyKEDsvTJiI/n+kD2LMOGYSPVIv3Fj0TSNNg9K7HpEzQNydO4/hGizs36I91hm9lcBRsqfdIfWa8emKD6DnUPd0XcyJc4FfjYP5MHl6/qiflx2gpNIeF/B+ovKq8L85WhFMYjyuRKDKqGCdgPI3P9ooDms+v1Od54OyEgtqZ5n7K8fN+Lw3wwao6YV+9VqAgQ==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=f0fyzPXtQc7rXWByvpcdFAY5r7OPBeAVPo3r+nByDrAdBrlNFVZnuqgFosih8o6Iu2VZBpFT0Mn9uXNJ6SEQHzCJ8CCmLN/w358YLJQfC1rHb87YdlT2KTXVTe1WcXdyN2pfycXsTqP1DJY45qzl5iYuZUANt3VvHnNATrNBgFs7pWMgoCuodWBLzn+FlOmG8F2WPDAImAL9W/lbfHtQiRx9x07T4rTvvrrWJo08LI+DATTdIjT33mWmjJxBHbHHqXtiV4cTuaBQ5EBhRpJQVuWnCVjZfh9R7ztQ55jK8C1xv28ZItvzh4bRHjMohjljKec9SFftEeROGhfWKo+UBw==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: Jan Beulich <jbeulich@xxxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>, Jason Andryuk <jason.andryuk@xxxxxxx>, Teddy Astie <teddy.astie@xxxxxxxxxx>
  • Delivery-date: Fri, 11 Sep 2026 11:14:15 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 9/11/26 11:06 AM, Andrew Cooper wrote:
On 10/09/2026 5:39 pm, Ross Lagerwall wrote:
For multi-byte IO port accesses, the APM says that SVM should intercept
if any of the corresponding permission bits are set. However, the code
has this backwards and only intercepts if all the permission bits are
set.

By any chance is this for the root partition, with 0xcf9 permitted but
0xcf8,a,b intercepted?

Yes, for the root partition. It intercepts 0xcf8,c,d,e,f and permits
0xcf9,a,b.


This affects Hyper-V since it does not generally set all the permission
bits of the multi-byte ports it allows its root partition to access.
This results in an L2 root partition that cannot do PCI config space
accesses and therefore cannot access its NVMe disk to continue booting.

Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
  xen/arch/x86/hvm/svm/nestedsvm.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index 5adb1bd72c4d..249fde43b5be 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -852,7 +852,7 @@ nsvm_vmcb_guest_intercepts_ioio(paddr_t iopm_pa, uint64_t 
exitinfo1)
      for ( io_bitmap = hvm_map_guest_frame_ro(gfn, 0); ; )
      {
          enabled = io_bitmap && test_bit(port, io_bitmap);
-        if ( !enabled || !--size )
+        if ( enabled || !--size )
              break;
          if ( unlikely(++port == 8 * PAGE_SIZE) )
          {

While this does fix a bug, I think the behaviour is still unsafe.

For starters, 'enabled' is a terrible name and is probably a major
factor in getting this wrong.  It should be 'intercepted'.

hvm_map_guest_frame_ro() can return NULL for several reasons[1],
including ballooned out frames/etc.  It is not by accident that a set
bit means intercept; it's for the same reason that the byte sequence FF
FF is #UD (with the PUSH that should have been in that position moving
elsewhere in the opcode table), and that's because ~0 is the return
value for "nothing here on the memory bus".

Either way, if io_bitmap is NULL, the port should be intercepted rather
than access being permitted, so the other prior line needs to be of the
form:

     intercepted = !io_bitmap || test_bit(port, io_bitmap);


OK, I'll send an updated patch.

Ross



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.