2019-10-11 00:09:13

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 00/29] vmlinux.lds.h: Refactor EXCEPTION_TABLE and NOTES

Arch maintainers: please send Acks (if you haven't already) for your
respective linker script changes; the intention is for this series to
land via -tip.

v1: https://lore.kernel.org/lkml/[email protected]
v2: clean up commit messages, rename RO_EXCEPTION_TABLE (bp)


This series works to move the linker sections for NOTES and
EXCEPTION_TABLE into the RO_DATA area, where they belong on most
(all?) architectures. The problem being addressed was the discovery
by Rick Edgecombe that the exception table was accidentally marked
executable while he was developing his execute-only-memory series. When
permissions were flipped from readable-and-executable to only-executable,
the exception table became unreadable, causing things to explode rather
badly. :)

Roughly speaking, the steps are:

- regularize the linker names for PT_NOTE and PT_LOAD program headers
(to "note" and "text" respectively)
- regularize restoration of linker section to program header assignment
(when PT_NOTE exists)
- move NOTES into RO_DATA
- finish macro naming conversions for RO_DATA and RW_DATA
- move EXCEPTION_TABLE into RO_DATA on architectures where this is clear
- clean up some x86-specific reporting of kernel memory resources
- switch x86 linker fill byte from x90 (NOP) to 0xcc (INT3), just because
I finally realized what that trailing ": 0x9090" meant -- and we should
trap, not slide, if execution lands in section padding

Thanks!

-Kees

Kees Cook (29):
powerpc: Rename "notes" PT_NOTE to "note"
powerpc: Remove PT_NOTE workaround
powerpc: Rename PT_LOAD identifier "kernel" to "text"
alpha: Rename PT_LOAD identifier "kernel" to "text"
ia64: Rename PT_LOAD identifier "code" to "text"
s390: Move RO_DATA into "text" PT_LOAD Program Header
x86: Restore "text" Program Header with dummy section
vmlinux.lds.h: Provide EMIT_PT_NOTE to indicate export of .notes
vmlinux.lds.h: Move Program Header restoration into NOTES macro
vmlinux.lds.h: Move NOTES into RO_DATA
vmlinux.lds.h: Replace RODATA with RO_DATA
vmlinux.lds.h: Replace RO_DATA_SECTION with RO_DATA
vmlinux.lds.h: Replace RW_DATA_SECTION with RW_DATA
vmlinux.lds.h: Allow EXCEPTION_TABLE to live in RO_DATA
x86: Actually use _etext for end of text segment
x86: Move EXCEPTION_TABLE to RO_DATA segment
alpha: Move EXCEPTION_TABLE to RO_DATA segment
arm64: Move EXCEPTION_TABLE to RO_DATA segment
c6x: Move EXCEPTION_TABLE to RO_DATA segment
h8300: Move EXCEPTION_TABLE to RO_DATA segment
ia64: Move EXCEPTION_TABLE to RO_DATA segment
microblaze: Move EXCEPTION_TABLE to RO_DATA segment
parisc: Move EXCEPTION_TABLE to RO_DATA segment
powerpc: Move EXCEPTION_TABLE to RO_DATA segment
xtensa: Move EXCEPTION_TABLE to RO_DATA segment
x86/mm: Remove redundant &s on addresses
x86/mm: Report which part of kernel image is freed
x86/mm: Report actual image regions in /proc/iomem
x86: Use INT3 instead of NOP for linker fill bytes

arch/alpha/kernel/vmlinux.lds.S | 18 +++++-----
arch/arc/kernel/vmlinux.lds.S | 6 ++--
arch/arm/kernel/vmlinux-xip.lds.S | 4 +--
arch/arm/kernel/vmlinux.lds.S | 4 +--
arch/arm64/kernel/vmlinux.lds.S | 9 ++---
arch/c6x/kernel/vmlinux.lds.S | 8 ++---
arch/csky/kernel/vmlinux.lds.S | 5 ++-
arch/h8300/kernel/vmlinux.lds.S | 9 ++---
arch/hexagon/kernel/vmlinux.lds.S | 5 ++-
arch/ia64/kernel/vmlinux.lds.S | 20 +++++------
arch/m68k/kernel/vmlinux-nommu.lds | 4 +--
arch/m68k/kernel/vmlinux-std.lds | 2 +-
arch/m68k/kernel/vmlinux-sun3.lds | 2 +-
arch/microblaze/kernel/vmlinux.lds.S | 8 ++---
arch/mips/kernel/vmlinux.lds.S | 15 ++++----
arch/nds32/kernel/vmlinux.lds.S | 5 ++-
arch/nios2/kernel/vmlinux.lds.S | 5 ++-
arch/openrisc/kernel/vmlinux.lds.S | 7 ++--
arch/parisc/kernel/vmlinux.lds.S | 11 +++---
arch/powerpc/kernel/vmlinux.lds.S | 37 ++++---------------
arch/riscv/kernel/vmlinux.lds.S | 5 ++-
arch/s390/kernel/vmlinux.lds.S | 12 +++----
arch/sh/kernel/vmlinux.lds.S | 3 +-
arch/sparc/kernel/vmlinux.lds.S | 3 +-
arch/um/include/asm/common.lds.S | 3 +-
arch/unicore32/kernel/vmlinux.lds.S | 5 ++-
arch/x86/include/asm/processor.h | 2 +-
arch/x86/include/asm/sections.h | 1 -
arch/x86/kernel/setup.c | 12 ++++++-
arch/x86/kernel/vmlinux.lds.S | 16 ++++-----
arch/x86/mm/init.c | 8 ++---
arch/x86/mm/init_64.c | 16 +++++----
arch/x86/mm/pti.c | 2 +-
arch/xtensa/kernel/vmlinux.lds.S | 8 ++---
include/asm-generic/vmlinux.lds.h | 53 ++++++++++++++++++++--------
35 files changed, 159 insertions(+), 174 deletions(-)

--
2.17.1


