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

[xen staging-4.19] domctl: handle XEN_DOMCTL_irq_permission without acquiring domctl lock



commit 2ff10f2acd12060b885153e50857e9e8847f4f8c
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Jun 4 21:40:34 2026 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Thu Jun 4 21:47:50 2026 +0100

    domctl: handle XEN_DOMCTL_irq_permission without acquiring domctl lock
    
    With dedicated locking added, the domctl lock isn't required here anymore.
    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@xxxxxxxx>
    Acked-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx>
    Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
 xen/common/domctl.c     | 59 +++++++++++++++++++++++++++----------------------
 xen/include/xsm/dummy.h |  3 ++-
 xen/xsm/flask/hooks.c   |  2 +-
 3 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 6b0316aa5e..944878cdcf 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -454,6 +454,38 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) 
u_domctl)
         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_bind_pt_irq:
@@ -787,33 +819,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) 
u_domctl)
         }
         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;
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 6d2c9ddbb6..02829e806b 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -172,6 +172,7 @@ static XSM_INLINE int cf_check xsm_domctl(
     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();
@@ -561,7 +562,7 @@ static XSM_INLINE int cf_check xsm_unmap_domain_irq(
 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);
 }
 
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index c301750134..270e682883 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -684,6 +684,7 @@ static int cf_check flask_domctl(struct domain *d, unsigned 
int cmd,
     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();
@@ -691,7 +692,6 @@ static int cf_check flask_domctl(struct domain *d, unsigned 
int cmd,
 
     /* 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:
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.19



 


Rackspace

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