Jelajahi Sumber

core, x86: make LIST_POISON less deadly

The list macros use LIST_POISON1 and LIST_POISON2 as undereferencable
pointers in order to trap erronous use of freed list_heads.  Unfortunately
userspace can arrange for those pointers to actually be dereferencable,
potentially turning an oops to an expolit.

To avoid this allow architectures (currently x86_64 only) to override
the default values for these pointers with truly-undereferencable values.
This is easy on x86_64 as the virtual address space is large and contains
areas that cannot be mapped.

Other 64-bit architectures will likely find similar unmapped ranges.

[ingo: switch to 0xdead000000000000 as the unmapped area]
[ingo: add comments, cleanup]
[jaswinder: eliminate sparse warnings]

Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Avi Kivity 15 tahun lalu
induk
melakukan
a29815a333
2 mengubah file dengan 19 tambahan dan 2 penghapusan
  1. 5 0
      arch/x86/Kconfig
  2. 14 2
      include/linux/poison.h

+ 5 - 0
arch/x86/Kconfig

@@ -1247,6 +1247,11 @@ config ARCH_MEMORY_PROBE
 	def_bool X86_64
 	def_bool X86_64
 	depends on MEMORY_HOTPLUG
 	depends on MEMORY_HOTPLUG
 
 
+config ILLEGAL_POINTER_VALUE
+       hex
+       default 0 if X86_32
+       default 0xdead000000000000 if X86_64
+
 source "mm/Kconfig"
 source "mm/Kconfig"
 
 
 config HIGHPTE
 config HIGHPTE

+ 14 - 2
include/linux/poison.h

@@ -2,13 +2,25 @@
 #define _LINUX_POISON_H
 #define _LINUX_POISON_H
 
 
 /********** include/linux/list.h **********/
 /********** include/linux/list.h **********/
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
 /*
 /*
  * These are non-NULL pointers that will result in page faults
  * These are non-NULL pointers that will result in page faults
  * under normal circumstances, used to verify that nobody uses
  * under normal circumstances, used to verify that nobody uses
  * non-initialized list entries.
  * non-initialized list entries.
  */
  */
-#define LIST_POISON1  ((void *) 0x00100100)
-#define LIST_POISON2  ((void *) 0x00200200)
+#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
 
 
 /********** include/linux/timer.h **********/
 /********** include/linux/timer.h **********/
 /*
 /*