Mailing List Archive

[xen staging] x86/boot: Support __ro_after_init
commit 05657c6d1821dfc4e9a618767a942b3555406046
Author: Andrew Cooper <andrew.cooper3@citrix.com>
AuthorDate: Mon Nov 29 20:11:01 2021 +0000
Commit: Andrew Cooper <andrew.cooper3@citrix.com>
CommitDate: Thu Dec 2 20:02:55 2021 +0000

x86/boot: Support __ro_after_init

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>
---
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(-)

diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index f5c15e45d6..723bd49c76 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();
}

@@ -1535,6 +1540,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
/*
* All Xen mappings are currently RWX 2M superpages. Restrict to:
* text - RX
+ * ro_after_init - RW for now, RO later
* rodata - RO
* init - keep RWX, discarded entirely later
* data/bss - RW
@@ -1543,7 +1549,11 @@ void __init noreturn __start_xen(unsigned long mbi_p)
(unsigned long)&__2M_text_end,
PAGE_HYPERVISOR_RX);

- modify_xen_mappings((unsigned long)&__2M_rodata_start,
+ modify_xen_mappings((unsigned long)&__ro_after_init_start,
+ (unsigned long)&__ro_after_init_end,
+ PAGE_HYPERVISOR_RW);
+
+ 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 87e344d4dd..4db5b404e0 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 eb9d7b433c..7dc03b6b8d 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -5,6 +5,7 @@
#include <asm/numa.h>

extern const char __2M_text_start[], __2M_text_end[];
+extern const char __ro_after_init_start[], __ro_after_init_end[];
extern const char __2M_rodata_start[], __2M_rodata_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 6ee174efa4..f52a0aedf7 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 */
--
generated by git-patchbot for /home/xen/git/xen.git#staging