]> xenbits.xensource.com Git - xen.git/commitdiff
x86/boot: Support __ro_after_init
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 29 Nov 2021 20:11:01 +0000 (20:11 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 2 Dec 2021 20:02:55 +0000 (20:02 +0000)
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
xen/arch/x86/xen.lds.S
xen/include/asm-x86/setup.h
xen/include/xen/cache.h

index f5c15e45d6947789fd4a5602cb646d63ac96c543..723bd49c766fa530dd5766d0589bfb6f1c47aa92 100644 (file)
@@ -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);
 
index 87e344d4dd9721eed7273057927d3f58c7398308..4db5b404e0739c1cfc26743da758c9cce2bedb8c 100644 (file)
@@ -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)
index eb9d7b433c1335b24a41951096e04291d7f58f0d..7dc03b6b8d022c53c35e6918b3256f36b1cf6d30 100644 (file)
@@ -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[];
index 6ee174efa43937b79345709fa8ce75d017a65f50..f52a0aedf7680593fcaa724b6788b768b09f3594 100644 (file)
@@ -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 */