diff options
Diffstat (limited to 'drivers/lguest/segments.c')
-rw-r--r-- | drivers/lguest/segments.c | 62 |
1 files changed, 5 insertions, 57 deletions
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index f675a41a80da..9b81119f46e9 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c | |||
@@ -43,22 +43,6 @@ | |||
43 | * begin. | 43 | * begin. |
44 | */ | 44 | */ |
45 | 45 | ||
46 | /* Is the descriptor the Guest wants us to put in OK? | ||
47 | * | ||
48 | * The flag which Intel says must be zero: must be zero. The descriptor must | ||
49 | * be present, (this is actually checked earlier but is here for thorougness), | ||
50 | * and the descriptor type must be 1 (a memory segment). */ | ||
51 | static int desc_ok(const struct desc_struct *gdt) | ||
52 | { | ||
53 | return ((gdt->b & 0x00209000) == 0x00009000); | ||
54 | } | ||
55 | |||
56 | /* Is the segment present? (Otherwise it can't be used by the Guest). */ | ||
57 | static int segment_present(const struct desc_struct *gdt) | ||
58 | { | ||
59 | return gdt->b & 0x8000; | ||
60 | } | ||
61 | |||
62 | /* There are several entries we don't let the Guest set. The TSS entry is the | 46 | /* There are several entries we don't let the Guest set. The TSS entry is the |
63 | * "Task State Segment" which controls all kinds of delicate things. The | 47 | * "Task State Segment" which controls all kinds of delicate things. The |
64 | * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the | 48 | * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the |
@@ -71,37 +55,11 @@ static int ignored_gdt(unsigned int num) | |||
71 | || num == GDT_ENTRY_DOUBLEFAULT_TSS); | 55 | || num == GDT_ENTRY_DOUBLEFAULT_TSS); |
72 | } | 56 | } |
73 | 57 | ||
74 | /* If the Guest asks us to remove an entry from the GDT, we have to be careful. | 58 | /*H:610 Once the GDT has been changed, we fix the new entries up a little. We |
75 | * If one of the segment registers is pointing at that entry the Switcher will | 59 | * don't care if they're invalid: the worst that can happen is a General |
76 | * crash when it tries to reload the segment registers for the Guest. | 60 | * Protection Fault in the Switcher when it restores a Guest segment register |
77 | * | 61 | * which tries to use that entry. Then we kill the Guest for causing such a |
78 | * It doesn't make much sense for the Guest to try to remove its own code, data | 62 | * mess: the message will be "unhandled trap 256". */ |
79 | * or stack segments while they're in use: assume that's a Guest bug. If it's | ||
80 | * one of the lesser segment registers using the removed entry, we simply set | ||
81 | * that register to 0 (unusable). */ | ||
82 | static void check_segment_use(struct lguest *lg, unsigned int desc) | ||
83 | { | ||
84 | /* GDT entries are 8 bytes long, so we divide to get the index and | ||
85 | * ignore the bottom bits. */ | ||
86 | if (lg->regs->gs / 8 == desc) | ||
87 | lg->regs->gs = 0; | ||
88 | if (lg->regs->fs / 8 == desc) | ||
89 | lg->regs->fs = 0; | ||
90 | if (lg->regs->es / 8 == desc) | ||
91 | lg->regs->es = 0; | ||
92 | if (lg->regs->ds / 8 == desc | ||
93 | || lg->regs->cs / 8 == desc | ||
94 | || lg->regs->ss / 8 == desc) | ||
95 | kill_guest(lg, "Removed live GDT entry %u", desc); | ||
96 | } | ||
97 | /*:*/ | ||
98 | /*M:009 We wouldn't need to check for removal of in-use segments if we handled | ||
99 | * faults in the Switcher. However, it's probably not a worthwhile | ||
100 | * optimization. :*/ | ||
101 | |||
102 | /*H:610 Once the GDT has been changed, we look through the changed entries and | ||
103 | * see if they're OK. If not, we'll call kill_guest() and the Guest will never | ||
104 | * get to use the invalid entries. */ | ||
105 | static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) | 63 | static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) |
106 | { | 64 | { |
107 | unsigned int i; | 65 | unsigned int i; |
@@ -112,16 +70,6 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) | |||
112 | if (ignored_gdt(i)) | 70 | if (ignored_gdt(i)) |
113 | continue; | 71 | continue; |
114 | 72 | ||
115 | /* We could fault in switch_to_guest if they are using | ||
116 | * a removed segment. */ | ||
117 | if (!segment_present(&lg->gdt[i])) { | ||
118 | check_segment_use(lg, i); | ||
119 | continue; | ||
120 | } | ||
121 | |||
122 | if (!desc_ok(&lg->gdt[i])) | ||
123 | kill_guest(lg, "Bad GDT descriptor %i", i); | ||
124 | |||
125 | /* Segment descriptors contain a privilege level: the Guest is | 73 | /* Segment descriptors contain a privilege level: the Guest is |
126 | * sometimes careless and leaves this as 0, even though it's | 74 | * sometimes careless and leaves this as 0, even though it's |
127 | * running at privilege level 1. If so, we fix it here. */ | 75 | * running at privilege level 1. If so, we fix it here. */ |