[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [BUG v2] common/domctl: xsm update for get_domain_state access
- To: Jason Andryuk <jason.andryuk@xxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
- From: "Daniel P. Smith" <dpsmith@xxxxxxxxxxxxxxxxxxxx>
- Date: Thu, 19 Feb 2026 07:15:16 -0500
- Arc-authentication-results: i=1; mx.zohomail.com; dkim=pass header.i=apertussolutions.com; spf=pass smtp.mailfrom=dpsmith@xxxxxxxxxxxxxxxxxxxx; dmarc=pass header.from=<dpsmith@xxxxxxxxxxxxxxxxxxxx>
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1771503322; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=iVWQvwAHlrWAyEjqQylfVKxysdT9hftzKejSBSQ5E+8=; b=cZHqTHmU1lpYHnDDfzhfHCBO4vPUU9OpGvkv4YyVqqCnjSwPK2KF0ssbr6ndydHQ3OiNB2vyWqVwy3K1U6uslp34QkaNgWah1fJR570O6SrlHvxdXMz1q3zRr33GytLcuLmLlyl0oJhJUKf2c/SJKnG/YkfdL45iPP07Mfg7/P8=
- Arc-seal: i=1; a=rsa-sha256; t=1771503322; cv=none; d=zohomail.com; s=zohoarc; b=Yf2ed+1ZVgezyQnUVpKdPIRuYSGD4NHHCy01V44HWbPmsMewYQQqs3OrGn+4QxLyuQQQs6CNREnAKn2kA1DZksr1aJxyYJjz/4vCuHemrVSw/P0sZE7iGEhLsL70UJe3MEuuFx+l9yHPVEsdxudpNiHwQv7xVoo7ft+gtmuiIxg=
- Autocrypt: addr=dpsmith@xxxxxxxxxxxxxxxxxxxx; keydata= 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
- Cc: Chris Rogers <rogersc@xxxxxxxxxxxx>, Dmytro Firsov <dmytro_firsov@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>
- Delivery-date: Thu, 19 Feb 2026 12:15:55 +0000
- List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
On 2/18/26 18:04, Jason Andryuk wrote:
On 2026-02-18 14:08, Daniel P. Smith wrote:
When using XSM Flask, passing DOMID_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.
Fixes: 3ad3df1bd0aa ("xen: add new domctl get_domain_state")
Reported-by: Chris Rogers <rogersc@xxxxxxxxxxxx>
Reported-by: Dmytro Firsov <dmytro_firsov@xxxxxxxx>
Signed-off-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx>
---
Changes in v2:
- fix commit message
- init dom as -1
- rework loop logic to use test_and_clear_bit()
---
xen/common/domain.c | 27 +++++++++++++++++++++------
xen/common/domctl.c | 7 ++-----
2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/xen/common/domain.c b/xen/common/domain.c
index de6fdf59236e..2ffec331a8d1 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 = -1;
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,28 +242,39 @@ int get_domain_state(struct
xen_domctl_get_domain_state *info, struct domain *d,
Between the two hunks is this:
hdl = lock_dom_exc_handler();
/*
* Only domain registered for VIRQ_DOM_EXC event is allowed to query
* domains having changed state.
*/
if ( current->domain != hdl )
{
rc = -EACCES;
goto out;
}
So it is only the domain with VIRQ_DOM_EXC that can enter the while loop:
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 + 1);
if ( dom >= DOMID_FIRST_RESERVED )
break;
+
+ d = rcu_lock_domain_by_id(dom);
+ if ( d && xsm_get_domain_state(XSM_XS_PRIV, d) )
... if the VIRQ_DOM_EXC owner is denied for domain d ...
+ {
+ rcu_unlock_domain(d);
+ d = NULL;
+ continue;
... the caller would continue ...
+ }
+
if ( test_and_clear_bit(dom, dom_state_changed) )
... and this bit would never be cleared. Should the VIRQ_DOM_EXC owner
always get to clear the bit even if it cannot see the result? Is this
too much of a corner case to care about?
If we want to go down this discussion path, here is yet another example
access control decisions are getting codified directly against
properties of a domain, in particular against VIRQ's which were waived
from XSM control. If having access to certain VIRQ's is going to be a
privilege determination, then perhaps we should visit whether they
should be labeled objects like physical IRQs.
The patch generally seems okay aside from this.
{
*domid = dom;
- d = rcu_lock_domain_by_id(dom);
-
if ( d )
{
set_domain_state_info(info, d);
-
rcu_unlock_domain(d);
}
else
memset(info, 0, sizeof(*info));
rc = 0;
-
break;
}
+
+ if ( d )
+ {
+ rcu_unlock_domain(d);
+ d = NULL;
+ }
}
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);
With the initial NULL deref issue, I wondered if this wouldn't be better
off modified to drop the d param - xsm_get_domain_state(XSM_XS_PRIV) -
and changing flask permissions like:
allow dom0_t xen_t:xen get_domain_state;
That would gate the external call, and individual domain permissions
could be checked with xsm_getdomaininfo(), or a new hook if you don't
want to re-use.
But as your approach avoids passing NULL, it seems okay to me. It also
doesn't change the flask policy, which is nice.
That's a plain nack from me. Whether it is viewed as a pipe dream or
not, my goal continues to be to work towards enabling the ability to
have a truly disaggregated platform. In the original architecture, it
was envisioned to have multiple toolstack domains, each responsible for
a distinct set of domains. In terms of implementation, that would mean
multiple xenstored instances, each with a purview over a subset of domains.
v/r,
dps
|