[PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry

Jason Andryuk posted 23 patches 3 days ago
[PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry
Posted by Jason Andryuk 3 days ago
With a split hardware and control domain, the control domain may still
want and xenstore access.  Currently this relies on init-dom0less to
seed the grants.  This is problematic since we don't want hardware
domain to be able to map the control domain's resources.  Instead have
the hypervisor see the grant table entry.  The grant is then accessible
as normal.

This is also useful with a xenstore stubdom to setup the xenbus page
much earlier.

This works with C xenstored.  OCaml xenstored does not use grants and
would fail to foreign map the page.

Signed-off-by: Jason Andryuk <jason.andryuk@amd.com>
---
 xen/arch/arm/dom0less-build.c |  9 +++++++++
 xen/common/grant_table.c      | 10 ++++++++++
 xen/include/xen/grant_table.h |  8 ++++++++
 3 files changed, 27 insertions(+)

diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 068bf99294..f1d5bbb097 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -21,6 +21,8 @@
 #include <asm/static-memory.h>
 #include <asm/static-shmem.h>
 
+static domid_t __initdata xs_domid = DOMID_INVALID;
+
 bool __init is_dom0less_mode(void)
 {
     struct bootmodules *mods = &bootinfo.modules;
@@ -753,6 +755,10 @@ static int __init alloc_xenstore_page(struct domain *d)
     interface->connection = XENSTORE_RECONNECT;
     unmap_domain_page(interface);
 
+    if ( xs_domid != DOMID_INVALID )
+        gnttab_seed_entry(d, GNTTAB_RESERVED_XENSTORE, xs_domid,
+                          gfn_x(gfn), GTF_permit_access);
+
     return 0;
 }
 
@@ -1173,6 +1179,9 @@ void __init create_domUs(void)
         if ( rc )
             panic("Could not set up domain %s (rc = %d)\n",
                   dt_node_name(node), rc);
+
+        if ( d_cfg.flags & XEN_DOMCTL_CDF_xs_domain )
+            xs_domid = d->domain_id;
     }
 }
 
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 6c77867f8c..ba93cdcbca 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -4346,6 +4346,16 @@ static void gnttab_usage_print(struct domain *rd)
         printk("no active grant table entries\n");
 }
 
