All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luis Henriques <luis.henriques@canonical.com>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	kernel-team@lists.ubuntu.com
Cc: Ingo Molnar <mingo@kernel.org>,
	"security@kernel.org" <security@kernel.org>,
	Denys Vlasenko <dvlasenk@redhat.com>,
	Jan Beulich <jbeulich@suse.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Andy Lutomirski <luto@amacapital.net>,
	Luis Henriques <luis.henriques@canonical.com>,
	Borislav Petkov <bp@alien8.de>, Andy Lutomirski <luto@kernel.org>,
	Brian Gerst <brgerst@gmail.com>,
	Sasha Levin <sasha.levin@oracle.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	xen-devel <xen-devel@lists.xen.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH 3.16.y-ckt 095/130] x86/ldt: Make modify_ldt synchronous
Date: Fri,  4 Sep 2015 14:08:03 +0100	[thread overview]
Message-ID: <1441372118-5933-96-git-send-email-luis.henriques__30433.5411907688$1441372340$gmane$org@canonical.com> (raw)
In-Reply-To: <1441372118-5933-1-git-send-email-luis.henriques@canonical.com>

3.16.7-ckt17 -stable review patch.  If anyone has any objections, please let me know.

------------------

From: Andy Lutomirski <luto@kernel.org>

commit 37868fe113ff2ba814b3b4eb12df214df555f8dc upstream.

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.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: security@kernel.org <security@kernel.org>
Cc: xen-devel <xen-devel@lists.xen.org>
Link: http://lkml.kernel.org/r/4c6978476782160600471bd865b318db34c7b628.1438291540.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
[ luis: backported to 3.16:
  - dropped changes to comments in switch_mm()
  - included asm/mmu_context.h in perf_event.c
  - adjusted context ]
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
---
 arch/x86/include/asm/desc.h        |  15 ---
 arch/x86/include/asm/mmu.h         |   3 +-
 arch/x86/include/asm/mmu_context.h |  48 ++++++-
 arch/x86/kernel/cpu/common.c       |   4 +-
 arch/x86/kernel/cpu/perf_event.c   |  13 +-
 arch/x86/kernel/ldt.c              | 262 ++++++++++++++++++++-----------------
 arch/x86/kernel/process_64.c       |   4 +-
 arch/x86/kernel/step.c             |   6 +-
 arch/x86/power/cpu.c               |   3 +-
 9 files changed, 208 insertions(+), 150 deletions(-)

diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index a94b82e8f156..69126184c609 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -280,21 +280,6 @@ static inline void clear_LDT(void)
 	set_ldt(NULL, 0);
 }
 
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
-	set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
-	preempt_disable();
-	load_LDT_nolock(pc);
-	preempt_enable();
-}
-
 static inline unsigned long get_desc_base(const struct desc_struct *desc)
 {
 	return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h
index 876e74e8eec7..b6b7bc3f5d26 100644
--- a/arch/x86/include/asm/mmu.h
+++ b/arch/x86/include/asm/mmu.h
@@ -9,8 +9,7 @@
  * we put the segment information here.
  */
 typedef struct {
-	void *ldt;
-	int size;
+	struct ldt_struct *ldt;
 
 #ifdef CONFIG_X86_64
 	/* True if mm supports a task running in 32 bit compatibility mode. */
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index be12c534fd59..86fef96f4eca 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -16,6 +16,50 @@ static inline void paravirt_activate_mm(struct mm_struct *prev,
 #endif	/* !CONFIG_PARAVIRT */
 
 /*
+ * ldt_structs can be allocated, used, and freed, but they are never
+ * modified while live.
+ */
+struct ldt_struct {
+	/*
+	 * Xen requires page-aligned LDTs with special permissions.  This is
+	 * needed to prevent us from installing evil descriptors such as
+	 * call gates.  On native, we could merge the ldt_struct and LDT
+	 * allocations, but it's not worth trying to optimize.
+	 */
+	struct desc_struct *entries;
+	int size;
+};
+
+static inline void load_mm_ldt(struct mm_struct *mm)
+{
+	struct ldt_struct *ldt;
+
+	/* lockless_dereference synchronizes with smp_store_release */
+	ldt = lockless_dereference(mm->context.ldt);
+
+	/*
+	 * Any change to mm->context.ldt is followed by an IPI to all
+	 * CPUs with the mm active.  The LDT will not be freed until
+	 * after the IPI is handled by all such CPUs.  This means that,
+	 * if the ldt_struct changes before we return, the values we see
+	 * will be safe, and the new values will be loaded before we run
+	 * any user code.
+	 *
+	 * NB: don't try to convert this to use RCU without extreme care.
+	 * We would still need IRQs off, because we don't want to change
+	 * the local LDT after an IPI loaded a newer value than the one
+	 * that we can see.
+	 */
+
+	if (unlikely(ldt))
+		set_ldt(ldt->entries, ldt->size);
+	else
+		clear_LDT();
+
+	DEBUG_LOCKS_WARN_ON(preemptible());
+}
+
+/*
  * Used for LDT copy/destruction.
  */
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
@@ -50,7 +94,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
 		/* Load the LDT, if the LDT is different: */
 		if (unlikely(prev->context.ldt != next->context.ldt))
-			load_LDT_nolock(&next->context);
+			load_mm_ldt(next);
 	}
 #ifdef CONFIG_SMP
 	  else {
@@ -71,7 +115,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			 * to make sure to use no freed page tables.
 			 */
 			load_cr3(next->pgd);
-			load_LDT_nolock(&next->context);
+			load_mm_ldt(next);
 		}
 	}
 #endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1f3a8885f836..8fc57acf86f4 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1355,7 +1355,7 @@ void cpu_init(void)
 	load_sp0(t, &current->thread);
 	set_tss_desc(cpu, t);
 	load_TR_desc();
-	load_LDT(&init_mm.context);
+	load_mm_ldt(&init_mm);
 
 	clear_all_debug_regs();
 	dbg_restore_debug_regs();
@@ -1402,7 +1402,7 @@ void cpu_init(void)
 	load_sp0(t, thread);
 	set_tss_desc(cpu, t);
 	load_TR_desc();
-	load_LDT(&init_mm.context);
+	load_mm_ldt(&init_mm);
 
 	t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
 
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 2879ecdaac43..2a6c3859e8a1 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -31,6 +31,7 @@
 #include <asm/nmi.h>
 #include <asm/smp.h>
 #include <asm/alternative.h>
+#include <asm/mmu_context.h>
 #include <asm/timer.h>
 #include <asm/desc.h>
 #include <asm/ldt.h>
@@ -1984,21 +1985,25 @@ static unsigned long get_segment_base(unsigned int segment)
 	int idx = segment >> 3;
 
 	if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+		struct ldt_struct *ldt;
+
 		if (idx > LDT_ENTRIES)
 			return 0;
 
-		if (idx > current->active_mm->context.size)
+		/* IRQs are off, so this synchronizes with smp_store_release */
+		ldt = lockless_dereference(current->active_mm->context.ldt);
+		if (!ldt || idx > ldt->size)
 			return 0;
 
-		desc = current->active_mm->context.ldt;
+		desc = &ldt->entries[idx];
 	} else {
 		if (idx > GDT_ENTRIES)
 			return 0;
 
-		desc = __this_cpu_ptr(&gdt_page.gdt[0]);
+		desc = __this_cpu_ptr(&gdt_page.gdt[0]) + idx;
 	}
 
-	return get_desc_base(desc + idx);
+	return get_desc_base(desc);
 }
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index c37886d759cc..2bcc0525f1c1 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 
@@ -20,82 +21,82 @@
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 
-#ifdef CONFIG_SMP
+/* context.lock is held for us, so we don't need any locking. */
 static void flush_ldt(void *current_mm)
 {
-	if (current->active_mm == current_mm)
-		load_LDT(&current->active_mm->context);
+	mm_context_t *pc;
+
+	if (current->active_mm != current_mm)
+		return;
+
+	pc = &current->active_mm->context;
+	set_ldt(pc->ldt->entries, pc->ldt->size);
 }
-#endif
 
