Skip to content

Commit d07a980

Browse files
heicarstMartin Schwidefsky
authored andcommitted
s390: add proper __ro_after_init support
On s390 __ro_after_init is currently mapped to __read_mostly which means that data marked as __ro_after_init will not be protected. Reason for this is that the common code __ro_after_init implementation is x86 centric: the ro_after_init data section was added to rodata, since x86 enables write protection to kernel text and rodata very late. On s390 we have write protection for these sections enabled with the initial page tables. So adding the ro_after_init data section to rodata does not work on s390. In order to make __ro_after_init work properly on s390 move the ro_after_init data, right behind rodata. Unlike the rodata section it will be marked read-only later after all init calls happened. This s390 specific implementation adds new __start_ro_after_init and __end_ro_after_init labels. Everything in between will be marked read-only after the init calls happened. In addition to the __ro_after_init data move also the exception table there, since from a practical point of view it fits the __ro_after_init requirements. Signed-off-by: Heiko Carstens <[email protected]> Reviewed-by: Kees Cook <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]>
1 parent 32fb2fc commit d07a980

File tree

5 files changed

+19
-11
lines changed

5 files changed

+19
-11
lines changed

arch/s390/include/asm/cache.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,4 @@
1515

1616
#define __read_mostly __attribute__((__section__(".data..read_mostly")))
1717

18-
/* Read-only memory is marked before mark_rodata_ro() is called. */
19-
#define __ro_after_init __read_mostly
20-
2118
#endif

arch/s390/include/asm/sections.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
#include <asm-generic/sections.h>
55

66
extern char _eshared[], _ehead[];
7+
extern char __start_ro_after_init[], __end_ro_after_init[];
78

89
#endif

arch/s390/kernel/vmlinux.lds.S

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
*/
1212
#define BSS_FIRST_SECTIONS *(.bss..swapper_pg_dir)
1313

14+
/* Handle ro_after_init data on our own. */
15+
#define RO_AFTER_INIT_DATA
16+
1417
#include <asm-generic/vmlinux.lds.h>
1518

1619
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
@@ -56,7 +59,14 @@ SECTIONS
5659
_eshared = .; /* End of shareable data */
5760
_sdata = .; /* Start of data section */
5861

59-
EXCEPTION_TABLE(16) :data
62+
. = ALIGN(PAGE_SIZE);
63+
__start_ro_after_init = .;
64+
.data..ro_after_init : {
65+
*(.data..ro_after_init)
66+
}
67+
EXCEPTION_TABLE(16)
68+
. = ALIGN(PAGE_SIZE);
69+
__end_ro_after_init = .;
6070

6171
RW_DATA_SECTION(0x100, PAGE_SIZE, THREAD_SIZE)
6272

arch/s390/mm/init.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,10 @@ void __init paging_init(void)
111111

112112
void mark_rodata_ro(void)
113113
{
114-
/* Text and rodata are already protected. Nothing to do here. */
115-
pr_info("Write protecting the kernel read-only data: %luk\n",
116-
((unsigned long)&_eshared - (unsigned long)&_stext) >> 10);
114+
unsigned long size = __end_ro_after_init - __start_ro_after_init;
115+
116+
set_memory_ro((unsigned long)__start_ro_after_init, size >> PAGE_SHIFT);
117+
pr_info("Write protected read-only-after-init data: %luk\n", size >> 10);
117118
}
118119

119120
void __init mem_init(void)

arch/s390/mm/vmem.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,14 +373,13 @@ int vmem_add_mapping(unsigned long start, unsigned long size)
373373
*/
374374
void __init vmem_map_init(void)
375375
{
376-
unsigned long ro_start, ro_end;
376+
unsigned long size = _eshared - _stext;
377377
struct memblock_region *reg;
378378

379379
for_each_memblock(memory, reg)
380380
vmem_add_mem(reg->base, reg->size);
381-
ro_start = PFN_ALIGN((unsigned long)&_stext);
382-
ro_end = (unsigned long)&_eshared & PAGE_MASK;
383-
set_memory_ro(ro_start, (ro_end - ro_start) >> PAGE_SHIFT);
381+
set_memory_ro((unsigned long)_stext, size >> PAGE_SHIFT);
382+
pr_info("Write protected kernel read-only data: %luk\n", size >> 10);
384383
}
385384

386385
/*

0 commit comments

Comments
 (0)