+void gnttab_seed_entry(struct domain *d, int idx, domid_t be_domid,
+                       uint64_t frame, unsigned int flags)
+{
+    struct grant_table *gt = d->grant_table;
+
+    shared_entry_v1(gt, idx).flags = flags;
+    shared_entry_v1(gt, idx).domid = be_domid;
+    shared_entry_v1(gt, idx).frame = frame;
+}
+
 static void cf_check gnttab_usage_print_all(unsigned char key)
 {
     struct domain *d;
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
index 50edfecfb6..63150fa497 100644
--- a/xen/include/xen/grant_table.h
+++ b/xen/include/xen/grant_table.h
@@ -45,6 +45,10 @@ void grant_table_destroy(
     struct domain *d);
 void grant_table_init_vcpu(struct vcpu *v);
 
+/* Seed a gnttab entry for Hyperlaunch/dom0less. */
+void gnttab_seed_entry(struct domain *d, int idx, domid_t be_domid,
+                       uint64_t frame, unsigned int flags);
+
 /*
  * Check if domain has active grants and log first 10 of them.
  */
@@ -85,6 +89,10 @@ static inline void grant_table_destroy(struct domain *d) {}
 
 static inline void grant_table_init_vcpu(struct vcpu *v) {}
 
+static inline void gnttab_seed_entry(struct domain *d, int idx,
+                                     domid_t be_domid, uint64_t frame,
+                                     unsigned int flags) {}
+
 static inline void grant_table_warn_active_grants(struct domain *d) {}
 
 static inline int gnttab_release_mappings(struct domain *d) { return 0; }
-- 
2.48.1
Re: [PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry
Posted by Julien Grall 2 days, 1 hour ago
Hi,

On 06/03/2025 22:03, Jason Andryuk wrote:
> With a split hardware and control domain, the control domain may still
> want and xenstore access.  Currently this relies on init-dom0less to
> seed the grants.  This is problematic since we don't want hardware
> domain to be able to map the control domain's resources.  Instead have
> the hypervisor see the grant table entry.  The grant is then accessible
> as normal.

I am probably missing something, but why would run xenstored in the 
hardware domain rather than the control domain? Isn't xenstored more 
related to the VM management than HW?

Cheers,

-- 
Julien Grall
Re: [PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry
Posted by Jason Andryuk 1 day, 23 hours ago
On 2025-03-07 16:24, Julien Grall wrote:
> Hi,
> 
> On 06/03/2025 22:03, Jason Andryuk wrote:
>> With a split hardware and control domain, the control domain may still
>> want and xenstore access.  Currently this relies on init-dom0less to
>> seed the grants.  This is problematic since we don't want hardware
>> domain to be able to map the control domain's resources.  Instead have
>> the hypervisor see the grant table entry.  The grant is then accessible
>> as normal.
> 
> I am probably missing something, but why would run xenstored in the 
> hardware domain rather than the control domain? Isn't xenstored more 
> related to the VM management than HW?

I addressed this in my other email.  You're probably right that 
xenstored should run in control, but implementation details prevent that 
in the short term.

Regardless, of the xenstored placement, I think it's a better design for 
Xen to seed the grants.  With Xen allocating the xenstore page and event 
channel, and now seeding the grant table, they can just be used.  A 
xenstore stubdom can just establish all the connections without relying 
on another domain to perform an action.

I tested that with hyperlaunching the xenstore stubdom.  That is where 
the two XS_PRIV changes later in the series come from.  xenstore stubdom 
iterates the domains, reads the hvm_param for the event channel, and 
then runs introduce to set up the connection.

Regards,
Jason

Re: [PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry
Posted by Stefano Stabellini 1 day, 21 hours ago
On Fri, 7 Mar 2025, Jason Andryuk wrote:
> On 2025-03-07 16:24, Julien Grall wrote:
> > Hi,
> > 
> > On 06/03/2025 22:03, Jason Andryuk wrote:
> > > With a split hardware and control domain, the control domain may still
> > > want and xenstore access.  Currently this relies on init-dom0less to
> > > seed the grants.  This is problematic since we don't want hardware
> > > domain to be able to map the control domain's resources.  Instead have
> > > the hypervisor see the grant table entry.  The grant is then accessible
> > > as normal.
> > 
> > I am probably missing something, but why would run xenstored in the hardware
> > domain rather than the control domain? Isn't xenstored more related to the
> > VM management than HW?
> 
> I addressed this in my other email.  You're probably right that xenstored
> should run in control, but implementation details prevent that in the short
> term.

I wrote a longer reply here:
https://marc.info/?l=xen-devel&m=174139414000462

I think there are valid reasons to run xenstored in either the control
domain or the hardware domain, so it should be configurable. If no
specific preference is indicated, I would place it in the hardware
domain because the control domain must remain free from interference.
Given that I don't think we know for sure today whether the Xenstore
protocol could be a potential vector for interference, it is safer to
avoid placing it in the control domain by default.


> Regardless, of the xenstored placement, I think it's a better design for Xen
> to seed the grants.  With Xen allocating the xenstore page and event channel,
> and now seeding the grant table, they can just be used.  A xenstore stubdom
> can just establish all the connections without relying on another domain to
> perform an action.

+1


> I tested that with hyperlaunching the xenstore stubdom.  That is where the two
> XS_PRIV changes later in the series come from.  xenstore stubdom iterates the
> domains, reads the hvm_param for the event channel, and then runs introduce to
> set up the connection.
Re: [PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry
Posted by Stefano Stabellini 2 days, 20 hours ago
On Thu, 6 Mar 2025, Jason Andryuk wrote:
> With a split hardware and control domain, the control domain may still
> want and xenstore access.  Currently this relies on init-dom0less to
> seed the grants.  This is problematic since we don't want hardware
> domain to be able to map the control domain's resources.  Instead have
> the hypervisor see the grant table entry.  The grant is then accessible
> as normal.
> 
> This is also useful with a xenstore stubdom to setup the xenbus page
> much earlier.

Reading the patch, it seems that what is doing is letting the xenstore
domain map the domU's grant table page. Is that correct?

If so, I would suggest to update the commit message as follows:

With split hardware/control/xenstore domains, the xenstore domain may
still want to access other domains' xenstore page. Currently this relies
on init-dom0less to seed the grants from Dom0.  This is problematic
since we don't want the hardware domain to be able to map other domains'
resources without their permission.  Instead have the hypervisor seed
the grant table entry for every dom0less domain.  The grant is then
accessible as normal.


> This works with C xenstored.  OCaml xenstored does not use grants and
> would fail to foreign map the page.
> 
> Signed-off-by: Jason Andryuk <jason.andryuk@amd.com>
> ---
>  xen/arch/arm/dom0less-build.c |  9 +++++++++
>  xen/common/grant_table.c      | 10 ++++++++++
>  xen/include/xen/grant_table.h |  8 ++++++++
>  3 files changed, 27 insertions(+)
> 
> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> index 068bf99294..f1d5bbb097 100644
> --- a/xen/arch/arm/dom0less-build.c
> +++ b/xen/arch/arm/dom0less-build.c
> @@ -21,6 +21,8 @@
>  #include <asm/static-memory.h>
>  #include <asm/static-shmem.h>
>  
> +static domid_t __initdata xs_domid = DOMID_INVALID;
> +
>  bool __init is_dom0less_mode(void)
>  {
>      struct bootmodules *mods = &bootinfo.modules;
> @@ -753,6 +755,10 @@ static int __init alloc_xenstore_page(struct domain *d)
>      interface->connection = XENSTORE_RECONNECT;
>      unmap_domain_page(interface);
>  
> +    if ( xs_domid != DOMID_INVALID )
> +        gnttab_seed_entry(d, GNTTAB_RESERVED_XENSTORE, xs_domid,
> +                          gfn_x(gfn), GTF_permit_access);
> +
>      return 0;
>  }
>  
> @@ -1173,6 +1179,9 @@ void __init create_domUs(void)
>          if ( rc )
>              panic("Could not set up domain %s (rc = %d)\n",
>                    dt_node_name(node), rc);
> +
> +        if ( d_cfg.flags & XEN_DOMCTL_CDF_xs_domain )
> +            xs_domid = d->domain_id;
>      }
>  }
>  
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index 6c77867f8c..ba93cdcbca 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -4346,6 +4346,16 @@ static void gnttab_usage_print(struct domain *rd)
>          printk("no active grant table entries\n");
>  }
>  
> +void gnttab_seed_entry(struct domain *d, int idx, domid_t be_domid,
> +                       uint64_t frame, unsigned int flags)
> +{
> +    struct grant_table *gt = d->grant_table;
> +
> +    shared_entry_v1(gt, idx).flags = flags;
> +    shared_entry_v1(gt, idx).domid = be_domid;
> +    shared_entry_v1(gt, idx).frame = frame;
> +}
> +
>  static void cf_check gnttab_usage_print_all(unsigned char key)
>  {
>      struct domain *d;
> diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
> index 50edfecfb6..63150fa497 100644
> --- a/xen/include/xen/grant_table.h
> +++ b/xen/include/xen/grant_table.h
> @@ -45,6 +45,10 @@ void grant_table_destroy(
>      struct domain *d);
>  void grant_table_init_vcpu(struct vcpu *v);
>  
> +/* Seed a gnttab entry for Hyperlaunch/dom0less. */
> +void gnttab_seed_entry(struct domain *d, int idx, domid_t be_domid,
> +                       uint64_t frame, unsigned int flags);
> +
>  /*
>   * Check if domain has active grants and log first 10 of them.
>   */
> @@ -85,6 +89,10 @@ static inline void grant_table_destroy(struct domain *d) {}
>  
>  static inline void grant_table_init_vcpu(struct vcpu *v) {}
>  
> +static inline void gnttab_seed_entry(struct domain *d, int idx,
> +                                     domid_t be_domid, uint64_t frame,
> +                                     unsigned int flags) {}
> +
>  static inline void grant_table_warn_active_grants(struct domain *d) {}
>  
>  static inline int gnttab_release_mappings(struct domain *d) { return 0; }
> -- 
> 2.48.1
> 
>
Re: [PATCH 08/23] xen/arm: dom0less seed xenstore grant table entry
Posted by Jason Andryuk 2 days, 4 hours ago
On 2025-03-06 20:47, Stefano Stabellini wrote:
> On Thu, 6 Mar 2025, Jason Andryuk wrote:
>> With a split hardware and control domain, the control domain may still
>> want and xenstore access.  Currently this relies on init-dom0less to
>> seed the grants.  This is problematic since we don't want hardware
>> domain to be able to map the control domain's resources.  Instead have
>> the hypervisor see the grant table entry.  The grant is then accessible
>> as normal.
>>
>> This is also useful with a xenstore stubdom to setup the xenbus page
>> much earlier.
> 
> Reading the patch, it seems that what is doing is letting the xenstore
> domain map the domU's grant table page. Is that correct?

The end result is everything is setup for xenstored to map 
GNTTAB_RESERVED_XENSTORE at some time later.

> If so, I would suggest to update the commit message as follows:
> 
> With split hardware/control/xenstore domains, the xenstore domain may
> still want to access other domains' xenstore page. Currently this relies
> on init-dom0less to seed the grants from Dom0.  This is problematic
> since we don't want the hardware domain to be able to map other domains'
> resources without their permission.  Instead have the hypervisor seed
> the grant table entry for every dom0less domain.  The grant is then
> accessible as normal.

I'll go with a tweaked version of yours:
xenstored maps other domains' xenstore pages.  Currently this relies
on init-dom0less or xl to seed the grants from Dom0.  With split 
hardware/control/xenstore domains, this is problematic since we don't 
want the hardware domain to be able to map other domains' resources 
without their permission.  Instead have the hypervisor seed the grant 
table entry for every dom0less domain.  The grant is then accessible as 
normal.

Regards,
Jason