-static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+/* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
+static struct ldt_struct *alloc_ldt_struct(int size)
 {
-	void *oldldt, *newldt;
-	int oldsize;
-
-	if (mincount <= pc->size)
-		return 0;
-	oldsize = pc->size;
-	mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
-			(~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
-	if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
-		newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
+	struct ldt_struct *new_ldt;
+	int alloc_size;
+
+	if (size > LDT_ENTRIES)
+		return NULL;
+
+	new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL);
+	if (!new_ldt)
+		return NULL;
+
+	BUILD_BUG_ON(LDT_ENTRY_SIZE != sizeof(struct desc_struct));
+	alloc_size = size * LDT_ENTRY_SIZE;
+
+	/*
+	 * Xen is very picky: it requires a page-aligned LDT that has no
+	 * trailing nonzero bytes in any page that contains LDT descriptors.
+	 * Keep it simple: zero the whole allocation and never allocate less
+	 * than PAGE_SIZE.
+	 */
+	if (alloc_size > PAGE_SIZE)
+		new_ldt->entries = vzalloc(alloc_size);
 	else
-		newldt = (void *)__get_free_page(GFP_KERNEL);
-
-	if (!newldt)
-		return -ENOMEM;
+		new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL);
 
-	if (oldsize)
-		memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
-	oldldt = pc->ldt;
-	memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
-	       (mincount - oldsize) * LDT_ENTRY_SIZE);
+	if (!new_ldt->entries) {
+		kfree(new_ldt);
+		return NULL;
+	}
 
-	paravirt_alloc_ldt(newldt, mincount);
+	new_ldt->size = size;
+	return new_ldt;
+}
 
-#ifdef CONFIG_X86_64
-	/* CHECKME: Do we really need this ? */
-	wmb();
-#endif
-	pc->ldt = newldt;
-	wmb();
-	pc->size = mincount;
-	wmb();
-
-	if (reload) {
-#ifdef CONFIG_SMP
-		preempt_disable();
-		load_LDT(pc);
-		if (!cpumask_equal(mm_cpumask(current->mm),
-				   cpumask_of(smp_processor_id())))
-			smp_call_function(flush_ldt, current->mm, 1);
-		preempt_enable();
-#else
-		load_LDT(pc);
-#endif
-	}
-	if (oldsize) {
-		paravirt_free_ldt(oldldt, oldsize);
-		if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
-			vfree(oldldt);
-		else
-			put_page(virt_to_page(oldldt));
-	}
-	return 0;
+/* After calling this, the LDT is immutable. */
+static void finalize_ldt_struct(struct ldt_struct *ldt)
+{
+	paravirt_alloc_ldt(ldt->entries, ldt->size);
 }
 
-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+/* context.lock is held */
+static void install_ldt(struct mm_struct *current_mm,
+			struct ldt_struct *ldt)
 {
-	int err = alloc_ldt(new, old->size, 0);
-	int i;
+	/* Synchronizes with lockless_dereference in load_mm_ldt. */
+	smp_store_release(&current_mm->context.ldt, ldt);
+
+	/* Activate the LDT for all CPUs using current_mm. */
+	on_each_cpu_mask(mm_cpumask(current_mm), flush_ldt, current_mm, true);
+}
 
-	if (err < 0)
-		return err;
+static void free_ldt_struct(struct ldt_struct *ldt)
+{
+	if (likely(!ldt))
+		return;
 
-	for (i = 0; i < old->size; i++)
-		write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
-	return 0;
+	paravirt_free_ldt(ldt->entries, ldt->size);
+	if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
+		vfree(ldt->entries);
+	else
+		kfree(ldt->entries);
+	kfree(ldt);
 }
 
 /*
@@ -104,17 +105,37 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
  */
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
+	struct ldt_struct *new_ldt;
 	struct mm_struct *old_mm;
 	int retval = 0;
 
 	mutex_init(&mm->context.lock);
-	mm->context.size = 0;
 	old_mm = current->mm;
-	if (old_mm && old_mm->context.size > 0) {
-		mutex_lock(&old_mm->context.lock);
-		retval = copy_ldt(&mm->context, &old_mm->context);
-		mutex_unlock(&old_mm->context.lock);
+	if (!old_mm) {
+		mm->context.ldt = NULL;
+		return 0;
 	}
+
+	mutex_lock(&old_mm->context.lock);
+	if (!old_mm->context.ldt) {
+		mm->context.ldt = NULL;
+		goto out_unlock;
+	}
+
+	new_ldt = alloc_ldt_struct(old_mm->context.ldt->size);
+	if (!new_ldt) {
+		retval = -ENOMEM;
+		goto out_unlock;
+	}
+
+	memcpy(new_ldt->entries, old_mm->context.ldt->entries,
+	       new_ldt->size * LDT_ENTRY_SIZE);
+	finalize_ldt_struct(new_ldt);
+
+	mm->context.ldt = new_ldt;
+
+out_unlock:
+	mutex_unlock(&old_mm->context.lock);
 	return retval;
 }
 
