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

[BUG] common/domctl: xsm update for get_domain_state access



When using XSM Flask, passing DOMIND_INVALID will result in a NULL pointer
reference from the passing of NULL as the target domain to
xsm_get_domain_state(). Simply not invoking xsm_get_domain_state() when the
target domain is NULL opens the opportunity to circumvent the XSM
get_domain_state access check. This is due to the fact that the call to
xsm_domctl() for get_domain_state op is a no-op check, deferring to
xsm_get_domain_state().

Modify the helper get_domain_state() to ensure the requesting domain has
get_domain_state access for the target domain, whether the target domain is
explicitly set or implicitly determined with a domain state search. In the case
of access not being allowed for a domain found during an implicit search, the
search will continue to the next domain whose state has changed.

Signed-off-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx>
Reported-by: Chris Rogers <rogersc@xxxxxxxxxxxx>
Fixes: 3ad3df1bd0aa ("xen: add new domctl get_domain_state")
---
 xen/common/domain.c | 22 +++++++++++++++++++---
 xen/common/domctl.c |  7 ++-----
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/xen/common/domain.c b/xen/common/domain.c
index de6fdf59236e..4886c59c874c 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -210,7 +210,7 @@ static void set_domain_state_info(struct 
xen_domctl_get_domain_state *info,
 int get_domain_state(struct xen_domctl_get_domain_state *info, struct domain 
*d,
                      domid_t *domid)
 {
-    unsigned int dom;
+    unsigned int dom = 0;
     int rc = -ENOENT;
     struct domain *hdl;
 
@@ -219,6 +219,10 @@ int get_domain_state(struct xen_domctl_get_domain_state 
*info, struct domain *d,
 
     if ( d )
     {
+        rc = xsm_get_domain_state(XSM_XS_PRIV, d);
+        if ( rc )
+            return rc;
+
         set_domain_state_info(info, d);
 
         return 0;
@@ -238,10 +242,10 @@ int get_domain_state(struct xen_domctl_get_domain_state 
*info, struct domain *d,
 
     while ( dom_state_changed )
     {
-        dom = find_first_bit(dom_state_changed, DOMID_MASK + 1);
+        dom = find_next_bit(dom_state_changed, DOMID_MASK + 1, dom);
         if ( dom >= DOMID_FIRST_RESERVED )
             break;
-        if ( test_and_clear_bit(dom, dom_state_changed) )
+        if ( test_bit(dom, dom_state_changed) )
         {
             *domid = dom;
 
@@ -249,6 +253,15 @@ int get_domain_state(struct xen_domctl_get_domain_state 
*info, struct domain *d,
 
             if ( d )
             {
+                rc = xsm_get_domain_state(XSM_XS_PRIV, d);
+                if ( rc )
+                {
+                    rcu_unlock_domain(d);
+                    rc = -ENOENT;
+                    dom++;
+                    continue;
+                }
+
                 set_domain_state_info(info, d);
 
                 rcu_unlock_domain(d);
@@ -256,10 +269,13 @@ int get_domain_state(struct xen_domctl_get_domain_state 
*info, struct domain *d,
             else
                 memset(info, 0, sizeof(*info));
 
+            clear_bit(dom, dom_state_changed);
             rc = 0;
 
             break;
         }
+
+        dom++;
     }
 
  out:
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 29a7726d32d0..2eedc639c72a 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -860,12 +860,9 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) 
u_domctl)
         break;
 
     case XEN_DOMCTL_get_domain_state:
-        ret = xsm_get_domain_state(XSM_XS_PRIV, d);
-        if ( ret )
-            break;
-
-        copyback = 1;
         ret = get_domain_state(&op->u.get_domain_state, d, &op->domain);
+        if ( !ret )
+            copyback = 1;
         break;
 
     default:
-- 
2.39.5




 


Rackspace

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