DivestOS/Patches/Linux_CVEs/CVE-2013-4737/ANY/0001.patch
2017-11-07 17:32:46 -05:00

151 lines
4.4 KiB
Diff

From 4256415b296348ff16cd17a5b8f8dce4dea37328 Mon Sep 17 00:00:00 2001
From: Larry Bassel <lbassel@codeaurora.org>
Date: Mon, 29 Jul 2013 13:43:17 -0700
Subject: msm: Make CONFIG_STRICT_MEMORY_RWX even stricter
If CONFIG_STRICT_MEMORY_RWX was set, the first section (containing
the kernel page table and the initial code) and the section
containing the init code were both given RWX permission, which is
a potential security hole.
Pad the first section after the initial code (which will never
be executed when the MMU is on) to make the rest of the kernel
text start in the second section and make the first section RW.
Move some data which had ended up in the "init text"
section into the "init data" one, as this is RW, not RX.
Make the "init text" RX.
We will not free the section containing the "init text",
because if we do, the kernel will allocate memory for RW data there.
Change-Id: I6ca5f4e07342c374246f04a3fee18042fd47c33b
CRs-fixed: 513919
Signed-off-by: Larry Bassel <lbassel@codeaurora.org>
---
arch/arm/kernel/vmlinux.lds.S | 12 +++++++-----
arch/arm/mm/init.c | 9 +++++++++
arch/arm/mm/mmu.c | 15 +++++++--------
3 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index ae59e5a..0bf55ae 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -93,6 +93,9 @@ SECTIONS
_text = .;
HEAD_TEXT
}
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ . = ALIGN(1<<SECTION_SHIFT);
+#endif
.text : { /* Real text segment */
_stext = .; /* Text and read-only data */
@@ -115,10 +118,10 @@ SECTIONS
*(.got) /* Global offset table */
ARM_CPU_KEEP(PROC_INFO)
}
+
#ifdef CONFIG_STRICT_MEMORY_RWX
. = ALIGN(1<<SECTION_SHIFT);
#endif
-
RO_DATA(PAGE_SIZE)
#ifdef CONFIG_ARM_UNWIND
@@ -156,6 +159,9 @@ SECTIONS
.init.proc.info : {
ARM_CPU_DISCARD(PROC_INFO)
}
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ . = ALIGN(1<<SECTION_SHIFT);
+#endif
.init.arch.info : {
__arch_info_begin = .;
*(.arch.info.init)
@@ -190,10 +196,6 @@ SECTIONS
INIT_RAM_FS
}
#ifndef CONFIG_XIP_KERNEL
-#ifdef CONFIG_STRICT_MEMORY_RWX
- . = ALIGN(1<<SECTION_SHIFT);
-#endif
- __init_data = .;
.exit.data : {
ARM_EXIT_KEEP(EXIT_DATA)
}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 34cb153..e82ea2b 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -909,6 +909,14 @@ void free_initmem(void)
"TCM link");
#endif
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ poison_init_mem((char *)__arch_info_begin,
+ __init_end - (char *)__arch_info_begin);
+ reclaimed_initmem = free_area(__phys_to_pfn(__pa(__arch_info_begin)),
+ __phys_to_pfn(__pa(__init_end)),
+ "init");
+ totalram_pages += reclaimed_initmem;
+#else
poison_init_mem(__init_begin, __init_end - __init_begin);
if (!machine_is_integrator() && !machine_is_cintegrator()) {
reclaimed_initmem = free_area(__phys_to_pfn(__pa(__init_begin)),
@@ -916,6 +924,7 @@ void free_initmem(void)
"init");
totalram_pages += reclaimed_initmem;
}
+#endif
}
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index c2efc34..e5a60a9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1379,8 +1379,6 @@ void mem_text_write_kernel_word(unsigned long *addr, unsigned long word)
}
EXPORT_SYMBOL(mem_text_write_kernel_word);
-extern char __init_data[];
-
static void __init map_lowmem(void)
{
struct memblock_region *reg;
@@ -1401,7 +1399,7 @@ static void __init map_lowmem(void)
#ifdef CONFIG_STRICT_MEMORY_RWX
if (start <= __pa(_text) && __pa(_text) < end) {
map.length = SECTION_SIZE;
- map.type = MT_MEMORY;
+ map.type = MT_MEMORY_RW;
create_mapping(&map);
@@ -1421,14 +1419,15 @@ static void __init map_lowmem(void)
map.pfn = __phys_to_pfn(__pa(__init_begin));
map.virtual = (unsigned long)__init_begin;
- map.length = __init_data - __init_begin;
- map.type = MT_MEMORY;
+ map.length = (char *)__arch_info_begin - __init_begin;
+ map.type = MT_MEMORY_RX;
create_mapping(&map);
- map.pfn = __phys_to_pfn(__pa(__init_data));
- map.virtual = (unsigned long)__init_data;
- map.length = __phys_to_virt(end) - (unsigned int)__init_data;
+ map.pfn = __phys_to_pfn(__pa(__arch_info_begin));
+ map.virtual = (unsigned long)__arch_info_begin;
+ map.length = __phys_to_virt(end) -
+ (unsigned long)__arch_info_begin;
map.type = MT_MEMORY_RW;
} else {
map.length = end - start;
--
cgit v1.1