Kees Cook (29):
powerpc: Rename "notes" PT_NOTE to "note"
powerpc: Remove PT_NOTE workaround
powerpc: Rename PT_LOAD identifier "kernel" to "text"
alpha: Rename PT_LOAD identifier "kernel" to "text"
ia64: Rename PT_LOAD identifier "code" to "text"
s390: Move RO_DATA into "text" PT_LOAD Program Header
x86: Restore "text" Program Header with dummy section
vmlinux.lds.h: Provide EMIT_PT_NOTE to indicate export of .notes
vmlinux.lds.h: Move Program Header restoration into NOTES macro
vmlinux.lds.h: Move NOTES into RO_DATA
vmlinux.lds.h: Replace RODATA with RO_DATA
vmlinux.lds.h: Replace RO_DATA_SECTION with RO_DATA
vmlinux.lds.h: Replace RW_DATA_SECTION with RW_DATA
vmlinux.lds.h: Allow EXCEPTION_TABLE to live in RO_DATA
x86: Actually use _etext for end of text segment
x86: Move EXCEPTION_TABLE to RO_DATA segment
alpha: Move EXCEPTION_TABLE to RO_DATA segment
arm64: Move EXCEPTION_TABLE to RO_DATA segment
c6x: Move EXCEPTION_TABLE to RO_DATA segment
h8300: Move EXCEPTION_TABLE to RO_DATA segment
ia64: Move EXCEPTION_TABLE to RO_DATA segment
microblaze: Move EXCEPTION_TABLE to RO_DATA segment
parisc: Move EXCEPTION_TABLE to RO_DATA segment
powerpc: Move EXCEPTION_TABLE to RO_DATA segment
xtensa: Move EXCEPTION_TABLE to RO_DATA segment
x86/mm: Remove redundant &s on addresses
x86/mm: Report which part of kernel image is freed
x86/mm: Report actual image regions in /proc/iomem
x86: Use INT3 instead of NOP for linker fill bytes

arch/alpha/kernel/vmlinux.lds.S | 18 +++++-----
arch/arc/kernel/vmlinux.lds.S | 6 ++--
arch/arm/kernel/vmlinux-xip.lds.S | 4 +--
arch/arm/kernel/vmlinux.lds.S | 4 +--
arch/arm64/kernel/vmlinux.lds.S | 10 +++---
arch/c6x/kernel/vmlinux.lds.S | 8 ++---
arch/csky/kernel/vmlinux.lds.S | 5 ++-
arch/h8300/kernel/vmlinux.lds.S | 9 ++---
arch/hexagon/kernel/vmlinux.lds.S | 5 ++-
arch/ia64/kernel/vmlinux.lds.S | 20 +++++------
arch/m68k/kernel/vmlinux-nommu.lds | 4 +--
arch/m68k/kernel/vmlinux-std.lds | 2 +-
arch/m68k/kernel/vmlinux-sun3.lds | 2 +-
arch/microblaze/kernel/vmlinux.lds.S | 8 ++---
arch/mips/kernel/vmlinux.lds.S | 15 ++++----
arch/nds32/kernel/vmlinux.lds.S | 5 ++-
arch/nios2/kernel/vmlinux.lds.S | 5 ++-
arch/openrisc/kernel/vmlinux.lds.S | 7 ++--
arch/parisc/kernel/vmlinux.lds.S | 11 +++---
arch/powerpc/kernel/vmlinux.lds.S | 37 ++++---------------
arch/riscv/kernel/vmlinux.lds.S | 5 ++-
arch/s390/kernel/vmlinux.lds.S | 12 +++----
arch/sh/kernel/vmlinux.lds.S | 3 +-
arch/sparc/kernel/vmlinux.lds.S | 3 +-
arch/um/include/asm/common.lds.S | 3 +-
arch/unicore32/kernel/vmlinux.lds.S | 5 ++-
arch/x86/include/asm/processor.h | 2 +-
arch/x86/include/asm/sections.h | 1 -
arch/x86/kernel/setup.c | 12 ++++++-
arch/x86/kernel/vmlinux.lds.S | 16 ++++-----
arch/x86/mm/init.c | 8 ++---
arch/x86/mm/init_64.c | 16 +++++----
arch/x86/mm/pti.c | 2 +-
arch/xtensa/kernel/vmlinux.lds.S | 8 ++---
include/asm-generic/vmlinux.lds.h | 53 ++++++++++++++++++++--------
35 files changed, 159 insertions(+), 175 deletions(-)

--
2.17.1


2019-10-11 00:09:20

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 15/29] x86: Actually use _etext for end of text segment

Various calculations are using the end of the exception table (which
does not need to be executable) as the end of the text segment. Instead,
in preparation for moving the exception table into RO_DATA, move _etext
after the exception table and update the calculations.

Signed-off-by: Kees Cook <[email protected]>
---
arch/x86/include/asm/sections.h | 1 -
arch/x86/kernel/vmlinux.lds.S | 7 +++----
arch/x86/mm/init_64.c | 6 +++---
arch/x86/mm/pti.c | 2 +-
4 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h
index 71b32f2570ab..036c360910c5 100644
--- a/arch/x86/include/asm/sections.h
+++ b/arch/x86/include/asm/sections.h
@@ -6,7 +6,6 @@
#include <asm/extable.h>

extern char __brk_base[], __brk_limit[];
-extern struct exception_table_entry __stop___ex_table[];
extern char __end_rodata_aligned[];

#if defined(CONFIG_X86_64)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 41362e90142d..a1a758e25b2b 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -143,15 +143,14 @@ SECTIONS
*(.text.__x86.indirect_thunk)
__indirect_thunk_end = .;
#endif
-
- /* End of text section */
- _etext = .;
} :text = 0x9090

EXCEPTION_TABLE(16)

