History

x86/ldt: Make modify_ldt synchronous

modify_ldt() has questionable locking and does not synchronize threads. Improve it: redesign the locking and synchronize all threads' LDTs using an IPI on all modifications. This will dramatically slow down modify_ldt in multithreaded programs, but there shouldn't be any multithreaded programs that care about modify_ldt's performance in the first place. This fixes some fallout from the CVE-2015-5157 fixes.

Andy Lutomirski committed 11 years ago

Commit 37868fe1 parent aa1acff9 files · +210 −153Browse files

Unified · Split

9 files
  1. arch/x86/include/asm/desc.h +0 −15
  2. arch/x86/include/asm/mmu.h +1 −2
  3. arch/x86/include/asm/mmu_context.h +49 −5
  4. arch/x86/kernel/cpu/common.c +2 −2
  5. arch/x86/kernel/cpu/perf_event.c +8 −4
  6. arch/x86/kernel/ldt.c +142 −120
  7. arch/x86/kernel/process_64.c +2 −2
  8. arch/x86/kernel/step.c +4 −2
  9. arch/x86/power/cpu.c +2 −1
arch/x86/include/asm/desc.h+0−15
@@ -280,21 +280,6 @@ static inline void clear_LDT(void) · 279 unmodified lines
280280 set_ldt(NULL, 0);
281281 }
282282
283−/*
284− * load one particular LDT into the current CPU
285− */
286−static inline void load_LDT_nolock(mm_context_t *pc)
287−{
288− set_ldt(pc->ldt, pc->size);
289−}
290−
291−static inline void load_LDT(mm_context_t *pc)
292−{
293− preempt_disable();
294− load_LDT_nolock(pc);
295− preempt_enable();
296−}
297−
298283 static inline unsigned long get_desc_base(const struct desc_struct *desc)
299284 {
300285 return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
arch/x86/include/asm/mmu.h+1−2
@@ -9,8 +9,7 @@ · 8 unmodified lines
99 * we put the segment information here.
1010 */
1111 typedef struct {
12− void *ldt;
13− int size;
12+ struct ldt_struct *ldt;
1413
1514 #ifdef CONFIG_X86_64
1615 /* True if mm supports a task running in 32 bit compatibility mode. */
arch/x86/include/asm/mmu_context.h+49−5
@@ -33,6 +33,50 @@ static inline void load_mm_cr4(struct mm_struct *mm) · 32 unmodified lines
3333 static inline void load_mm_cr4(struct mm_struct *mm) {}
3434 #endif
3535
36+/*
37+ * ldt_structs can be allocated, used, and freed, but they are never
38+ * modified while live.
39+ */
40+struct ldt_struct {
41+ /*
42+ * Xen requires page-aligned LDTs with special permissions. This is
43+ * needed to prevent us from installing evil descriptors such as
44+ * call gates. On native, we could merge the ldt_struct and LDT
45+ * allocations, but it's not worth trying to optimize.
46+ */
47+ struct desc_struct *entries;
48+ int size;
49+};
50+
51+static inline void load_mm_ldt(struct mm_struct *mm)
52+{
53+ struct ldt_struct *ldt;
54+
55+ /* lockless_dereference synchronizes with smp_store_release */
56+ ldt = lockless_dereference(mm->context.ldt);
57+
58+ /*
59+ * Any change to mm->context.ldt is followed by an IPI to all
60+ * CPUs with the mm active. The LDT will not be freed until
61+ * after the IPI is handled by all such CPUs. This means that,
62+ * if the ldt_struct changes before we return, the values we see
63+ * will be safe, and the new values will be loaded before we run
64+ * any user code.
65+ *
66+ * NB: don't try to convert this to use RCU without extreme care.
67+ * We would still need IRQs off, because we don't want to change
68+ * the local LDT after an IPI loaded a newer value than the one
69+ * that we can see.
70+ */
71+
72+ if (unlikely(ldt))
73+ set_ldt(ldt->entries, ldt->size);
74+ else
75+ clear_LDT();
76+
77+ DEBUG_LOCKS_WARN_ON(preemptible());
78+}
79+
3680 /*
3781 * Used for LDT copy/destruction.
3882 */
@@ -78,12 +122,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, · 39 unmodified lines
78122 * was called and then modify_ldt changed
79123 * prev->context.ldt but suppressed an IPI to this CPU.
80124 * In this case, prev->context.ldt != NULL, because we
81− * never free an LDT while the mm still exists. That
82− * means that next->context.ldt != prev->context.ldt,
83− * because mms never share an LDT.
125+ * never set context.ldt to NULL while the mm still
126+ * exists. That means that next->context.ldt !=
127+ * prev->context.ldt, because mms never share an LDT.
84128 */
85129 if (unlikely(prev->context.ldt != next->context.ldt))
86− load_LDT_nolock(&next->context);
130+ load_mm_ldt(next);
87131 }
88132 #ifdef CONFIG_SMP
89133 else {
@@ -106,7 +150,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, · 16 unmodified lines
106150 load_cr3(next->pgd);
107151 trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
108152 load_mm_cr4(next);
109− load_LDT_nolock(&next->context);
153+ load_mm_ldt(next);
110154 }
111155 }
112156 #endif
arch/x86/kernel/cpu/common.c+2−2
@@ -1410,7 +1410,7 @@ void cpu_init(void) · 1409 unmodified lines
14101410 load_sp0(t, &current->thread);
14111411 set_tss_desc(cpu, t);
14121412 load_TR_desc();
1413− load_LDT(&init_mm.context);
1413+ load_mm_ldt(&init_mm);
14141414
14151415 clear_all_debug_regs();
14161416 dbg_restore_debug_regs();
@@ -1459,7 +1459,7 @@ void cpu_init(void) · 42 unmodified lines
14591459 load_sp0(t, thread);
14601460 set_tss_desc(cpu, t);
14611461 load_TR_desc();
1462− load_LDT(&init_mm.context);
1462+ load_mm_ldt(&init_mm);
14631463
14641464 t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
14651465
arch/x86/kernel/cpu/perf_event.c+8−4
@@ -2179,21 +2179,25 @@ static unsigned long get_segment_base(unsigned int segment) · 2178 unmodified lines
21792179 int idx = segment >> 3;
21802180
21812181 if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
2182+ struct ldt_struct *ldt;
2183+
21822184 if (idx > LDT_ENTRIES)
21832185 return 0;
21842186
2185− if (idx > current->active_mm->context.size)
2187+ /* IRQs are off, so this synchronizes with smp_store_release */
2188+ ldt = lockless_dereference(current->active_mm->context.ldt);
2189+ if (!ldt || idx > ldt->size)
21862190 return 0;
21872191
2188− desc = current->active_mm->context.ldt;
2192+ desc = &ldt->entries[idx];
21892193 } else {
21902194 if (idx > GDT_ENTRIES)
21912195 return 0;
21922196
2193− desc = raw_cpu_ptr(gdt_page.gdt);
2197+ desc = raw_cpu_ptr(gdt_page.gdt) + idx;
21942198 }
21952199
2196− return get_desc_base(desc + idx);
2200+ return get_desc_base(desc);
21972201 }
21982202
21992203 #ifdef CONFIG_COMPAT
arch/x86/kernel/ldt.c+142−120
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212 #include <linux/string.h>
1313 #include <linux/mm.h>
1414 #include <linux/smp.h>
15+#include <linux/slab.h>
1516 #include <linux/vmalloc.h>
1617 #include <linux/uaccess.h>
1718
@@ -20,82 +21,82 @@ · 2 unmodified lines
2021 #include <asm/mmu_context.h>
2122 #include <asm/syscalls.h>
2223
23−#ifdef CONFIG_SMP
24+/* context.lock is held for us, so we don't need any locking. */
2425 static void flush_ldt(void *current_mm)
2526 {
26− if (current->active_mm == current_mm)
27− load_LDT(&current->active_mm->context);
27+ mm_context_t *pc;
28+
29+ if (current->active_mm != current_mm)
30+ return;
31+
32+ pc = &current->active_mm->context;
33+ set_ldt(pc->ldt->entries, pc->ldt->size);
2834 }
29−#endif
3035
31−static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
36+/* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
37+static struct ldt_struct *alloc_ldt_struct(int size)
3238 {
33− void *oldldt, *newldt;
34− int oldsize;
35−
36− if (mincount <= pc->size)
37− return 0;
38− oldsize = pc->size;
39− mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
40− (~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
41− if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
42− newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
39+ struct ldt_struct *new_ldt;
40+ int alloc_size;
41+
42+ if (size > LDT_ENTRIES)
43+ return NULL;
44+
45+ new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL);
46+ if (!new_ldt)
47+ return NULL;
48+
49+ BUILD_BUG_ON(LDT_ENTRY_SIZE != sizeof(struct desc_struct));
50+ alloc_size = size * LDT_ENTRY_SIZE;
51+
52+ /*
53+ * Xen is very picky: it requires a page-aligned LDT that has no
54+ * trailing nonzero bytes in any page that contains LDT descriptors.
55+ * Keep it simple: zero the whole allocation and never allocate less
56+ * than PAGE_SIZE.
57+ */
58+ if (alloc_size > PAGE_SIZE)
59+ new_ldt->entries = vzalloc(alloc_size);
4360 else
44− newldt = (void *)__get_free_page(GFP_KERNEL);
45−
46− if (!newldt)
47− return -ENOMEM;
61+ new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL);
4862
49− if (oldsize)
50− memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
51− oldldt = pc->ldt;
52− memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
53− (mincount - oldsize) * LDT_ENTRY_SIZE);
63+ if (!new_ldt->entries) {
64+ kfree(new_ldt);
65+ return NULL;
66+ }
5467
55− paravirt_alloc_ldt(newldt, mincount);
68+ new_ldt->size = size;
69+ return new_ldt;
70+}
5671
57−#ifdef CONFIG_X86_64
58− /* CHECKME: Do we really need this ? */
59− wmb();
60−#endif
61− pc->ldt = newldt;
62− wmb();
63− pc->size = mincount;
64− wmb();
65−
66− if (reload) {
67−#ifdef CONFIG_SMP
68− preempt_disable();
69− load_LDT(pc);
70− if (!cpumask_equal(mm_cpumask(current->mm),
71− cpumask_of(smp_processor_id())))
72− smp_call_function(flush_ldt, current->mm, 1);
73− preempt_enable();
74−#else
75− load_LDT(pc);
76−#endif
77− }
78− if (oldsize) {
79− paravirt_free_ldt(oldldt, oldsize);
80− if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
81− vfree(oldldt);
82− else
83− put_page(virt_to_page(oldldt));
84− }
85− return 0;
72+/* After calling this, the LDT is immutable. */
73+static void finalize_ldt_struct(struct ldt_struct *ldt)
74+{
75+ paravirt_alloc_ldt(ldt->entries, ldt->size);
8676 }
8777
88−static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
78+/* context.lock is held */
79+static void install_ldt(struct mm_struct *current_mm,
80+ struct ldt_struct *ldt)
8981 {
90− int err = alloc_ldt(new, old->size, 0);
91− int i;
82+ /* Synchronizes with lockless_dereference in load_mm_ldt. */
83+ smp_store_release(&current_mm->context.ldt, ldt);
84+
85+ /* Activate the LDT for all CPUs using current_mm. */
86+ on_each_cpu_mask(mm_cpumask(current_mm), flush_ldt, current_mm, true);
87+}
9288
93− if (err < 0)
94− return err;
89+static void free_ldt_struct(struct ldt_struct *ldt)
90+{
91+ if (likely(!ldt))
92+ return;
9593
96− for (i = 0; i < old->size; i++)
97− write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
98− return 0;
94+ paravirt_free_ldt(ldt->entries, ldt->size);
95+ if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
96+ vfree(ldt->entries);
97+ else
98+ kfree(ldt->entries);
99+ kfree(ldt);
99100 }
100101
101102 /*
@@ -104,17 +105,37 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old) · 2 unmodified lines
104105 */
105106 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
106107 {
108+ struct ldt_struct *new_ldt;
107109 struct mm_struct *old_mm;
108110 int retval = 0;
109111
110112 mutex_init(&mm->context.lock);
111− mm->context.size = 0;
112113 old_mm = current->mm;
113− if (old_mm && old_mm->context.size > 0) {
114− mutex_lock(&old_mm->context.lock);
115− retval = copy_ldt(&mm->context, &old_mm->context);
116− mutex_unlock(&old_mm->context.lock);
114+ if (!old_mm) {
115+ mm->context.ldt = NULL;
116+ return 0;
117117 }
118+
119+ mutex_lock(&old_mm->context.lock);
120+ if (!old_mm->context.ldt) {
121+ mm->context.ldt = NULL;
122+ goto out_unlock;
123+ }
124+
125+ new_ldt = alloc_ldt_struct(old_mm->context.ldt->size);
126+ if (!new_ldt) {
127+ retval = -ENOMEM;
128+ goto out_unlock;
129+ }
130+
131+ memcpy(new_ldt->entries, old_mm->context.ldt->entries,
132+ new_ldt->size * LDT_ENTRY_SIZE);
133+ finalize_ldt_struct(new_ldt);
134+
135+ mm->context.ldt = new_ldt;
136+
137+out_unlock:
138+ mutex_unlock(&old_mm->context.lock);
118139 return retval;
119140 }
120141
@@ -125,53 +146,47 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) · 4 unmodified lines
125146 */
126147 void destroy_context(struct mm_struct *mm)
127148 {
128− if (mm->context.size) {
129−#ifdef CONFIG_X86_32
130− /* CHECKME: Can this ever happen ? */
131− if (mm == current->active_mm)
132− clear_LDT();
133−#endif
134− paravirt_free_ldt(mm->context.ldt, mm->context.size);
135− if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
136− vfree(mm->context.ldt);
137− else
138− put_page(virt_to_page(mm->context.ldt));
139− mm->context.size = 0;
140− }
149+ free_ldt_struct(mm->context.ldt);
150+ mm->context.ldt = NULL;
141151 }
142152
143153 static int read_ldt(void __user *ptr, unsigned long bytecount)
144154 {
145− int err;
155+ int retval;
146156 unsigned long size;
147157 struct mm_struct *mm = current->mm;
148158
149− if (!mm->context.size)
150− return 0;
159+ mutex_lock(&mm->context.lock);
160+
161+ if (!mm->context.ldt) {
162+ retval = 0;
163+ goto out_unlock;
164+ }
165+
151166 if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
152167 bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
153168
154− mutex_lock(&mm->context.lock);
155− size = mm->context.size * LDT_ENTRY_SIZE;
169+ size = mm->context.ldt->size * LDT_ENTRY_SIZE;
156170 if (size > bytecount)
157171 size = bytecount;
158172
159− err = 0;
160− if (copy_to_user(ptr, mm->context.ldt, size))
161− err = -EFAULT;
162− mutex_unlock(&mm->context.lock);
163− if (err < 0)
164− goto error_return;
173+ if (copy_to_user(ptr, mm->context.ldt->entries, size)) {
174+ retval = -EFAULT;
175+ goto out_unlock;
176+ }
177+
165178 if (size != bytecount) {
166− /* zero-fill the rest */
167− if (clear_user(ptr + size, bytecount - size) != 0) {
168− err = -EFAULT;
169− goto error_return;
179+ /* Zero-fill the rest and pretend we read bytecount bytes. */
180+ if (clear_user(ptr + size, bytecount - size)) {
181+ retval = -EFAULT;
182+ goto out_unlock;
170183 }
171184 }
172− return bytecount;
173−error_return:
174− return err;
185+ retval = bytecount;
186+
187+out_unlock:
188+ mutex_unlock(&mm->context.lock);
189+ return retval;
175190 }
176191
177192 static int read_default_ldt(void __user *ptr, unsigned long bytecount)
@@ -195,6 +210,8 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) · 17 unmodified lines
195210 struct desc_struct ldt;
196211 int error;
197212 struct user_desc ldt_info;
213+ int oldsize, newsize;
214+ struct ldt_struct *new_ldt, *old_ldt;
198215
199216 error = -EINVAL;
200217 if (bytecount != sizeof(ldt_info))
@@ -213,34 +230,39 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) · 12 unmodified lines
213230 goto out;
214231 }
215232
216− mutex_lock(&mm->context.lock);
217− if (ldt_info.entry_number >= mm->context.size) {
218− error = alloc_ldt(&current->mm->context,
219− ldt_info.entry_number + 1, 1);
220− if (error < 0)
221− goto out_unlock;
222− }
223−
224− /* Allow LDTs to be cleared by the user. */
225− if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
226− if (oldmode || LDT_empty(&ldt_info)) {
227− memset(&ldt, 0, sizeof(ldt));
228− goto install;
233+ if ((oldmode && !ldt_info.base_addr && !ldt_info.limit) ||
234+ LDT_empty(&ldt_info)) {
235+ /* The user wants to clear the entry. */
236+ memset(&ldt, 0, sizeof(ldt));
237+ } else {
238+ if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
239+ error = -EINVAL;
240+ goto out;
229241 }
242+
243+ fill_ldt(&ldt, &ldt_info);
244+ if (oldmode)
245+ ldt.avl = 0;
230246 }
231247
232− if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
233− error = -EINVAL;
248+ mutex_lock(&mm->context.lock);
249+
250+ old_ldt = mm->context.ldt;
251+ oldsize = old_ldt ? old_ldt->size : 0;
252+ newsize = max((int)(ldt_info.entry_number + 1), oldsize);
253+
254+ error = -ENOMEM;
255+ new_ldt = alloc_ldt_struct(newsize);
256+ if (!new_ldt)
234257 goto out_unlock;
235− }
236258
237− fill_ldt(&ldt, &ldt_info);
238− if (oldmode)
239− ldt.avl = 0;
259+ if (old_ldt)
260+ memcpy(new_ldt->entries, old_ldt->entries, oldsize * LDT_ENTRY_SIZE);
261+ new_ldt->entries[ldt_info.entry_number] = ldt;
262+ finalize_ldt_struct(new_ldt);
240263
241− /* Install the new entry ... */
242−install:
243− write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
264+ install_ldt(mm, new_ldt);
265+ free_ldt_struct(old_ldt);
244266 error = 0;
245267
246268 out_unlock:
arch/x86/kernel/process_64.c+2−2
@@ -121,11 +121,11 @@ void __show_regs(struct pt_regs *regs, int all) · 120 unmodified lines
121121 void release_thread(struct task_struct *dead_task)
122122 {
123123 if (dead_task->mm) {
124− if (dead_task->mm->context.size) {
124+ if (dead_task->mm->context.ldt) {
125125 pr_warn("WARNING: dead process %s still has LDT? <%p/%d>\n",
126126 dead_task->comm,
127127 dead_task->mm->context.ldt,
128− dead_task->mm->context.size);
128+ dead_task->mm->context.ldt->size);
129129 BUG();
130130 }
131131 }
arch/x86/kernel/step.c+4−2
@@ -5,6 +5,7 @@ · 4 unmodified lines
55 #include <linux/mm.h>
66 #include <linux/ptrace.h>
77 #include <asm/desc.h>
8+#include <asm/mmu_context.h>
89
910 unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
1011 {
@@ -30,10 +31,11 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re · 19 unmodified lines
3031 seg &= ~7UL;
3132
3233 mutex_lock(&child->mm->context.lock);
33− if (unlikely((seg >> 3) >= child->mm->context.size))
34+ if (unlikely(!child->mm->context.ldt ||
35+ (seg >> 3) >= child->mm->context.ldt->size))
3436 addr = -1L; /* bogus selector, access would fault */
3537 else {
36− desc = child->mm->context.ldt + seg;
38+ desc = &child->mm->context.ldt->entries[seg];
3739 base = get_desc_base(desc);
3840
3941 /* 16-bit code segment? */
arch/x86/power/cpu.c+2−1
@@ -22,6 +22,7 @@ · 21 unmodified lines
2222 #include <asm/fpu/internal.h>
2323 #include <asm/debugreg.h>
2424 #include <asm/cpu.h>
25+#include <asm/mmu_context.h>
2526
2627 #ifdef CONFIG_X86_32
2728 __visible unsigned long saved_context_ebx;
@@ -153,7 +154,7 @@ static void fix_processor_context(void) · 125 unmodified lines
153154 syscall_init(); /* This sets MSR_*STAR and related */
154155 #endif
155156 load_TR_desc(); /* This does ltr */
156− load_LDT(&current->active_mm->context); /* This does lldt */
157+ load_mm_ldt(current->active_mm); /* This does lldt */
157158
158159 fpu__resume_cpu();
159160 }