@@ -125,53 +146,47 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
  */
 void destroy_context(struct mm_struct *mm)
 {
-	if (mm->context.size) {
-#ifdef CONFIG_X86_32
-		/* CHECKME: Can this ever happen ? */
-		if (mm == current->active_mm)
-			clear_LDT();
-#endif
-		paravirt_free_ldt(mm->context.ldt, mm->context.size);
-		if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
-			vfree(mm->context.ldt);
-		else
-			put_page(virt_to_page(mm->context.ldt));
-		mm->context.size = 0;
-	}
+	free_ldt_struct(mm->context.ldt);
+	mm->context.ldt = NULL;
 }
 
 static int read_ldt(void __user *ptr, unsigned long bytecount)
 {
-	int err;
+	int retval;
 	unsigned long size;
 	struct mm_struct *mm = current->mm;
 
-	if (!mm->context.size)
-		return 0;
+	mutex_lock(&mm->context.lock);
+
+	if (!mm->context.ldt) {
+		retval = 0;
+		goto out_unlock;
+	}
+
 	if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
 		bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
 
-	mutex_lock(&mm->context.lock);
-	size = mm->context.size * LDT_ENTRY_SIZE;
+	size = mm->context.ldt->size * LDT_ENTRY_SIZE;
 	if (size > bytecount)
 		size = bytecount;
 
-	err = 0;
-	if (copy_to_user(ptr, mm->context.ldt, size))
-		err = -EFAULT;
-	mutex_unlock(&mm->context.lock);
-	if (err < 0)
-		goto error_return;
+	if (copy_to_user(ptr, mm->context.ldt->entries, size)) {
+		retval = -EFAULT;
+		goto out_unlock;
+	}
+
 	if (size != bytecount) {
-		/* zero-fill the rest */
-		if (clear_user(ptr + size, bytecount - size) != 0) {
-			err = -EFAULT;
-			goto error_return;
+		/* Zero-fill the rest and pretend we read bytecount bytes. */
+		if (clear_user(ptr + size, bytecount - size)) {
+			retval = -EFAULT;
+			goto out_unlock;
 		}
 	}
-	return bytecount;
-error_return:
-	return err;
+	retval = bytecount;
+
+out_unlock:
+	mutex_unlock(&mm->context.lock);
+	return retval;
 }
 
 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)
 	struct desc_struct ldt;
 	int error;
 	struct user_desc ldt_info;
+	int oldsize, newsize;
+	struct ldt_struct *new_ldt, *old_ldt;
 
 	error = -EINVAL;
 	if (bytecount != sizeof(ldt_info))
@@ -213,34 +230,39 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 			goto out;
 	}
 
-	mutex_lock(&mm->context.lock);
-	if (ldt_info.entry_number >= mm->context.size) {
-		error = alloc_ldt(&current->mm->context,
-				  ldt_info.entry_number + 1, 1);
-		if (error < 0)
-			goto out_unlock;
-	}
-
-	/* Allow LDTs to be cleared by the user. */
-	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
-		if (oldmode || LDT_empty(&ldt_info)) {
-			memset(&ldt, 0, sizeof(ldt));
-			goto install;
+	if ((oldmode && !ldt_info.base_addr && !ldt_info.limit) ||
+	    LDT_empty(&ldt_info)) {
+		/* The user wants to clear the entry. */
+		memset(&ldt, 0, sizeof(ldt));
+	} else {
+		if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
+			error = -EINVAL;
+			goto out;
 		}
+
+		fill_ldt(&ldt, &ldt_info);
+		if (oldmode)
+			ldt.avl = 0;
 	}
 
-	if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
-		error = -EINVAL;
+	mutex_lock(&mm->context.lock);
+
+	old_ldt = mm->context.ldt;
+	oldsize = old_ldt ? old_ldt->size : 0;
+	newsize = max((int)(ldt_info.entry_number + 1), oldsize);
+
+	error = -ENOMEM;
+	new_ldt = alloc_ldt_struct(newsize);
+	if (!new_ldt)
 		goto out_unlock;
-	}
 