- /* .text should occupy whole number of pages */
+ /* End of text section, which should occupy whole number of pages */
+ _etext = .;
. = ALIGN(PAGE_SIZE);
+
X86_ALIGN_RODATA_BEGIN
RO_DATA(PAGE_SIZE)
X86_ALIGN_RODATA_END
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index a6b5c653727b..26299e9ce6da 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1263,7 +1263,7 @@ int kernel_set_to_readonly;
void set_kernel_text_rw(void)
{
unsigned long start = PFN_ALIGN(_text);
- unsigned long end = PFN_ALIGN(__stop___ex_table);
+ unsigned long end = PFN_ALIGN(_etext);

if (!kernel_set_to_readonly)
return;
@@ -1282,7 +1282,7 @@ void set_kernel_text_rw(void)
void set_kernel_text_ro(void)
{
unsigned long start = PFN_ALIGN(_text);
- unsigned long end = PFN_ALIGN(__stop___ex_table);
+ unsigned long end = PFN_ALIGN(_etext);

if (!kernel_set_to_readonly)
return;
@@ -1301,7 +1301,7 @@ void mark_rodata_ro(void)
unsigned long start = PFN_ALIGN(_text);
unsigned long rodata_start = PFN_ALIGN(__start_rodata);
unsigned long end = (unsigned long) &__end_rodata_hpage_align;
- unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
+ unsigned long text_end = PFN_ALIGN(&_etext);
unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
unsigned long all_end;

diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index 7f2140414440..44a9f068eee0 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -574,7 +574,7 @@ static void pti_clone_kernel_text(void)
*/
unsigned long start = PFN_ALIGN(_text);
unsigned long end_clone = (unsigned long)__end_rodata_aligned;
- unsigned long end_global = PFN_ALIGN((unsigned long)__stop___ex_table);
+ unsigned long end_global = PFN_ALIGN((unsigned long)_etext);

if (!pti_kernel_image_global_ok())
return;
--
2.17.1

2019-10-11 00:09:22

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 28/29] x86/mm: Report actual image regions in /proc/iomem

The resource reservations in /proc/iomem made for the kernel image did
not reflect the gaps between text, rodata, and data. Add the "rodata"
resource and update the start/end calculations to match the respective
calls to free_kernel_image_pages().

Before (booted with "nokaslr" for easier comparison):

00100000-bffd9fff : System RAM
01000000-01e011d0 : Kernel code
01e011d1-025619bf : Kernel data
02a95000-035fffff : Kernel bss

After:

00100000-bffd9fff : System RAM
01000000-01e011d0 : Kernel code
02000000-023d4fff : Kernel rodata
02400000-025619ff : Kernel data
02a95000-035fffff : Kernel bss

Signed-off-by: Kees Cook <[email protected]>
---
arch/x86/kernel/setup.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 77ea96b794bd..591e885a852e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -143,6 +143,13 @@ struct boot_params boot_params;
/*
* Machine setup..
*/
+static struct resource rodata_resource = {
+ .name = "Kernel rodata",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
+};
+
static struct resource data_resource = {
.name = "Kernel data",
.start = 0,
@@ -951,7 +958,9 @@ void __init setup_arch(char **cmdline_p)

code_resource.start = __pa_symbol(_text);
code_resource.end = __pa_symbol(_etext)-1;
- data_resource.start = __pa_symbol(_etext);
+ rodata_resource.start = __pa_symbol(__start_rodata);
+ rodata_resource.end = __pa_symbol(__end_rodata)-1;
+ data_resource.start = __pa_symbol(_sdata);
data_resource.end = __pa_symbol(_edata)-1;
bss_resource.start = __pa_symbol(__bss_start);
bss_resource.end = __pa_symbol(__bss_stop)-1;
@@ -1040,6 +1049,7 @@ void __init setup_arch(char **cmdline_p)

/* after parse_early_param, so could debug it */
insert_resource(&iomem_resource, &code_resource);
+ insert_resource(&iomem_resource, &rodata_resource);
insert_resource(&iomem_resource, &data_resource);
insert_resource(&iomem_resource, &bss_resource);

--
2.17.1

2019-10-11 00:09:32

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 13/29] vmlinux.lds.h: Replace RW_DATA_SECTION with RW_DATA

Rename RW_DATA_SECTION to RW_DATA. (Calling this a "section" is a lie,
since it's multiple sections and section flags cannot be applied to
the macro.)

Signed-off-by: Kees Cook <[email protected]>
---
arch/alpha/kernel/vmlinux.lds.S | 2 +-
arch/arc/kernel/vmlinux.lds.S | 2 +-
arch/arm/kernel/vmlinux-xip.lds.S | 2 +-
arch/arm/kernel/vmlinux.lds.S | 2 +-
arch/arm64/kernel/vmlinux.lds.S | 2 +-
arch/csky/kernel/vmlinux.lds.S | 2 +-
arch/h8300/kernel/vmlinux.lds.S | 2 +-
arch/hexagon/kernel/vmlinux.lds.S | 2 +-
arch/m68k/kernel/vmlinux-nommu.lds | 2 +-
arch/m68k/kernel/vmlinux-std.lds | 2 +-
arch/m68k/kernel/vmlinux-sun3.lds | 2 +-
arch/microblaze/kernel/vmlinux.lds.S | 2 +-
arch/nds32/kernel/vmlinux.lds.S | 2 +-
arch/nios2/kernel/vmlinux.lds.S | 2 +-
arch/openrisc/kernel/vmlinux.lds.S | 2 +-
arch/parisc/kernel/vmlinux.lds.S | 2 +-
arch/riscv/kernel/vmlinux.lds.S | 2 +-
arch/s390/kernel/vmlinux.lds.S | 2 +-
arch/sh/kernel/vmlinux.lds.S | 2 +-
arch/sparc/kernel/vmlinux.lds.S | 2 +-
arch/unicore32/kernel/vmlinux.lds.S | 2 +-
arch/xtensa/kernel/vmlinux.lds.S | 2 +-
include/asm-generic/vmlinux.lds.h | 4 ++--
23 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index af411817dd7d..edc45f45523b 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -50,7 +50,7 @@ SECTIONS

_sdata = .; /* Start of rw data section */
_data = .;
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)

.got : {
*(.got)
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 7d1d27066deb..54139a6f469b 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -101,7 +101,7 @@ SECTIONS
* 1. this is .data essentially
* 2. THREAD_SIZE for init.task, must be kernel-stk sz aligned
*/
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)

_edata = .;

diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index d2a9651c24ad..21b8b271c80d 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -112,7 +112,7 @@ SECTIONS

. = ALIGN(THREAD_SIZE);
_sdata = .;
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
.data.ro_after_init : AT(ADDR(.data.ro_after_init) - LOAD_OFFSET) {
*(.data..ro_after_init)
}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 068db6860867..319ccb10846a 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -141,7 +141,7 @@ SECTIONS
__init_end = .;

_sdata = .;
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .;

BSS_SECTION(0, 0, 0)
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index e7dafc29b1fa..a4b3e6c0680c 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -214,7 +214,7 @@ SECTIONS

_data = .;
_sdata = .;
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)

