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>

authored by Avi Kivity and committed by Linus Torvalds a29815a3 c0f607c6

+19 -2
+5
arch/x86/Kconfig
··· 1247 1247 def_bool X86_64 1248 1248 depends on MEMORY_HOTPLUG 1249 1249 1250 + config ILLEGAL_POINTER_VALUE 1251 + hex 1252 + default 0 if X86_32 1253 + default 0xdead000000000000 if X86_64 1254 + 1250 1255 source "mm/Kconfig" 1251 1256 1252 1257 config HIGHPTE
+14 -2
include/linux/poison.h
··· 2 2 #define _LINUX_POISON_H 3 3 4 4 /********** include/linux/list.h **********/ 5 + 6 + /* 7 + * Architectures might want to move the poison pointer offset 8 + * into some well-recognized area such as 0xdead000000000000, 9 + * that is also not mappable by user-space exploits: 10 + */ 11 + #ifdef CONFIG_ILLEGAL_POINTER_VALUE 12 + # define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL) 13 + #else 14 + # define POISON_POINTER_DELTA 0 15 + #endif 16 + 5 17 /* 6 18 * These are non-NULL pointers that will result in page faults 7 19 * under normal circumstances, used to verify that nobody uses 8 20 * non-initialized list entries. 9 21 */ 10 - #define LIST_POISON1 ((void *) 0x00100100) 11 - #define LIST_POISON2 ((void *) 0x00200200) 22 + #define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) 23 + #define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) 12 24 13 25 /********** include/linux/timer.h **********/ 14 26 /*