-	fill_ldt(&ldt, &ldt_info);
-	if (oldmode)
-		ldt.avl = 0;
+	if (old_ldt)
+		memcpy(new_ldt->entries, old_ldt->entries, oldsize * LDT_ENTRY_SIZE);
+	new_ldt->entries[ldt_info.entry_number] = ldt;
+	finalize_ldt_struct(new_ldt);
 
-	/* Install the new entry ...  */
-install:
-	write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
+	install_ldt(mm, new_ldt);
+	free_ldt_struct(old_ldt);
 	error = 0;
 
 out_unlock:
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 166119618afb..e84487aa2fd2 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -122,11 +122,11 @@ void __show_regs(struct pt_regs *regs, int all)
 void release_thread(struct task_struct *dead_task)
 {
 	if (dead_task->mm) {
-		if (dead_task->mm->context.size) {
+		if (dead_task->mm->context.ldt) {
 			pr_warn("WARNING: dead process %s still has LDT? <%p/%d>\n",
 				dead_task->comm,
 				dead_task->mm->context.ldt,
-				dead_task->mm->context.size);
+				dead_task->mm->context.ldt->size);
 			BUG();
 		}
 	}
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index 9b4d51d0c0d0..6273324186ac 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -5,6 +5,7 @@
 #include <linux/mm.h>
 #include <linux/ptrace.h>
 #include <asm/desc.h>
+#include <asm/mmu_context.h>
 
 unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
 {
@@ -30,10 +31,11 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re
 		seg &= ~7UL;
 
 		mutex_lock(&child->mm->context.lock);
-		if (unlikely((seg >> 3) >= child->mm->context.size))
+		if (unlikely(!child->mm->context.ldt ||
+			     (seg >> 3) >= child->mm->context.ldt->size))
 			addr = -1L; /* bogus selector, access would fault */
 		else {
-			desc = child->mm->context.ldt + seg;
+			desc = &child->mm->context.ldt->entries[seg];
 			base = get_desc_base(desc);
 
 			/* 16-bit code segment? */
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 424f4c97a44d..6c8e2f5ce056 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -23,6 +23,7 @@
 #include <asm/debugreg.h>
 #include <asm/fpu-internal.h> /* pcntxt_mask */
 #include <asm/cpu.h>
+#include <asm/mmu_context.h>
 
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
@@ -157,7 +158,7 @@ static void fix_processor_context(void)
 	syscall_init();				/* This sets MSR_*STAR and related */
 #endif
 	load_TR_desc();				/* This does ltr */
-	load_LDT(&current->active_mm->context);	/* This does lldt */
+	load_mm_ldt(current->active_mm);	/* This does lldt */
 }
 
 /**

  parent reply	other threads:[~2015-09-04 13:08 UTC|newest]

Thread overview: 133+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-04 13:06 [3.16.y-ckt stable] Linux 3.16.7-ckt17 stable review Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 001/130] md: use kzalloc() when bitmap is disabled Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 002/130] sparc64: Fix userspace FPU register corruptions Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 003/130] sysfs: Create mountpoints with sysfs_create_mount_point Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 004/130] ARM: OMAP2+: hwmod: Fix _wait_target_ready() for hwmods without sysc Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 005/130] ASoC: pcm1681: Fix setting de-emphasis sampling rate selection Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 006/130] iscsi-target: Fix use-after-free during TPG session shutdown Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 007/130] iscsi-target: Fix iscsit_start_kthreads failure OOPs Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 008/130] iscsi-target: Fix iser explicit logout TX kthread leak Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 009/130] ARM: dts: i.MX35: Fix can support Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 010/130] ALSA: hda - Apply fixup for another Toshiba Satellite S50D Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 011/130] vhost: actually track log eventfd file Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 012/130] arm64/efi: map the entire UEFI vendor string before reading it Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 013/130] xfs: remote attribute headers contain an invalid LSN Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 014/130] xfs: remote attributes need to be considered data Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 015/130] ALSA: hda - Apply a fixup to Dell Vostro 5480 Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 016/130] ALSA: usb-audio: add dB range mapping for some devices Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 017/130] drm/i915: Replace WARN inside I915_READ64_2x32 with retry loop Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 018/130] drm/radeon/combios: add some validation of lvds values Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 019/130] x86/efi: Use all 64 bit of efi_memmap in setup_e820() Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 020/130] ipr: Fix locking for unit attention handling Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 021/130] ipr: Fix incorrect trace indexing Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 022/130] ipr: Fix invalid array indexing for HRRQ Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 023/130] ALSA: hda - Fix MacBook Pro 5,2 quirk Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 024/130] x86/xen: Probe target addresses in set_aliased_prot() before the hypercall Luis Henriques
2015-09-04 13:06   ` Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 025/130] netfilter: ctnetlink: put back references to master ct and expect objects Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 026/130] ipvs: do not use random local source address for tunnels Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 027/130] ipvs: fix crash if scheduler is changed Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 028/130] ipvs: fix crash with sync protocol v0 and FTP Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 029/130] netfilter: nf_conntrack: Support expectations in different zones Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 030/130] NFS: Don't revalidate the mapping if both size and change attr are up to date Luis Henriques
2015-09-04 13:06 ` [PATCH 3.16.y-ckt 031/130] ALSA: hda - fix cs4210_spdif_automute() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 032/130] net/mlx4_core: Fix wrong index in propagating port change event to VFs Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 033/130] niu: don't count tx error twice in case of headroom realloc fails Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 034/130] avr32: handle NULL as a valid clock object Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 035/130] packet: missing dev_put() in packet_do_bind() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 036/130] packet: tpacket_snd(): fix signed/unsigned comparison Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 037/130] bridge: mdb: fix delmdb state in the notification Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 038/130] net: sched: fix refcount imbalance in actions Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 039/130] act_pedit: check binding before calling tcf_hash_release() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 040/130] PCI: Restore PCI_MSIX_FLAGS_BIRMASK definition Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 041/130] USB: qcserial/option: make AT URCs work for Sierra Wireless MC7305/MC7355 Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 042/130] USB: qcserial: Add support for Dell Wireless 5809e 4G Modem Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 043/130] nfsd: Drop BUG_ON and ignore SECLABEL on absent filesystem Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 044/130] crypto: ixp4xx - Remove bogus BUG_ON on scattered dst buffer Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 045/130] USB: sierra: add 1199:68AB device ID Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 046/130] rbd: fix copyup completion race Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 047/130] md/bitmap: return an error when bitmap superblock is corrupt Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 048/130] md/raid1: extend spinlock to protect raid1_end_read_request against inconsistencies Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 049/130] thermal: exynos: Disable the regulator on probe failure Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 050/130] MIPS: Fix sched_getaffinity with MT FPAFF enabled Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 051/130] MIPS: Malta: Don't reinitialise RTC Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 052/130] MIPS: do_mcheck: Fix kernel code dump with EVA Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 053/130] MIPS: show_stack: Fix stack trace " Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 054/130] MIPS: Flush RPS on kernel entry " Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 055/130] xhci: fix off by one error in TRB DMA address boundary check Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 056/130] drivers/usb: Delete XHCI command timer if necessary Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 057/130] ALSA: fireworks/firewire-lib: add support for recent firmware quirk Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 058/130] mm, vmscan: Do not wait for page writeback for GFP_NOFS allocations Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 059/130] MIPS: Make set_pte() SMP safe Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 060/130] ipc: modify message queue accounting to not take kernel data structures into account Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 061/130] ocfs2: fix BUG in ocfs2_downconvert_thread_do_work() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 062/130] fsnotify: fix oops in fsnotify_clear_marks_by_group_flags() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 063/130] drm/radeon: fix hotplug race at startup Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 064/130] rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 065/130] net/tipc: initialize security state for new connection socket Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 066/130] net: pktgen: fix race between pktgen_thread_worker() and kthread_stop() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 067/130] net: call rcu_read_lock early in process_backlog Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 068/130] net: Clone skb before setting peeked flag Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 069/130] net: Fix skb csum races when peeking Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 070/130] net: Fix skb_set_peeked use-after-free bug Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 071/130] ipv6: lock socket in ip6_datagram_connect() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 072/130] bonding: correct the MAC address for "follow" fail_over_mac policy Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 073/130] netlink: don't hold mutex in rcu callback when releasing mmapd ring Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 074/130] rds: fix an integer overflow test in rds_info_getsockopt() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 075/130] udp: fix dst races with multicast early demux Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 076/130] bna: fix interrupts storm caused by erroneous packets Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 077/130] net: gso: use feature flag argument in all protocol gso handlers Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 078/130] Fix firmware loader uevent buffer NULL pointer dereference Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 079/130] qla2xxx: Mark port lost when we receive an RSCN for it Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 080/130] megaraid_sas: use raw_smp_processor_id() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 081/130] fs/buffer.c: support buffer cache allocations with gfp modifiers Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 082/130] bufferhead: Add _gfp version for sb_getblk() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 083/130] ext4: avoid deadlocks in the writeback path by using sb_getblk_gfp Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 084/130] HID: usbhid: add Chicony/Pixart usb optical mouse that needs QUIRK_ALWAYS_POLL Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 085/130] ima: add support for new "euid" policy condition Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 086/130] ima: extend "mask" policy matching support Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 087/130] mfd: arizona: Fix initialisation of the PM runtime Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 088/130] xen-blkfront: don't add indirect pages to list when !feature_persistent Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 089/130] xen-blkback: replace work_pending with work_busy in purge_persistent_gnt() Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 090/130] regmap: regcache-rbtree: Clean new present bits on present bitmap resize Luis Henriques
2015-09-04 13:07 ` [PATCH 3.16.y-ckt 091/130] target/iscsi: Fix double free of a TUR followed by a solicited NOPOUT Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 092/130] target: REPORT LUNS should return LUN 0 even for dynamic ACLs Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 093/130] perf: Fix fasync handling on inherited events Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 094/130] KVM: x86: Use adjustment in guest cycles when handling MSR_IA32_TSC_ADJUST Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 095/130] x86/ldt: Make modify_ldt synchronous Luis Henriques
2015-09-04 13:08 ` Luis Henriques [this message]
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 096/130] x86/ldt: Correct LDT access in single stepping logic Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 097/130] rcu: Provide counterpart to rcu_dereference() for non-RCU situations Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 098/130] rcu: Move lockless_dereference() out of rcupdate.h Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 099/130] x86/ldt: Correct FPU emulation access to LDT Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 100/130] localmodconfig: Use Kbuild files too Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 101/130] dm thin metadata: delete btrees when releasing metadata snapshot Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 102/130] dm btree: add ref counting ops for the leaves of top level btrees Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 103/130] drm/radeon: add new OLAND pci id Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 104/130] libiscsi: Fix host busy blocking during connection teardown Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 105/130] libfc: Fix fc_exch_recv_req() error path Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 106/130] libfc: Fix fc_fcp_cleanup_each_cmd() Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 107/130] EDAC, ppc4xx: Access mci->csrows array elements properly Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 108/130] crypto: caam - fix memory corruption in ahash_final_ctx Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 109/130] drm/vmwgfx: Fix execbuf locking issues Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 110/130] mm/hwpoison: fix page refcount of unknown non LRU page Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 111/130] ipc,sem: fix use after free on IPC_RMID after a task using same semaphore set exits Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 112/130] ipc/sem.c: change memory barrier in sem_lock() to smp_rmb() Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 113/130] ipc/sem.c: update/correct memory barriers Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 114/130] MIPS: Fix seccomp syscall argument for MIPS64 Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 115/130] x86/ldt: Further fix FPU emulation Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 116/130] SCSI: Fix NULL pointer dereference in runtime PM Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 117/130] ALSA: usb-audio: Fix runtime PM unbalance Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 118/130] Add factory recertified Crucial M500s to blacklist Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 119/130] arm64: KVM: Fix host crash when injecting a fault into a 32bit guest Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 120/130] batman-adv: fix kernel crash due to missing NULL checks Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 121/130] batman-adv: protect tt_local_entry from concurrent delete events Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 122/130] perf: Fix PERF_EVENT_IOC_PERIOD migration race Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 123/130] net: Fix RCU splat in af_key Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 124/130] ip6_gre: release cached dst on tunnel removal Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 125/130] s390/sclp: fix compile error Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 126/130] xen/gntdev: convert priv->lock to a mutex Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 127/130] xen/gntdevt: Fix race condition in gntdev_release() Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 128/130] signalfd: fix information leak in signalfd_copyinfo Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 129/130] signal: fix information leak in copy_siginfo_to_user Luis Henriques
2015-09-04 13:08 ` [PATCH 3.16.y-ckt 130/130] signal: fix information leak in copy_siginfo_from_user32 Luis Henriques

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='1441372118-5933-96-git-send-email-luis.henriques__30433.5411907688$1441372340$gmane$org@canonical.com' \
    --to=luis.henriques@canonical.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=dvlasenk@redhat.com \
    --cc=hpa@zytor.com \
    --cc=jbeulich@suse.com \
    --cc=kernel-team@lists.ubuntu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=luto@kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=sasha.levin@oracle.com \
    --cc=security@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.