diff mbox series

[3/3] x86/livepatch: Relax permissions on rodata too

Message ID 20240305121121.3527944-4-andrew.cooper3@citrix.com (mailing list archive)
State New
Headers show
Series x86/livepatch: Reinstate the ability to patch .rodata | expand

Commit Message

Andrew Cooper March 5, 2024, 12:11 p.m. UTC
This reinstates the capability to patch .rodata in load/unload hooks, which
was lost when we stopped using CR0.WP=0 to patch.

This turns out to be rather less of a large TODO than I thought at the time.

Fixes: 8676092a0f16 ("x86/livepatch: Fix livepatch application when CET is active")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
CC: Ross Lagerwall <ross.lagerwall@citrix.com>
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
---
 xen/arch/x86/livepatch.c    |  4 ++--
 xen/common/virtual_region.c | 12 ++++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

Comments

Andrew Cooper March 5, 2024, 1:02 p.m. UTC | #1
On 05/03/2024 12:11 pm, Andrew Cooper wrote:
> diff --git a/xen/common/virtual_region.c b/xen/common/virtual_region.c
> index d2efe9e11492..f45812483b8e 100644
> --- a/xen/common/virtual_region.c
> +++ b/xen/common/virtual_region.c
> @@ -91,9 +91,15 @@ void relax_virtual_region_perms(void)
>  
>      rcu_read_lock(&rcu_virtual_region_lock);
>      list_for_each_entry_rcu( region, &virtual_region_list, list )
> +    {
>          modify_xen_mappings_lite((unsigned long)region->text_start,
>                                   PAGE_ALIGN((unsigned long)region->text_end),
>                                   PAGE_HYPERVISOR_RWX);
> +        if ( region->rodata_start )
> +            modify_xen_mappings_lite((unsigned long)region->rodata_start,
> +                                     ROUNDUP((unsigned long)region->rodata_end, PAGE_SIZE),

I missed the final refresh to turn this to PAGE_ALIGN().  Fixed locally.

~Andrew
Roger Pau Monne March 5, 2024, 1:48 p.m. UTC | #2
On Tue, Mar 05, 2024 at 01:02:37PM +0000, Andrew Cooper wrote:
> On 05/03/2024 12:11 pm, Andrew Cooper wrote:
> > diff --git a/xen/common/virtual_region.c b/xen/common/virtual_region.c
> > index d2efe9e11492..f45812483b8e 100644
> > --- a/xen/common/virtual_region.c
> > +++ b/xen/common/virtual_region.c
> > @@ -91,9 +91,15 @@ void relax_virtual_region_perms(void)
> >  
> >      rcu_read_lock(&rcu_virtual_region_lock);
> >      list_for_each_entry_rcu( region, &virtual_region_list, list )
> > +    {
> >          modify_xen_mappings_lite((unsigned long)region->text_start,
> >                                   PAGE_ALIGN((unsigned long)region->text_end),
> >                                   PAGE_HYPERVISOR_RWX);
> > +        if ( region->rodata_start )
> > +            modify_xen_mappings_lite((unsigned long)region->rodata_start,
> > +                                     ROUNDUP((unsigned long)region->rodata_end, PAGE_SIZE),
> 
> I missed the final refresh to turn this to PAGE_ALIGN().  Fixed locally.

With that:

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks, Roger.
Ross Lagerwall March 7, 2024, 1:04 p.m. UTC | #3
On Tue, Mar 5, 2024 at 1:02 PM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> On 05/03/2024 12:11 pm, Andrew Cooper wrote:
> > diff --git a/xen/common/virtual_region.c b/xen/common/virtual_region.c
> > index d2efe9e11492..f45812483b8e 100644
> > --- a/xen/common/virtual_region.c
> > +++ b/xen/common/virtual_region.c
> > @@ -91,9 +91,15 @@ void relax_virtual_region_perms(void)
> >
> >      rcu_read_lock(&rcu_virtual_region_lock);
> >      list_for_each_entry_rcu( region, &virtual_region_list, list )
> > +    {
> >          modify_xen_mappings_lite((unsigned long)region->text_start,
> >                                   PAGE_ALIGN((unsigned long)region->text_end),
> >                                   PAGE_HYPERVISOR_RWX);
> > +        if ( region->rodata_start )
> > +            modify_xen_mappings_lite((unsigned long)region->rodata_start,
> > +                                     ROUNDUP((unsigned long)region->rodata_end, PAGE_SIZE),
>
> I missed the final refresh to turn this to PAGE_ALIGN().  Fixed locally.

In that case,

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
diff mbox series

Patch

diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index ee539f001b73..4f76127e1f77 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -62,7 +62,7 @@  int arch_livepatch_safety_check(void)
 int noinline arch_livepatch_quiesce(void)
 {
     /*
-     * Relax perms on .text to be RWX, so we can modify them.
+     * Relax perms on .text/.rodata, so we can modify them.
      *
      * This relaxes perms globally, but all other CPUs are waiting on us.
      */
@@ -75,7 +75,7 @@  int noinline arch_livepatch_quiesce(void)
 void noinline arch_livepatch_revive(void)
 {
     /*
-     * Reinstate perms on .text to be RX.  This also cleans out the dirty
+     * Reinstate perms on .text/.rodata.  This also cleans out the dirty
      * bits, which matters when CET Shstk is active.
      *
      * The other CPUs waiting for us could in principle have re-walked while
diff --git a/xen/common/virtual_region.c b/xen/common/virtual_region.c
index d2efe9e11492..f45812483b8e 100644
--- a/xen/common/virtual_region.c
+++ b/xen/common/virtual_region.c
@@ -91,9 +91,15 @@  void relax_virtual_region_perms(void)
 
     rcu_read_lock(&rcu_virtual_region_lock);
     list_for_each_entry_rcu( region, &virtual_region_list, list )
+    {
         modify_xen_mappings_lite((unsigned long)region->text_start,
                                  PAGE_ALIGN((unsigned long)region->text_end),
                                  PAGE_HYPERVISOR_RWX);
+        if ( region->rodata_start )
+            modify_xen_mappings_lite((unsigned long)region->rodata_start,
+                                     ROUNDUP((unsigned long)region->rodata_end, PAGE_SIZE),
+                                     PAGE_HYPERVISOR_RW);
+    }
     rcu_read_unlock(&rcu_virtual_region_lock);
 }
 
@@ -103,9 +109,15 @@  void tighten_virtual_region_perms(void)
 
     rcu_read_lock(&rcu_virtual_region_lock);
     list_for_each_entry_rcu( region, &virtual_region_list, list )
+    {
         modify_xen_mappings_lite((unsigned long)region->text_start,
                                  PAGE_ALIGN((unsigned long)region->text_end),
                                  PAGE_HYPERVISOR_RX);
+        if ( region->rodata_start )
+            modify_xen_mappings_lite((unsigned long)region->rodata_start,
+                                     ROUNDUP((unsigned long)region->rodata_end, PAGE_SIZE),
+                                     PAGE_HYPERVISOR_RO);
+    }
     rcu_read_unlock(&rcu_virtual_region_lock);
 }
 #endif /* CONFIG_X86 */