/*
* Data written with the MMU off but read with the MMU on requires
diff --git a/arch/csky/kernel/vmlinux.lds.S b/arch/csky/kernel/vmlinux.lds.S
index 8598bd7a7bcd..2ff37beaf2bf 100644
--- a/arch/csky/kernel/vmlinux.lds.S
+++ b/arch/csky/kernel/vmlinux.lds.S
@@ -50,7 +50,7 @@ SECTIONS

_sdata = .;
RO_DATA(PAGE_SIZE)
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .;

EXCEPTION_TABLE(L1_CACHE_BYTES)
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index d3247d33b115..2ac7bdcd2fe0 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -47,7 +47,7 @@ SECTIONS
#endif
_sdata = . ;
__data_start = . ;
- RW_DATA_SECTION(0, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(0, PAGE_SIZE, THREAD_SIZE)
#if defined(CONFIG_ROMKERNEL)
#undef ADDR
#endif
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index 0145251fa317..0ca2471ddb9f 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -49,7 +49,7 @@ SECTIONS
INIT_DATA_SECTION(PAGE_SIZE)

_sdata = .;
- RW_DATA_SECTION(32,PAGE_SIZE,_THREAD_SIZE)
+ RW_DATA(32,PAGE_SIZE,_THREAD_SIZE)
RO_DATA(PAGE_SIZE)
_edata = .;

diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds
index de80f8b8ae78..7b975420c3d9 100644
--- a/arch/m68k/kernel/vmlinux-nommu.lds
+++ b/arch/m68k/kernel/vmlinux-nommu.lds
@@ -61,7 +61,7 @@ SECTIONS {

_sdata = .;
RO_DATA(PAGE_SIZE)
- RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(16, PAGE_SIZE, THREAD_SIZE)
_edata = .;

EXCEPTION_TABLE(16)
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index 625a5785804f..6e7eb49ed985 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -33,7 +33,7 @@ SECTIONS

RODATA

- RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(16, PAGE_SIZE, THREAD_SIZE)

BSS_SECTION(0, 0, 0)

diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 9868270b0984..1a0ad6b6dd8c 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -30,7 +30,7 @@ SECTIONS

EXCEPTION_TABLE(16) :data
_sdata = .; /* Start of rw data section */
- RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) :data
+ RW_DATA(16, PAGE_SIZE, THREAD_SIZE) :data
/* End of data goes *here* so that freeing init code works properly. */
_edata = .;
NOTES
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 2299694748ea..b8efb08204a1 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -69,7 +69,7 @@ SECTIONS {
}

_sdata = . ;
- RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(32, PAGE_SIZE, THREAD_SIZE)
_edata = . ;

/* Under the microblaze ABI, .sdata and .sbss must be contiguous */
diff --git a/arch/nds32/kernel/vmlinux.lds.S b/arch/nds32/kernel/vmlinux.lds.S
index 10ff570ba95b..f679d3397436 100644
--- a/arch/nds32/kernel/vmlinux.lds.S
+++ b/arch/nds32/kernel/vmlinux.lds.S
@@ -54,7 +54,7 @@ SECTIONS

_sdata = .;
RO_DATA(PAGE_SIZE)
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .;

EXCEPTION_TABLE(16)
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 318804a2c7a1..c55a7cfa1075 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -50,7 +50,7 @@ SECTIONS

_sdata = .;
RO_DATA(PAGE_SIZE)
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .;

BSS_SECTION(0, 0, 0)
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index f73e0d3ea09f..60449fd7f16f 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -74,7 +74,7 @@ SECTIONS
/* Whatever comes after _e_kernel_ro had better be page-aligend, too */

/* 32 here is cacheline size... recheck this */
- RW_DATA_SECTION(32, PAGE_SIZE, PAGE_SIZE)
+ RW_DATA(32, PAGE_SIZE, PAGE_SIZE)

_edata = .;

diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index e1c563c7dca1..12b3d7d5e9e4 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -148,7 +148,7 @@ SECTIONS
data_start = .;

/* Data */
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, PAGE_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, PAGE_SIZE)

/* PA-RISC locks requires 16-byte alignment */
. = ALIGN(16);
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
index 66dc17d24dd9..12f42f96d46e 100644
--- a/arch/riscv/kernel/vmlinux.lds.S
+++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -57,7 +57,7 @@ SECTIONS
*(.srodata*)
}

- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
.sdata : {
__global_pointer$ = . + 0x800;
*(.sdata*)
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index b33c4823f8b5..37695499717d 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -67,7 +67,7 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
__end_ro_after_init = .;

- RW_DATA_SECTION(0x100, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(0x100, PAGE_SIZE, THREAD_SIZE)
BOOT_DATA_PRESERVED

_edata = .; /* End of data section */
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index fef39054cc70..c60b19958c35 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -51,7 +51,7 @@ SECTIONS

_sdata = .;
RO_DATA(PAGE_SIZE)
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .;

DWARF_EH_FRAME
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 8929fbc35a80..7ec79918b566 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -67,7 +67,7 @@ SECTIONS
.data1 : {
*(.data1)
}
- RW_DATA_SECTION(SMP_CACHE_BYTES, 0, THREAD_SIZE)
+ RW_DATA(SMP_CACHE_BYTES, 0, THREAD_SIZE)

/* End of data section */
_edata = .;
diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S
index 367c80313bec..6fb320b337ef 100644
--- a/arch/unicore32/kernel/vmlinux.lds.S
+++ b/arch/unicore32/kernel/vmlinux.lds.S
@@ -44,7 +44,7 @@ SECTIONS

_sdata = .;
RO_DATA(PAGE_SIZE)
- RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .;

EXCEPTION_TABLE(L1_CACHE_BYTES)
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index b97e5798b9cf..bdbd7c4056c1 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -134,7 +134,7 @@ SECTIONS
/* Data section */

_sdata = .;
- RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
_edata = .;

/* Initialization code and data: */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 061e57c609f6..356078e50a5c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -24,7 +24,7 @@
*
* _sdata = .;
* RO_DATA(PAGE_SIZE)
- * RW_DATA_SECTION(...)
+ * RW_DATA(...)
* _edata = .;
*
* EXCEPTION_TABLE(...)
@@ -975,7 +975,7 @@
* matches the requirement of PAGE_ALIGNED_DATA.
*
* use 0 as page_align if page_aligned data is not used */
-#define RW_DATA_SECTION(cacheline, pagealigned, inittask) \
+#define RW_DATA(cacheline, pagealigned, inittask) \
. = ALIGN(PAGE_SIZE); \
.data : AT(ADDR(.data) - LOAD_OFFSET) { \
INIT_TASK_DATA(inittask) \
--
2.17.1

2019-10-11 00:10:54

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 04/29] alpha: Rename PT_LOAD identifier "kernel" to "text"

In preparation for moving NOTES into RO_DATA, rename the linker script
internal identifier for the PT_LOAD Program Header from "kernel" to
"text" to match other architectures.

Signed-off-by: Kees Cook <[email protected]>
---
arch/alpha/kernel/vmlinux.lds.S | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index c4b5ceceab52..781090cacc96 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -8,7 +8,7 @@
OUTPUT_FORMAT("elf64-alpha")
OUTPUT_ARCH(alpha)
ENTRY(__start)
-PHDRS { kernel PT_LOAD; note PT_NOTE; }
+PHDRS { text PT_LOAD; note PT_NOTE; }
jiffies = jiffies_64;
SECTIONS
{
@@ -27,14 +27,14 @@ SECTIONS
LOCK_TEXT
*(.fixup)
*(.gnu.warning)
- } :kernel
+ } :text
swapper_pg_dir = SWAPPER_PGD;
_etext = .; /* End of text section */

- NOTES :kernel :note
+ NOTES :text :note
.dummy : {
*(.dummy)
- } :kernel
+ } :text

