aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/switcher.S
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-08-09 06:57:13 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-09 11:14:56 -0400
commit0d027c01cd36b8cff727c78d2e40d334ba9895a8 (patch)
tree21dde51409ab83cbb3ce7200393b3a0acb76388d /drivers/lguest/switcher.S
parent37250097e1b730c30da1790e354c0da65e617043 (diff)
lguest: Fix Malicious Guest GDT Host Crash
If a Guest makes hypercall which sets a GDT entry to not present, we currently set any segment registers using that GDT entry to 0. Unfortunately, this is not sufficient: there are other ways of altering GDT entries which will cause a fault. The correct solution to do what Linux does: let them set any GDT value they want and handle the #GP when popping causes a fault. This has the added benefit of making our Switcher slightly more robust in the case of any other bugs which cause it to fault. We kill the Guest if it causes a fault in the Switcher: it's the Guest's responsibility to make sure it's not using segments when it changes them. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/lguest/switcher.S')
-rw-r--r--drivers/lguest/switcher.S15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/lguest/switcher.S b/drivers/lguest/switcher.S
index d418179ea6b5..7c9c230cc845 100644
--- a/drivers/lguest/switcher.S
+++ b/drivers/lguest/switcher.S
@@ -47,6 +47,7 @@
47// Down here in the depths of assembler code. 47// Down here in the depths of assembler code.
48#include <linux/linkage.h> 48#include <linux/linkage.h>
49#include <asm/asm-offsets.h> 49#include <asm/asm-offsets.h>
50#include <asm/page.h>
50#include "lg.h" 51#include "lg.h"
51 52
52// We mark the start of the code to copy 53// We mark the start of the code to copy
@@ -182,13 +183,15 @@ ENTRY(switch_to_guest)
182 movl $(LGUEST_DS), %eax; \ 183 movl $(LGUEST_DS), %eax; \
183 movl %eax, %ds; \ 184 movl %eax, %ds; \
184 /* So where are we? Which CPU, which struct? \ 185 /* So where are we? Which CPU, which struct? \
185 * The stack is our clue: our TSS sets \ 186 * The stack is our clue: our TSS starts \
186 * It at the end of "struct lguest_pages" \ 187 * It at the end of "struct lguest_pages". \
187 * And we then pushed and pushed and pushed Guest regs: \ 188 * Or we may have stumbled while restoring \
188 * Now stack points atop the "struct lguest_regs". \ 189 * Our Guest segment regs while in switch_to_guest, \
189 * Subtract that offset, and we find our struct. */ \ 190 * The fault pushed atop that part-unwound stack. \
191 * If we round the stack down to the page start \
192 * We're at the start of "struct lguest_pages". */ \
190 movl %esp, %eax; \ 193 movl %esp, %eax; \
191 subl $LGUEST_PAGES_regs, %eax; \ 194 andl $(~(1 << PAGE_SHIFT - 1)), %eax; \
192 /* Save our trap number: the switch will obscure it \ 195 /* Save our trap number: the switch will obscure it \
193 * (The Guest regs are not mapped here in the Host) \ 196 * (The Guest regs are not mapped here in the Host) \
194 * %ebx holds it safe for deliver_to_host */ \ 197 * %ebx holds it safe for deliver_to_host */ \