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

[xen stable-4.15] VT-d: avoid infinite recursion on domain_context_mapping_one() error path



commit b3ee746000f37f38b41bfec97d37dbb1d4f3eca4
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Fri Apr 8 15:01:42 2022 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Fri Apr 8 15:01:42 2022 +0200

    VT-d: avoid infinite recursion on domain_context_mapping_one() error path
    
    Despite the comment there infinite recursion was still possible, by
    flip-flopping between two domains. This is because prev_dom is derived
    from the DID found in the context entry, which was already updated by
    the time error recovery is invoked. Simply introduce yet another mode
    flag to prevent rolling back an in-progress roll-back of a prior
    mapping attempt.
    
    Also drop the existing recursion prevention for having been dead anyway:
    Earlier in the function we already bail when prev_dom == domain.
    
    Fixes: 8f41e481b485 ("VT-d: re-assign devices directly")
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    master commit: 99d829dba1390b98a3ca07b365713e62182ee7ca
    master date: 2022-04-07 12:31:16 +0200
---
 xen/drivers/passthrough/vtd/iommu.c | 9 ++++-----
 xen/drivers/passthrough/vtd/vtd.h   | 3 ++-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/xen/drivers/passthrough/vtd/iommu.c 
b/xen/drivers/passthrough/vtd/iommu.c
index e9b6ed64e9..68dd2f5500 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1586,7 +1586,7 @@ int domain_context_mapping_one(
     if ( !seg && !rc )
         rc = me_wifi_quirk(domain, bus, devfn, domid, pgd_maddr, mode);
 
-    if ( rc )
+    if ( rc && !(mode & MAP_ERROR_RECOVERY) )
     {
         if ( !prev_dom ||
              /*
@@ -1596,13 +1596,12 @@ int domain_context_mapping_one(
               */
              (prev_dom == dom_io && !pdev) )
             ret = domain_context_unmap_one(domain, iommu, bus, devfn);
-        else if ( prev_dom != domain ) /* Avoid infinite recursion. */
+        else
             ret = domain_context_mapping_one(prev_dom, iommu, bus, devfn, pdev,
                                              DEVICE_DOMID(prev_dom, pdev),
                                              DEVICE_PGTABLE(prev_dom, pdev),
-                                             mode & MAP_WITH_RMRR) < 0;
-        else
-            ret = 1;
+                                             (mode & MAP_WITH_RMRR) |
+                                             MAP_ERROR_RECOVERY) < 0;
 
         if ( !ret && pdev && pdev->devfn == devfn )
             check_cleanup_domid_map(domain, pdev, iommu);
diff --git a/xen/drivers/passthrough/vtd/vtd.h 
b/xen/drivers/passthrough/vtd/vtd.h
index e4ab242fee..cb2df76eed 100644
--- a/xen/drivers/passthrough/vtd/vtd.h
+++ b/xen/drivers/passthrough/vtd/vtd.h
@@ -29,7 +29,8 @@
 #define MAP_WITH_RMRR         (1u << 0)
 #define MAP_OWNER_DYING       (1u << 1)
 #define MAP_SINGLE_DEVICE     (1u << 2)
-#define UNMAP_ME_PHANTOM_FUNC (1u << 3)
+#define MAP_ERROR_RECOVERY    (1u << 3)
+#define UNMAP_ME_PHANTOM_FUNC (1u << 4)
 
 /* Allow for both IOAPIC and IOSAPIC. */
 #define IO_xAPIC_route_entry IO_APIC_route_entry
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.15



 


Rackspace

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