RODATA
EXCEPTION_TABLE(16)
--
2.17.1

2019-10-11 00:10:58

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 03/29] powerpc: Rename PT_LOAD identifier "kernel" to "text"

In preparation for moving NOTES into RO_DATA, rename the linker script
internal identifier for the PT_LOAD Program Header from "kernel" to
"text" to match other architectures.

Signed-off-by: Kees Cook <[email protected]>
---
arch/powerpc/kernel/vmlinux.lds.S | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index a3c8492b2b19..e184a63aa5b0 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -18,7 +18,7 @@
ENTRY(_stext)

PHDRS {
- kernel PT_LOAD FLAGS(7); /* RWX */
+ text PT_LOAD FLAGS(7); /* RWX */
note PT_NOTE FLAGS(0);
}

@@ -63,7 +63,7 @@ SECTIONS
#else /* !CONFIG_PPC64 */
HEAD_TEXT
#endif
- } :kernel
+ } :text

__head_end = .;

@@ -112,7 +112,7 @@ SECTIONS
__got2_end = .;
#endif /* CONFIG_PPC32 */

- } :kernel
+ } :text

. = ALIGN(ETEXT_ALIGN_SIZE);
_etext = .;
@@ -163,9 +163,9 @@ SECTIONS
#endif
EXCEPTION_TABLE(0)

- NOTES :kernel :note
+ NOTES :text :note
/* Restore program header away from PT_NOTE. */
- .dummy : { *(.dummy) } :kernel
+ .dummy : { *(.dummy) } :text

/*
* Init sections discarded at runtime
@@ -180,7 +180,7 @@ SECTIONS
#ifdef CONFIG_PPC64
*(.tramp.ftrace.init);
#endif
- } :kernel
+ } :text

/* .exit.text is discarded at runtime, not link time,
* to deal with references from __bug_table
--
2.17.1

2019-10-11 00:11:06

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 02/29] powerpc: Remove PT_NOTE workaround

In preparation for moving NOTES into RO_DATA, remove the PT_NOTE
workaround since the kernel requires at least gcc 4.6 now.

Signed-off-by: Kees Cook <[email protected]>
---
arch/powerpc/kernel/vmlinux.lds.S | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 81e672654789..a3c8492b2b19 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -20,20 +20,6 @@ ENTRY(_stext)
PHDRS {
kernel PT_LOAD FLAGS(7); /* RWX */
note PT_NOTE FLAGS(0);
- dummy PT_NOTE FLAGS(0);
-
- /* binutils < 2.18 has a bug that makes it misbehave when taking an
- ELF file with all segments at load address 0 as input. This
- happens when running "strip" on vmlinux, because of the AT() magic
- in this linker script. People using GCC >= 4.2 won't run into
- this problem, because the "build-id" support will put some data
- into the "notes" segment (at a non-zero load address).
-
- To work around this, we force some data into both the "dummy"
- segment and the kernel segment, so the dummy segment will get a
- non-zero load address. It's not enough to always create the
- "notes" segment, since if nothing gets assigned to it, its load
- address will be zero. */
}

#ifdef CONFIG_PPC64
@@ -178,14 +164,8 @@ SECTIONS
EXCEPTION_TABLE(0)

NOTES :kernel :note
-
- /* The dummy segment contents for the bug workaround mentioned above
- near PHDRS. */
- .dummy : AT(ADDR(.dummy) - LOAD_OFFSET) {
- LONG(0)
- LONG(0)
- LONG(0)
- } :kernel :dummy
+ /* Restore program header away from PT_NOTE. */
+ .dummy : { *(.dummy) } :kernel

/*
* Init sections discarded at runtime
--
2.17.1

2019-10-11 00:13:37

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 14/29] vmlinux.lds.h: Allow EXCEPTION_TABLE to live in RO_DATA

Many architectures have an EXCEPTION_TABLE that only needs to
be readable. As such, it should live in RO_DATA. Create a macro to
identify this case for the architectures that can move EXCEPTION_TABLE
into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
Acked-by: Will Deacon <[email protected]>
---
include/asm-generic/vmlinux.lds.h | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 356078e50a5c..9867d8e41eed 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -69,6 +69,17 @@
#define NOTES_HEADERS_RESTORE
#endif

+/*
+ * Some architectures have non-executable read-only exception tables.
+ * They can be added to the RO_DATA segment by specifying their desired
+ * alignment.
+ */
+#ifdef RO_EXCEPTION_TABLE_ALIGN
+#define RO_EXCEPTION_TABLE EXCEPTION_TABLE(RO_EXCEPTION_TABLE_ALIGN)
+#else
+#define RO_EXCEPTION_TABLE
+#endif
+
/* Align . to a 8 byte boundary equals to maximum function alignment. */
#define ALIGN_FUNCTION() . = ALIGN(8)

@@ -513,6 +524,7 @@
__stop___modver = .; \
} \
\
+ RO_EXCEPTION_TABLE \
NOTES \
\
. = ALIGN((align)); \
--
2.17.1

2019-10-11 00:13:42

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 26/29] x86/mm: Remove redundant &s on addresses

The &s on addresses are redundant. Remove them to match all the other
similar functions.

Signed-off-by: Kees Cook <[email protected]>
---
arch/x86/mm/init_64.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 26299e9ce6da..e67ddca8b7a8 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1300,9 +1300,9 @@ void mark_rodata_ro(void)
{
unsigned long start = PFN_ALIGN(_text);
unsigned long rodata_start = PFN_ALIGN(__start_rodata);
- unsigned long end = (unsigned long) &__end_rodata_hpage_align;
- unsigned long text_end = PFN_ALIGN(&_etext);
- unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
+ unsigned long end = (unsigned long)__end_rodata_hpage_align;
+ unsigned long text_end = PFN_ALIGN(_etext);
+ unsigned long rodata_end = PFN_ALIGN(__end_rodata);
unsigned long all_end;

printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
--
2.17.1

2019-10-11 00:13:48

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 27/29] x86/mm: Report which part of kernel image is freed

The memory freeing report wasn't very useful for figuring out which
parts of the kernel image were being freed. Add the details for clearer
reporting in dmesg.

Before:

[ 2.150450] Freeing unused kernel image memory: 1348K
[ 2.154574] Write protecting the kernel read-only data: 20480k
[ 2.157641] Freeing unused kernel image memory: 2040K
[ 2.158827] Freeing unused kernel image memory: 172K

