From c3ff11b11c21777a9b1c616607705f3a7340b391 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Tue, 2 Apr 2024 16:19:36 +0200 Subject: [PATCH 64/67] x86/livepatch: Relax permissions on rodata too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Roger Pau Monné Reviewed-by: Ross Lagerwall master commit: b083b1c393dc8961acf0959b1d2e0ad459985ae3 master date: 2024-03-07 14:24:42 +0000 --- xen/arch/x86/livepatch.c | 4 ++-- xen/common/virtual_region.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c index ee539f001b..4f76127e1f 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 9c566f8ec9..aefc08e75f 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, + PAGE_ALIGN((unsigned long)region->rodata_end), + 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, + PAGE_ALIGN((unsigned long)region->rodata_end), + PAGE_HYPERVISOR_RO); + } rcu_read_unlock(&rcu_virtual_region_lock); } #endif /* CONFIG_X86 */ -- 2.44.0