aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2015-03-22 17:01:12 -0400
committerIngo Molnar <mingo@kernel.org>2015-03-24 15:47:07 -0400
commit84f53788458c95309b88948b69ff95921e9c74a8 (patch)
tree40bdca85cb9793ee50b67b9c7675f1021eb9d039 /arch/x86/include
parent65c2377486c0b68f149f7d8770499a86b15786b6 (diff)
x86/asm: Deobfuscate segment.h
This file just defines a number of constants, and a few macros and inline functions. It is particularly badly written. For example, it is not trivial to see how descriptors are numbered (you'd expect that should be easy, right?). This change deobfuscates it via the following changes: Group all GDT_ENTRY_foo together (move intervening stuff away). Number them explicitly: use a number, not PREV_DEFINE+1, +2, +3: I want to immediately see that GDT_ENTRY_PNPBIOS_CS32 is 18. Seeing (GDT_ENTRY_KERNEL_BASE+6) instead is not useful. The above change allows to remove GDT_ENTRY_KERNEL_BASE and GDT_ENTRY_PNPBIOS_BASE, which weren't used anywhere else. After a group of GDT_ENTRY_foo, define all selector values. Remove or improve some comments. In particular: Comment deleted as stating the obvious: /* * The GDT has 32 entries */ #define GDT_ENTRIES 32 "The segment offset needs to contain a RPL. Grr. -AK" changed to "Selectors need to also have a correct RPL (+3 thingy)" "GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets)" expanded into a description *how exactly* sysret hardcodes them. Patch was tested to compile and not change vmlinux.o on 32-bit and 64-bit builds (verified with objdump). Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> Cc: Alexei Starovoitov <ast@plumgrid.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Will Drewry <wad@chromium.org> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/include')
-rw-r--r--arch/x86/include/asm/segment.h125
1 files changed, 54 insertions, 71 deletions
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index db257a58571f..117028f58882 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -15,12 +15,10 @@
15/* Simple and small GDT entries for booting only */ 15/* Simple and small GDT entries for booting only */
16 16
17#define GDT_ENTRY_BOOT_CS 2 17#define GDT_ENTRY_BOOT_CS 2
18#define GDT_ENTRY_BOOT_DS 3
19#define GDT_ENTRY_BOOT_TSS 4
18#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8) 20#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
19
20#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
21#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8) 21#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
22
23#define GDT_ENTRY_BOOT_TSS (GDT_ENTRY_BOOT_CS + 2)
24#define __BOOT_TSS (GDT_ENTRY_BOOT_TSS * 8) 22#define __BOOT_TSS (GDT_ENTRY_BOOT_TSS * 8)
25 23
26#define SEGMENT_RPL_MASK 0x3 /* 24#define SEGMENT_RPL_MASK 0x3 /*
@@ -80,97 +78,86 @@
80#define GDT_ENTRY_TLS_MIN 6 78#define GDT_ENTRY_TLS_MIN 6
81#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) 79#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
82 80
81#define GDT_ENTRY_KERNEL_CS 12
82#define GDT_ENTRY_KERNEL_DS 13
83#define GDT_ENTRY_DEFAULT_USER_CS 14 83#define GDT_ENTRY_DEFAULT_USER_CS 14
84
85#define GDT_ENTRY_DEFAULT_USER_DS 15 84#define GDT_ENTRY_DEFAULT_USER_DS 15
85#define GDT_ENTRY_TSS 16
86#define GDT_ENTRY_LDT 17
87#define GDT_ENTRY_PNPBIOS_CS32 18
88#define GDT_ENTRY_PNPBIOS_CS16 19
89#define GDT_ENTRY_PNPBIOS_DS 20
90#define GDT_ENTRY_PNPBIOS_TS1 21
91#define GDT_ENTRY_PNPBIOS_TS2 22
92#define GDT_ENTRY_APMBIOS_BASE 23
93
94#define GDT_ENTRY_ESPFIX_SS 26
95#define GDT_ENTRY_PERCPU 27
96#define GDT_ENTRY_STACK_CANARY 28
86 97
87#define GDT_ENTRY_KERNEL_BASE (12) 98#define GDT_ENTRY_DOUBLEFAULT_TSS 31
88
89#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE+0)
90
91#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE+1)
92
93#define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE+4)
94#define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE+5)
95
96#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE+6)
97#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE+11)
98 99
99#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE+14) 100#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
101#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
102#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3)
103#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3)
100#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS*8) 104#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS*8)
101 105#define PNP_CS32 (GDT_ENTRY_PNPBIOS_CS32 * 8) /* segment for calling fn */
102#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE+15) 106#define PNP_CS16 (GDT_ENTRY_PNPBIOS_CS16 * 8) /* code segment for BIOS */
107/* "Is this PNP code selector (PNP_CS32 or PNP_CS16)?" */
108#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == PNP_CS32)
109#define PNP_DS (GDT_ENTRY_PNPBIOS_DS * 8) /* data segment for BIOS */
110#define PNP_TS1 (GDT_ENTRY_PNPBIOS_TS1 * 8) /* transfer data segment */
111#define PNP_TS2 (GDT_ENTRY_PNPBIOS_TS2 * 8) /* another data segment */
103#ifdef CONFIG_SMP 112#ifdef CONFIG_SMP
104#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8) 113#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU*8)
105#else 114#else
106#define __KERNEL_PERCPU 0 115#define __KERNEL_PERCPU 0
107#endif 116#endif
108
109#define GDT_ENTRY_STACK_CANARY (GDT_ENTRY_KERNEL_BASE+16)
110#ifdef CONFIG_CC_STACKPROTECTOR 117#ifdef CONFIG_CC_STACKPROTECTOR
111#define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY*8) 118#define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY*8)
112#else 119#else
113#define __KERNEL_STACK_CANARY 0 120#define __KERNEL_STACK_CANARY 0
114#endif 121#endif
115 122
116#define GDT_ENTRY_DOUBLEFAULT_TSS 31
117
118/*
119 * The GDT has 32 entries
120 */
121#define GDT_ENTRIES 32 123#define GDT_ENTRIES 32
122 124
123/* The PnP BIOS entries in the GDT */ 125#else /* 64-bit: */
124#define GDT_ENTRY_PNPBIOS_CS32 (GDT_ENTRY_PNPBIOS_BASE + 0)
125#define GDT_ENTRY_PNPBIOS_CS16 (GDT_ENTRY_PNPBIOS_BASE + 1)
126#define GDT_ENTRY_PNPBIOS_DS (GDT_ENTRY_PNPBIOS_BASE + 2)
127#define GDT_ENTRY_PNPBIOS_TS1 (GDT_ENTRY_PNPBIOS_BASE + 3)
128#define GDT_ENTRY_PNPBIOS_TS2 (GDT_ENTRY_PNPBIOS_BASE + 4)
129
130/* The PnP BIOS selectors */
131#define PNP_CS32 (GDT_ENTRY_PNPBIOS_CS32 * 8) /* segment for calling fn */
132#define PNP_CS16 (GDT_ENTRY_PNPBIOS_CS16 * 8) /* code segment for BIOS */
133#define PNP_DS (GDT_ENTRY_PNPBIOS_DS * 8) /* data segment for BIOS */
134#define PNP_TS1 (GDT_ENTRY_PNPBIOS_TS1 * 8) /* transfer data segment */
135#define PNP_TS2 (GDT_ENTRY_PNPBIOS_TS2 * 8) /* another data segment */
136 126
137
138/*
139 * Matching rules for certain types of segments.
140 */
141
142/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
143#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
144
145
146#else
147#include <asm/cache.h> 127#include <asm/cache.h>
148 128
149#define GDT_ENTRY_KERNEL32_CS 1 129#define GDT_ENTRY_KERNEL32_CS 1
150#define GDT_ENTRY_KERNEL_CS 2 130#define GDT_ENTRY_KERNEL_CS 2
151#define GDT_ENTRY_KERNEL_DS 3 131#define GDT_ENTRY_KERNEL_DS 3
152
153#define __KERNEL32_CS (GDT_ENTRY_KERNEL32_CS * 8)
154
155/* 132/*
156 * we cannot use the same code segment descriptor for user and kernel 133 * we cannot use the same code segment descriptor for user and kernel
157 * -- not even in the long flat mode, because of different DPL /kkeil 134 * -- not even in the long flat mode, because of different DPL /kkeil
158 * The segment offset needs to contain a RPL. Grr. -AK 135 * GDT layout to get 64bit syscall/sysret right. sysret hardcodes selectors:
159 * GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets) 136 * if returning to 32-bit userspace: cs = STAR.SYSRET_CS,
137 * if returning to 64-bit userspace: cs = STAR.SYSRET_CS+16,
138 * ss = STAR.SYSRET_CS+8 (in either case)
139 * thus USER_DS should be between 32-bit and 64-bit code selectors:
160 */ 140 */
161#define GDT_ENTRY_DEFAULT_USER32_CS 4 141#define GDT_ENTRY_DEFAULT_USER32_CS 4
162#define GDT_ENTRY_DEFAULT_USER_DS 5 142#define GDT_ENTRY_DEFAULT_USER_DS 5
163#define GDT_ENTRY_DEFAULT_USER_CS 6 143#define GDT_ENTRY_DEFAULT_USER_CS 6
164#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8+3)
165#define __USER32_DS __USER_DS
166 144
167#define GDT_ENTRY_TSS 8 /* needs two entries */ 145#define GDT_ENTRY_TSS 8 /* needs two entries */
168#define GDT_ENTRY_LDT 10 /* needs two entries */ 146#define GDT_ENTRY_LDT 10 /* needs two entries */
169#define GDT_ENTRY_TLS_MIN 12 147#define GDT_ENTRY_TLS_MIN 12
170#define GDT_ENTRY_TLS_MAX 14 148#define GDT_ENTRY_TLS_MAX 14
171 149
172#define GDT_ENTRY_PER_CPU 15 /* Abused to load per CPU data from limit */ 150#define GDT_ENTRY_PER_CPU 15 /* abused to load per CPU data from limit */
173#define __PER_CPU_SEG (GDT_ENTRY_PER_CPU * 8 + 3) 151
152/* Selectors need to also have a correct RPL (+3 thingy) */
153#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
154#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
155#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3)
156#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3)
157#define __KERNEL32_CS (GDT_ENTRY_KERNEL32_CS*8)
158#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8+3)
159#define __USER32_DS __USER_DS
160#define __PER_CPU_SEG (GDT_ENTRY_PER_CPU*8+3)
174 161
175/* TLS indexes for 64bit - hardcoded in arch_prctl */ 162/* TLS indexes for 64bit - hardcoded in arch_prctl */
176#define FS_TLS 0 163#define FS_TLS 0
@@ -183,10 +170,6 @@
183 170
184#endif 171#endif
185 172
186#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
187#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
188#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3)
189#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3)
190#ifndef CONFIG_PARAVIRT 173#ifndef CONFIG_PARAVIRT
191#define get_kernel_rpl() 0 174#define get_kernel_rpl() 0
192#endif 175#endif