diff mbox series

[7/8] x86/boot: Support __ro_after_init

Message ID 20211130100445.31156-8-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show
Series x86: Support for __ro_after_init | expand

Commit Message

Andrew Cooper Nov. 30, 2021, 10:04 a.m. UTC
For security hardening reasons, it advantageous to make setup-once data
immutable after boot.  Borrow __ro_after_init from Linux.

On x86, place .data.ro_after_init at the start of .rodata, excluding it from
the early permission restrictions.  Re-apply RO restrictions to the whole of
.rodata in init_done(), attempting to reform the superpage if possible.

For architectures which don't implement __ro_after_init explicitly, variables
merges into .data.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Wei Liu <wl@xen.org>
---
 xen/arch/x86/setup.c        | 12 +++++++++++-
 xen/arch/x86/xen.lds.S      |  6 ++++++
 xen/include/asm-x86/setup.h |  1 +
 xen/include/xen/cache.h     |  2 ++
 4 files changed, 20 insertions(+), 1 deletion(-)

Comments

Jan Beulich Dec. 2, 2021, 1:10 p.m. UTC | #1
On 30.11.2021 11:04, Andrew Cooper wrote:
> For security hardening reasons, it advantageous to make setup-once data
> immutable after boot.  Borrow __ro_after_init from Linux.
> 
> On x86, place .data.ro_after_init at the start of .rodata, excluding it from
> the early permission restrictions.  Re-apply RO restrictions to the whole of
> .rodata in init_done(), attempting to reform the superpage if possible.
> 
> For architectures which don't implement __ro_after_init explicitly, variables
> merges into .data.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>
diff mbox series

Patch

diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 8329263430ed..3bbc46f244b9 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -663,6 +663,11 @@  static void noreturn init_done(void)
     init_xenheap_pages(__pa(start), __pa(end));
     printk("Freed %lukB init memory\n", (end - start) >> 10);
 
+    /* Mark .rodata/ro_after_init as RO.  Maybe reform the superpage. */
+    modify_xen_mappings((unsigned long)&__2M_rodata_start,
+                        (unsigned long)&__2M_rodata_end,
+                        PAGE_HYPERVISOR_RO);
+
     startup_cpu_idle_loop();
 }
 
@@ -1541,8 +1546,13 @@  void __init noreturn __start_xen(unsigned long mbi_p)
                         (unsigned long)&__2M_text_end,
                         PAGE_HYPERVISOR_RX);
 
+    /* Mark .data.ro_after_init as RW.  Maybe shatters the .rodata superpage. */
+    modify_xen_mappings((unsigned long)&__ro_after_init_start,
+                        (unsigned long)&__ro_after_init_end,
+                        PAGE_HYPERVISOR_RW);
+
     /* Mark .rodata as RO. */
-    modify_xen_mappings((unsigned long)&__2M_rodata_start,
+    modify_xen_mappings((unsigned long)&__ro_after_init_end,
                         (unsigned long)&__2M_rodata_end,
                         PAGE_HYPERVISOR_RO);
 
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 87e344d4dd97..4db5b404e073 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -97,6 +97,12 @@  SECTIONS
   __2M_rodata_start = .;       /* Start of 2M superpages, mapped RO. */
   DECL_SECTION(.rodata) {
        _srodata = .;
+
+       __ro_after_init_start = .;
+       *(.data.ro_after_init)
+       . = ALIGN(PAGE_SIZE);
+       __ro_after_init_end = .;
+
        /* Bug frames table */
        __start_bug_frames = .;
        *(.bug_frames.0)
diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
index eb9d7b433c13..34edea405f85 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -6,6 +6,7 @@ 
 
 extern const char __2M_text_start[], __2M_text_end[];
 extern const char __2M_rodata_start[], __2M_rodata_end[];
+extern const char __ro_after_init_start[], __ro_after_init_end[];
 extern char __2M_init_start[], __2M_init_end[];
 extern char __2M_rwdata_start[], __2M_rwdata_end[];
 
diff --git a/xen/include/xen/cache.h b/xen/include/xen/cache.h
index 6ee174efa439..f52a0aedf768 100644
--- a/xen/include/xen/cache.h
+++ b/xen/include/xen/cache.h
@@ -15,4 +15,6 @@ 
 #define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
 #endif
 
+#define __ro_after_init __section(".data.ro_after_init")
+
 #endif /* __LINUX_CACHE_H */