After:

[ 2.329678] Freeing unused kernel image (initmem) memory: 1348K
[ 2.331953] Write protecting the kernel read-only data: 20480k
[ 2.335361] Freeing unused kernel image (text/rodata gap) memory: 2040K
[ 2.336927] Freeing unused kernel image (rodata/data gap) memory: 172K

Signed-off-by: Kees Cook <[email protected]>
---
arch/x86/include/asm/processor.h | 2 +-
arch/x86/mm/init.c | 8 ++++----
arch/x86/mm/init_64.c | 6 ++++--
3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 6e0a3b43d027..790f250d39a8 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -958,7 +958,7 @@ static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)

extern unsigned long arch_align_stack(unsigned long sp);
void free_init_pages(const char *what, unsigned long begin, unsigned long end);
-extern void free_kernel_image_pages(void *begin, void *end);
+extern void free_kernel_image_pages(const char *what, void *begin, void *end);

void default_idle(void);
#ifdef CONFIG_XEN
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index fd10d91a6115..e7bb483557c9 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -829,14 +829,13 @@ void free_init_pages(const char *what, unsigned long begin, unsigned long end)
* used for the kernel image only. free_init_pages() will do the
* right thing for either kind of address.
*/
-void free_kernel_image_pages(void *begin, void *end)
+void free_kernel_image_pages(const char *what, void *begin, void *end)
{
unsigned long begin_ul = (unsigned long)begin;
unsigned long end_ul = (unsigned long)end;
unsigned long len_pages = (end_ul - begin_ul) >> PAGE_SHIFT;

-
- free_init_pages("unused kernel image", begin_ul, end_ul);
+ free_init_pages(what, begin_ul, end_ul);

/*
* PTI maps some of the kernel into userspace. For performance,
@@ -865,7 +864,8 @@ void __ref free_initmem(void)

mem_encrypt_free_decrypted_mem();

- free_kernel_image_pages(&__init_begin, &__init_end);
+ free_kernel_image_pages("unused kernel image (initmem)",
+ &__init_begin, &__init_end);
}

#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index e67ddca8b7a8..dcb9bc961b39 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1334,8 +1334,10 @@ void mark_rodata_ro(void)
set_memory_ro(start, (end-start) >> PAGE_SHIFT);
#endif

- free_kernel_image_pages((void *)text_end, (void *)rodata_start);
- free_kernel_image_pages((void *)rodata_end, (void *)_sdata);
+ free_kernel_image_pages("unused kernel image (text/rodata gap)",
+ (void *)text_end, (void *)rodata_start);
+ free_kernel_image_pages("unused kernel image (rodata/data gap)",
+ (void *)rodata_end, (void *)_sdata);

debug_checkwx();
}
--
2.17.1

2019-10-11 00:13:53

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 29/29] x86: Use INT3 instead of NOP for linker fill bytes

Instead of using 0x90 (NOP) to fill bytes between functions, which makes
it easier to sloppily target functions in function pointer overwrite
attacks, fill with 0xCC (INT3) to force a trap. Also drop the space
between "=" and the value to better match the binutils documentation
https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html#Output-Section-Fill

Example "objdump -d" before:

...
ffffffff810001e0 <start_cpu0>:
ffffffff810001e0: 48 8b 25 e1 b1 51 01 mov 0x151b1e1(%rip),%rsp # ffffffff8251b3c8 <initial_stack>
ffffffff810001e7: e9 d5 fe ff ff jmpq ffffffff810000c1 <secondary_startup_64+0x91>
ffffffff810001ec: 90 nop
ffffffff810001ed: 90 nop
ffffffff810001ee: 90 nop
ffffffff810001ef: 90 nop

ffffffff810001f0 <__startup_64>:
...

After:

...
ffffffff810001e0 <start_cpu0>:
ffffffff810001e0: 48 8b 25 41 79 53 01 mov 0x1537941(%rip),%rsp # ffffffff82537b28 <initial_stack>
ffffffff810001e7: e9 d5 fe ff ff jmpq ffffffff810000c1 <secondary_startup_64+0x91>
ffffffff810001ec: cc int3
ffffffff810001ed: cc int3
ffffffff810001ee: cc int3
ffffffff810001ef: cc int3

ffffffff810001f0 <__startup_64>:
...

Signed-off-by: Kees Cook <[email protected]>
---
arch/x86/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index b06d6e1188de..3a1a819da137 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -144,7 +144,7 @@ SECTIONS
*(.text.__x86.indirect_thunk)
__indirect_thunk_end = .;
#endif
- } :text = 0x9090
+ } :text =0xcccc

/* End of text section, which should occupy whole number of pages */
_etext = .;
--
2.17.1

2019-10-11 00:14:01

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 24/29] powerpc: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/powerpc/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 4e7cec088c8b..8834220036a5 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -7,6 +7,7 @@

#define BSS_FIRST_SECTIONS *(.bss.prominit)
#define EMITS_PT_NOTE
+#define RO_EXCEPTION_TABLE_ALIGN 0

#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
@@ -162,7 +163,6 @@ SECTIONS
__stop__btb_flush_fixup = .;
}
#endif
- EXCEPTION_TABLE(0)

/*
* Init sections discarded at runtime
--
2.17.1

2019-10-11 00:14:11

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 18/29] arm64: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA. Also
removes the redundant ALIGN, which is already present at the end of the
RO_DATA macro.

Signed-off-by: Kees Cook <[email protected]>
Acked-by: Will Deacon <[email protected]>
---
arch/arm64/kernel/vmlinux.lds.S | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index a4b3e6c0680c..9128a26eb45b 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -5,6 +5,8 @@
* Written by Martin Mares <[email protected]>
*/

+#define RO_EXCEPTION_TABLE_ALIGN 8
+
#include <asm-generic/vmlinux.lds.h>
#include <asm/cache.h>
#include <asm/kernel-pgtable.h>
@@ -135,10 +137,9 @@ SECTIONS
. = ALIGN(SEGMENT_ALIGN);
_etext = .; /* End of text section */

- RO_DATA(PAGE_SIZE) /* everything from this point to */
- EXCEPTION_TABLE(8) /* __init_begin will be marked RO NX */
+ /* everything from this point to __init_begin will be marked RO NX */
+ RO_DATA(PAGE_SIZE)

- . = ALIGN(PAGE_SIZE);
idmap_pg_dir = .;
. += IDMAP_DIR_SIZE;

--
2.17.1

