aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-07-23 13:37:00 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-07-31 17:01:48 -0400
commitf6f91b0d9fd971c630cef908dde8fe8795aefbf8 (patch)
tree54032cefa513a3ae63971998caa90eea4736180c /arch
parente39e3f3ebfef03450cf7bfa7a974a8c61f7980c8 (diff)
ARM: allow kuser helpers to be removed from the vector page
Provide a kernel configuration option to allow the kernel user helpers to be removed from the vector page, thereby preventing their use with ROP (return orientated programming) attacks. This option is only visible for CPU architectures which natively support all the operations which kernel user helpers would normally provide, and must be enabled with caution. Cc: <stable@vger.kernel.org> Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/entry-armv.S3
-rw-r--r--arch/arm/kernel/traps.c23
-rw-r--r--arch/arm/mm/Kconfig34
3 files changed, 51 insertions, 9 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 94caefb550bf..d40d0ef389db 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -753,6 +753,7 @@ ENDPROC(__switch_to)
753 .endr 753 .endr
754 .endm 754 .endm
755 755
756#ifdef CONFIG_KUSER_HELPERS
756 .align 5 757 .align 5
757 .globl __kuser_helper_start 758 .globl __kuser_helper_start
758__kuser_helper_start: 759__kuser_helper_start:
@@ -939,6 +940,8 @@ __kuser_helper_version: @ 0xffff0ffc
939 .globl __kuser_helper_end 940 .globl __kuser_helper_end
940__kuser_helper_end: 941__kuser_helper_end:
941 942
943#endif
944
942 THUMB( .thumb ) 945 THUMB( .thumb )
943 946
944/* 947/*
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 2c8c7fa78b8c..e3ca35ccd38e 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -800,15 +800,26 @@ void __init trap_init(void)
800 return; 800 return;
801} 801}
802 802
803static void __init kuser_get_tls_init(unsigned long vectors) 803#ifdef CONFIG_KUSER_HELPERS
804static void __init kuser_init(void *vectors)
804{ 805{
806 extern char __kuser_helper_start[], __kuser_helper_end[];
807 int kuser_sz = __kuser_helper_end - __kuser_helper_start;
808
809 memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
810
805 /* 811 /*
806 * vectors + 0xfe0 = __kuser_get_tls 812 * vectors + 0xfe0 = __kuser_get_tls
807 * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 813 * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8
808 */ 814 */
809 if (tls_emu || has_tls_reg) 815 if (tls_emu || has_tls_reg)
810 memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4); 816 memcpy(vectors + 0xfe0, vectors + 0xfe8, 4);
817}
818#else
819static void __init kuser_init(void *vectors)
820{
811} 821}
822#endif
812 823
813void __init early_trap_init(void *vectors_base) 824void __init early_trap_init(void *vectors_base)
814{ 825{
@@ -816,8 +827,6 @@ void __init early_trap_init(void *vectors_base)
816 unsigned long vectors = (unsigned long)vectors_base; 827 unsigned long vectors = (unsigned long)vectors_base;
817 extern char __stubs_start[], __stubs_end[]; 828 extern char __stubs_start[], __stubs_end[];
818 extern char __vectors_start[], __vectors_end[]; 829 extern char __vectors_start[], __vectors_end[];
819 extern char __kuser_helper_start[], __kuser_helper_end[];
820 int kuser_sz = __kuser_helper_end - __kuser_helper_start;
821 unsigned i; 830 unsigned i;
822 831
823 vectors_page = vectors_base; 832 vectors_page = vectors_base;
@@ -838,12 +847,8 @@ void __init early_trap_init(void *vectors_base)
838 */ 847 */
839 memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); 848 memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
840 memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); 849 memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
841 memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
842 850
843 /* 851 kuser_init(vectors_base);
844 * Do processor specific fixups for the kuser helpers
845 */
846 kuser_get_tls_init(vectors);
847 852
848 /* 853 /*
849 * Copy signal return handlers into the vector page, and 854 * Copy signal return handlers into the vector page, and
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 6cacdc8dd654..db5c2cab8fda 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -421,24 +421,28 @@ config CPU_32v3
421 select CPU_USE_DOMAINS if MMU 421 select CPU_USE_DOMAINS if MMU
422 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 422 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
423 select TLS_REG_EMUL if SMP || !MMU 423 select TLS_REG_EMUL if SMP || !MMU
424 select NEED_KUSER_HELPERS
424 425
425config CPU_32v4 426config CPU_32v4
426 bool 427 bool
427 select CPU_USE_DOMAINS if MMU 428 select CPU_USE_DOMAINS if MMU
428 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 429 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
429 select TLS_REG_EMUL if SMP || !MMU 430 select TLS_REG_EMUL if SMP || !MMU
431 select NEED_KUSER_HELPERS
430 432
431config CPU_32v4T 433config CPU_32v4T
432 bool 434 bool
433 select CPU_USE_DOMAINS if MMU 435 select CPU_USE_DOMAINS if MMU
434 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 436 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
435 select TLS_REG_EMUL if SMP || !MMU 437 select TLS_REG_EMUL if SMP || !MMU
438 select NEED_KUSER_HELPERS
436 439
437config CPU_32v5 440config CPU_32v5
438 bool 441 bool
439 select CPU_USE_DOMAINS if MMU 442 select CPU_USE_DOMAINS if MMU
440 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 443 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
441 select TLS_REG_EMUL if SMP || !MMU 444 select TLS_REG_EMUL if SMP || !MMU
445 select NEED_KUSER_HELPERS
442 446
443config CPU_32v6 447config CPU_32v6
444 bool 448 bool
@@ -776,6 +780,7 @@ config CPU_BPREDICT_DISABLE
776 780
777config TLS_REG_EMUL 781config TLS_REG_EMUL
778 bool 782 bool
783 select NEED_KUSER_HELPERS
779 help 784 help
780 An SMP system using a pre-ARMv6 processor (there are apparently 785 An SMP system using a pre-ARMv6 processor (there are apparently
781 a few prototypes like that in existence) and therefore access to 786 a few prototypes like that in existence) and therefore access to
@@ -783,11 +788,40 @@ config TLS_REG_EMUL
783 788
784config NEEDS_SYSCALL_FOR_CMPXCHG 789config NEEDS_SYSCALL_FOR_CMPXCHG
785 bool 790 bool
791 select NEED_KUSER_HELPERS
786 help 792 help
787 SMP on a pre-ARMv6 processor? Well OK then. 793 SMP on a pre-ARMv6 processor? Well OK then.
788 Forget about fast user space cmpxchg support. 794 Forget about fast user space cmpxchg support.
789 It is just not possible. 795 It is just not possible.
790 796
797config NEED_KUSER_HELPERS
798 bool
799
800config KUSER_HELPERS
801 bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS
802 default y
803 help
804 Warning: disabling this option may break user programs.
805
806 Provide kuser helpers in the vector page. The kernel provides
807 helper code to userspace in read only form at a fixed location
808 in the high vector page to allow userspace to be independent of
809 the CPU type fitted to the system. This permits binaries to be
810 run on ARMv4 through to ARMv7 without modification.
811
812 However, the fixed address nature of these helpers can be used
813 by ROP (return orientated programming) authors when creating
814 exploits.
815
816 If all of the binaries and libraries which run on your platform
817 are built specifically for your platform, and make no use of
818 these helpers, then you can turn this option off. However,
819 when such an binary or library is run, it will receive a SIGILL
820 signal, which will terminate the program.
821
822 Say N here only if you are absolutely certain that you do not
823 need these helpers; otherwise, the safe option is to say Y.
824
791config DMA_CACHE_RWFO 825config DMA_CACHE_RWFO
792 bool "Enable read/write for ownership DMA cache maintenance" 826 bool "Enable read/write for ownership DMA cache maintenance"
793 depends on CPU_V6K && SMP 827 depends on CPU_V6K && SMP