2019-10-11 00:14:27

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 19/29] c6x: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/c6x/kernel/vmlinux.lds.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a3547f9d415b..ac99ba0864bf 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -5,6 +5,9 @@
* Copyright (C) 2010, 2011 Texas Instruments Incorporated
* Mark Salter <[email protected]>
*/
+
+#define RO_EXCEPTION_TABLE_ALIGN 16
+
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
#include <asm/page.h>
@@ -80,8 +83,6 @@ SECTIONS
*(.gnu.warning)
}

- EXCEPTION_TABLE(16)
-
RO_DATA(PAGE_SIZE)
.const :
{
--
2.17.1

2019-10-11 00:14:43

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 22/29] microblaze: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/microblaze/kernel/vmlinux.lds.S | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index b8efb08204a1..760cac41cbfe 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -11,6 +11,8 @@
OUTPUT_ARCH(microblaze)
ENTRY(microblaze_start)

+#define RO_EXCEPTION_TABLE_ALIGN 16
+
#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
@@ -52,7 +54,6 @@ SECTIONS {

. = ALIGN(16);
RO_DATA(4096)
- EXCEPTION_TABLE(16)

/*
* sdata2 section can go anywhere, but must be word aligned
--
2.17.1

2019-10-11 00:14:50

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 23/29] parisc: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/parisc/kernel/vmlinux.lds.S | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 12b3d7d5e9e4..53e29d88f99c 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -19,6 +19,7 @@
*(.data..vm0.pte)

#define CC_USING_PATCHABLE_FUNCTION_ENTRY
+#define RO_EXCEPTION_TABLE_ALIGN 8

#include <asm-generic/vmlinux.lds.h>

@@ -129,9 +130,6 @@ SECTIONS

RO_DATA(8)

- /* RO because of BUILDTIME_EXTABLE_SORT */
- EXCEPTION_TABLE(8)
-
/* unwind info */
.PARISC.unwind : {
__start___unwind = .;
--
2.17.1

2019-10-11 00:15:12

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 17/29] alpha: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/alpha/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index edc45f45523b..bc6f727278fd 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */

#define EMITS_PT_NOTE
+#define RO_EXCEPTION_TABLE_ALIGN 16

#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
@@ -35,7 +36,6 @@ SECTIONS
_etext = .; /* End of text section */

RO_DATA(4096)
- EXCEPTION_TABLE(16)

/* Will be freed after init */
__init_begin = ALIGN(PAGE_SIZE);
--
2.17.1

2019-10-11 00:16:14

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 21/29] ia64: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/ia64/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 11d5115bc44d..1ec6b703c5b4 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -6,6 +6,7 @@
#include <asm/thread_info.h>

#define EMITS_PT_NOTE
+#define RO_EXCEPTION_TABLE_ALIGN 16

#include <asm-generic/vmlinux.lds.h>

@@ -70,7 +71,6 @@ SECTIONS {
/*
* Read-only data
*/
- EXCEPTION_TABLE(16)

/* MCA table */
. = ALIGN(16);
--
2.17.1

2019-10-11 00:17:13

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2 25/29] xtensa: Move EXCEPTION_TABLE to RO_DATA segment

Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.

Signed-off-by: Kees Cook <[email protected]>
---
arch/xtensa/kernel/vmlinux.lds.S | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index bdbd7c4056c1..0043d5858f14 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -14,6 +14,8 @@
* Joe Taylor <[email protected], [email protected]>
*/

+#define RO_EXCEPTION_TABLE_ALIGN 16
+
#include <asm-generic/vmlinux.lds.h>
#include <asm/page.h>
#include <asm/thread_info.h>
@@ -130,7 +132,6 @@ SECTIONS

.fixup : { *(.fixup) }

- EXCEPTION_TABLE(16)
/* Data section */

_sdata = .;
--
2.17.1

2019-10-11 06:08:05

by Michael Ellerman

[permalink] [raw]
Subject: Re: [PATCH v2 02/29] powerpc: Remove PT_NOTE workaround

Kees Cook <[email protected]> writes:
> In preparation for moving NOTES into RO_DATA, remove the PT_NOTE
> workaround since the kernel requires at least gcc 4.6 now.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> arch/powerpc/kernel/vmlinux.lds.S | 24 ++----------------------
> 1 file changed, 2 insertions(+), 22 deletions(-)

Acked-by: Michael Ellerman <[email protected]>

For the archives, Joel tried a similar patch a while back which caused
some problems, see:

https://lore.kernel.org/linuxppc-dev/[email protected]/

and a v2:

https://lore.kernel.org/linuxppc-dev/[email protected]/

This is similar to his v2. The only outstanding comment on his v2 was
from Segher:
(And I do not know if there are any tools that expect the notes in a phdr,
or even specifically the second phdr).

But this patch solves that by not changing the note.

cheers

> diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
> index 81e672654789..a3c8492b2b19 100644
> --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -20,20 +20,6 @@ ENTRY(_stext)
> PHDRS {
> kernel PT_LOAD FLAGS(7); /* RWX */
> note PT_NOTE FLAGS(0);
> - dummy PT_NOTE FLAGS(0);
> -
> - /* binutils < 2.18 has a bug that makes it misbehave when taking an
> - ELF file with all segments at load address 0 as input. This
> - happens when running "strip" on vmlinux, because of the AT() magic
> - in this linker script. People using GCC >= 4.2 won't run into
> - this problem, because the "build-id" support will put some data
> - into the "notes" segment (at a non-zero load address).
> -
> - To work around this, we force some data into both the "dummy"
> - segment and the kernel segment, so the dummy segment will get a
> - non-zero load address. It's not enough to always create the
> - "notes" segment, since if nothing gets assigned to it, its load
> - address will be zero. */
> }
>
> #ifdef CONFIG_PPC64
> @@ -178,14 +164,8 @@ SECTIONS
> EXCEPTION_TABLE(0)
>
> NOTES :kernel :note
> -
> - /* The dummy segment contents for the bug workaround mentioned above
> - near PHDRS. */
> - .dummy : AT(ADDR(.dummy) - LOAD_OFFSET) {
> - LONG(0)
> - LONG(0)
> - LONG(0)
> - } :kernel :dummy
> + /* Restore program header away from PT_NOTE. */
> + .dummy : { *(.dummy) } :kernel
>
> /*
> * Init sections discarded at runtime
> --
> 2.17.1

2019-10-11 06:08:19

by Michael Ellerman

[permalink] [raw]
Subject: Re: [PATCH v2 03/29] powerpc: Rename PT_LOAD identifier "kernel" to "text"

Kees Cook <[email protected]> writes:
> In preparation for moving NOTES into RO_DATA, rename the linker script
> internal identifier for the PT_LOAD Program Header from "kernel" to
> "text" to match other architectures.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> arch/powerpc/kernel/vmlinux.lds.S | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)

Acked-by: Michael Ellerman <[email protected]>

cheers

> diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
> index a3c8492b2b19..e184a63aa5b0 100644
> --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -18,7 +18,7 @@
> ENTRY(_stext)
>
> PHDRS {
> - kernel PT_LOAD FLAGS(7); /* RWX */
> + text PT_LOAD FLAGS(7); /* RWX */
> note PT_NOTE FLAGS(0);
> }
>
> @@ -63,7 +63,7 @@ SECTIONS
> #else /* !CONFIG_PPC64 */
> HEAD_TEXT
> #endif
> - } :kernel
> + } :text
>
> __head_end = .;
>
> @@ -112,7 +112,7 @@ SECTIONS
> __got2_end = .;
> #endif /* CONFIG_PPC32 */
>
> - } :kernel
> + } :text
>
> . = ALIGN(ETEXT_ALIGN_SIZE);
> _etext = .;
> @@ -163,9 +163,9 @@ SECTIONS
> #endif
> EXCEPTION_TABLE(0)
>
> - NOTES :kernel :note
> + NOTES :text :note
> /* Restore program header away from PT_NOTE. */
> - .dummy : { *(.dummy) } :kernel
> + .dummy : { *(.dummy) } :text
>
> /*
> * Init sections discarded at runtime
> @@ -180,7 +180,7 @@ SECTIONS
> #ifdef CONFIG_PPC64
> *(.tramp.ftrace.init);
> #endif
> - } :kernel
> + } :text
>
> /* .exit.text is discarded at runtime, not link time,
> * to deal with references from __bug_table
> --
> 2.17.1

2019-10-11 07:49:59

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH v2 13/29] vmlinux.lds.h: Replace RW_DATA_SECTION with RW_DATA

On Fri, Oct 11, 2019 at 2:07 AM Kees Cook <[email protected]> wrote:
> Rename RW_DATA_SECTION to RW_DATA. (Calling this a "section" is a lie,
> since it's multiple sections and section flags cannot be applied to
> the macro.)
>
> Signed-off-by: Kees Cook <[email protected]>

> arch/m68k/kernel/vmlinux-nommu.lds | 2 +-
> arch/m68k/kernel/vmlinux-std.lds | 2 +-
> arch/m68k/kernel/vmlinux-sun3.lds | 2 +-

For m68k:
Acked-by: Geert Uytterhoeven <[email protected]>

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2019-10-11 16:12:05

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 02/29] powerpc: Remove PT_NOTE workaround

On Fri, Oct 11, 2019 at 05:07:04PM +1100, Michael Ellerman wrote:
> Kees Cook <[email protected]> writes:
> > In preparation for moving NOTES into RO_DATA, remove the PT_NOTE
> > workaround since the kernel requires at least gcc 4.6 now.
> >
> > Signed-off-by: Kees Cook <[email protected]>
> > ---
> > arch/powerpc/kernel/vmlinux.lds.S | 24 ++----------------------
> > 1 file changed, 2 insertions(+), 22 deletions(-)
>
> Acked-by: Michael Ellerman <[email protected]>

Thanks!

> For the archives, Joel tried a similar patch a while back which caused
> some problems, see:
>
> https://lore.kernel.org/linuxppc-dev/[email protected]/
>
> and a v2:
>
> https://lore.kernel.org/linuxppc-dev/[email protected]/
>
> This is similar to his v2. The only outstanding comment on his v2 was
> from Segher:
> (And I do not know if there are any tools that expect the notes in a phdr,
> or even specifically the second phdr).
>
> But this patch solves that by not changing the note.

Ah yes. Agreed: I'm retaining the note and dropping the workarounds.
FWIW, this builds happily for me in my tests.

-Kees

--
Kees Cook

2019-10-12 10:03:43

by Helge Deller

[permalink] [raw]
Subject: Re: [PATCH v2 23/29] parisc: Move EXCEPTION_TABLE to RO_DATA segment

On 11.10.19 02:06, Kees Cook wrote:
> Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> arch/parisc/kernel/vmlinux.lds.S | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)


Acked-by: Helge Deller <[email protected]> # parisc

Helge

>
> diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
> index 12b3d7d5e9e4..53e29d88f99c 100644
> --- a/arch/parisc/kernel/vmlinux.lds.S
> +++ b/arch/parisc/kernel/vmlinux.lds.S
> @@ -19,6 +19,7 @@
> *(.data..vm0.pte)
>
> #define CC_USING_PATCHABLE_FUNCTION_ENTRY
> +#define RO_EXCEPTION_TABLE_ALIGN 8
>
> #include <asm-generic/vmlinux.lds.h>
>
> @@ -129,9 +130,6 @@ SECTIONS
>
> RO_DATA(8)
>
> - /* RO because of BUILDTIME_EXTABLE_SORT */
> - EXCEPTION_TABLE(8)
> -
> /* unwind info */
> .PARISC.unwind : {
> __start___unwind = .;
>

2019-10-14 07:54:03

by Max Filippov

[permalink] [raw]
Subject: Re: [PATCH v2 25/29] xtensa: Move EXCEPTION_TABLE to RO_DATA segment

On Thu, Oct 10, 2019 at 5:16 PM Kees Cook <[email protected]> wrote:
>
> Since the EXCEPTION_TABLE is read-only, collapse it into RO_DATA.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> arch/xtensa/kernel/vmlinux.lds.S | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)

Acked-by: Max Filippov <[email protected]>

--
Thanks.
-- Max

2019-10-16 12:54:15

by Heiko Carstens

[permalink] [raw]
Subject: Re: [PATCH v2 00/29] vmlinux.lds.h: Refactor EXCEPTION_TABLE and NOTES

On Thu, Oct 10, 2019 at 05:05:40PM -0700, Kees Cook wrote:
> Arch maintainers: please send Acks (if you haven't already) for your
> respective linker script changes; the intention is for this series to
> land via -tip.
>
> v1: https://lore.kernel.org/lkml/[email protected]
> v2: clean up commit messages, rename RO_EXCEPTION_TABLE (bp)
>
>
> This series works to move the linker sections for NOTES and
> EXCEPTION_TABLE into the RO_DATA area, where they belong on most
> (all?) architectures. The problem being addressed was the discovery
> by Rick Edgecombe that the exception table was accidentally marked
> executable while he was developing his execute-only-memory series. When
> permissions were flipped from readable-and-executable to only-executable,
> the exception table became unreadable, causing things to explode rather
> badly. :)

Feel free to add
Acked-by: Heiko Carstens <[email protected]>
to every patch in this series which touches s390.