[PATCH 4.14 16/74] x86/ldt: Prevent LDT inheritance on exec

2017-12-27 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Thomas Gleixner 

commit a4828f81037f491b2cc986595e3a969a6eeb2fb5 upstream.

The LDT is inherited across fork() or exec(), but that makes no sense
at all because exec() is supposed to start the process clean.

The reason why this happens is that init_new_context_ldt() is called from
init_new_context() which obviously needs to be called for both fork() and
exec().

It would be surprising if anything relies on that behaviour, so it seems to
be safe to remove that misfeature.

Split the context initialization into two parts. Clear the LDT pointer and
initialize the mutex from the general context init and move the LDT
duplication to arch_dup_mmap() which is only called on fork().

Signed-off-by: Thomas Gleixner 
Signed-off-by: Peter Zijlstra 
Cc: Andy Lutomirski 
Cc: Andy Lutomirsky 
Cc: Boris Ostrovsky 
Cc: Borislav Petkov 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Dave Hansen 
Cc: Dave Hansen 
Cc: David Laight 
Cc: Denys Vlasenko 
Cc: Eduardo Valentin 
Cc: Greg KH 
Cc: H. Peter Anvin 
Cc: Josh Poimboeuf 
Cc: Juergen Gross 
Cc: Linus Torvalds 
Cc: Will Deacon 
Cc: aligu...@amazon.com
Cc: dan.j.willi...@intel.com
Cc: hu...@google.com
Cc: keesc...@google.com
Cc: kirill.shute...@linux.intel.com
Cc: linux...@kvack.org
Signed-off-by: Ingo Molnar 
Signed-off-by: Greg Kroah-Hartman 

---
 arch/x86/include/asm/mmu_context.h|   21 ++---
 arch/x86/kernel/ldt.c |   18 +-
 tools/testing/selftests/x86/ldt_gdt.c |9 +++--
 3 files changed, 22 insertions(+), 26 deletions(-)

--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -57,11 +57,17 @@ struct ldt_struct {
 /*
  * Used for LDT copy/destruction.
  */
-int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm);
+static inline void init_new_context_ldt(struct mm_struct *mm)
+{
+   mm->context.ldt = NULL;
+   init_rwsem(>context.ldt_usr_sem);
+}
+int ldt_dup_context(struct mm_struct *oldmm, struct mm_struct *mm);
 void destroy_context_ldt(struct mm_struct *mm);
 #else  /* CONFIG_MODIFY_LDT_SYSCALL */
-static inline int init_new_context_ldt(struct task_struct *tsk,
-  struct mm_struct *mm)
+static inline void init_new_context_ldt(struct mm_struct *mm) { }
+static inline int ldt_dup_context(struct mm_struct *oldmm,
+ struct mm_struct *mm)
 {
return 0;
 }
@@ -137,15 +143,16 @@ static inline int init_new_context(struc
mm->context.ctx_id = atomic64_inc_return(_mm_ctx_id);
atomic64_set(>context.tlb_gen, 0);
 
-   #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
if (cpu_feature_enabled(X86_FEATURE_OSPKE)) {
/* pkey 0 is the default and always allocated */
mm->context.pkey_allocation_map = 0x1;
/* -1 means unallocated or invalid */
mm->context.execute_only_pkey = -1;
}
-   #endif
-   return init_new_context_ldt(tsk, mm);
+#endif
+   init_new_context_ldt(mm);
+   return 0;
 }
 static inline void destroy_context(struct mm_struct *mm)
 {
@@ -181,7 +188,7 @@ do {\
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
paravirt_arch_dup_mmap(oldmm, mm);
-   return 0;
+   return ldt_dup_context(oldmm, mm);
 }
 
 static inline void arch_exit_mmap(struct mm_struct *mm)
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -131,28 +131,20 @@ static void free_ldt_struct(struct ldt_s
 }
 
 /*
- * we do not have to muck with descriptors here, that is
- * done in switch_mm() as needed.
+ * Called on fork from arch_dup_mmap(). Just copy the current LDT state,
+ * the new task is not running, so nothing can be installed.
  */
-int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm)
+int ldt_dup_context(struct mm_struct *old_mm, struct mm_struct *mm)
 {
struct ldt_struct *new_ldt;
-   struct mm_struct *old_mm;
int retval = 0;
 
-   init_rwsem(>context.ldt_usr_sem);
-
-   old_mm = current->mm;
-   if (!old_mm) {
-   mm->context.ldt = NULL;
+   if (!old_mm)
return 0;
-   }
 
mutex_lock(_mm->context.lock);
-   if (!old_mm->context.ldt) {
-   mm->context.ldt = NULL;
+   if 

[PATCH 4.14 16/74] x86/ldt: Prevent LDT inheritance on exec

2017-12-27 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Thomas Gleixner 

commit a4828f81037f491b2cc986595e3a969a6eeb2fb5 upstream.

The LDT is inherited across fork() or exec(), but that makes no sense
at all because exec() is supposed to start the process clean.

The reason why this happens is that init_new_context_ldt() is called from
init_new_context() which obviously needs to be called for both fork() and
exec().

It would be surprising if anything relies on that behaviour, so it seems to
be safe to remove that misfeature.

Split the context initialization into two parts. Clear the LDT pointer and
initialize the mutex from the general context init and move the LDT
duplication to arch_dup_mmap() which is only called on fork().

Signed-off-by: Thomas Gleixner 
Signed-off-by: Peter Zijlstra 
Cc: Andy Lutomirski 
Cc: Andy Lutomirsky 
Cc: Boris Ostrovsky 
Cc: Borislav Petkov 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Dave Hansen 
Cc: Dave Hansen 
Cc: David Laight 
Cc: Denys Vlasenko 
Cc: Eduardo Valentin 
Cc: Greg KH 
Cc: H. Peter Anvin 
Cc: Josh Poimboeuf 
Cc: Juergen Gross 
Cc: Linus Torvalds 
Cc: Will Deacon 
Cc: aligu...@amazon.com
Cc: dan.j.willi...@intel.com
Cc: hu...@google.com
Cc: keesc...@google.com
Cc: kirill.shute...@linux.intel.com
Cc: linux...@kvack.org
Signed-off-by: Ingo Molnar 
Signed-off-by: Greg Kroah-Hartman 

---
 arch/x86/include/asm/mmu_context.h|   21 ++---
 arch/x86/kernel/ldt.c |   18 +-
 tools/testing/selftests/x86/ldt_gdt.c |9 +++--
 3 files changed, 22 insertions(+), 26 deletions(-)

--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -57,11 +57,17 @@ struct ldt_struct {
 /*
  * Used for LDT copy/destruction.
  */
-int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm);
+static inline void init_new_context_ldt(struct mm_struct *mm)
+{
+   mm->context.ldt = NULL;
+   init_rwsem(>context.ldt_usr_sem);
+}
+int ldt_dup_context(struct mm_struct *oldmm, struct mm_struct *mm);
 void destroy_context_ldt(struct mm_struct *mm);
 #else  /* CONFIG_MODIFY_LDT_SYSCALL */
-static inline int init_new_context_ldt(struct task_struct *tsk,
-  struct mm_struct *mm)
+static inline void init_new_context_ldt(struct mm_struct *mm) { }
+static inline int ldt_dup_context(struct mm_struct *oldmm,
+ struct mm_struct *mm)
 {
return 0;
 }
@@ -137,15 +143,16 @@ static inline int init_new_context(struc
mm->context.ctx_id = atomic64_inc_return(_mm_ctx_id);
atomic64_set(>context.tlb_gen, 0);
 
-   #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
if (cpu_feature_enabled(X86_FEATURE_OSPKE)) {
/* pkey 0 is the default and always allocated */
mm->context.pkey_allocation_map = 0x1;
/* -1 means unallocated or invalid */
mm->context.execute_only_pkey = -1;
}
-   #endif
-   return init_new_context_ldt(tsk, mm);
+#endif
+   init_new_context_ldt(mm);
+   return 0;
 }
 static inline void destroy_context(struct mm_struct *mm)
 {
@@ -181,7 +188,7 @@ do {\
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
paravirt_arch_dup_mmap(oldmm, mm);
-   return 0;
+   return ldt_dup_context(oldmm, mm);
 }
 
 static inline void arch_exit_mmap(struct mm_struct *mm)
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -131,28 +131,20 @@ static void free_ldt_struct(struct ldt_s
 }
 
 /*
- * we do not have to muck with descriptors here, that is
- * done in switch_mm() as needed.
+ * Called on fork from arch_dup_mmap(). Just copy the current LDT state,
+ * the new task is not running, so nothing can be installed.
  */
-int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm)
+int ldt_dup_context(struct mm_struct *old_mm, struct mm_struct *mm)
 {
struct ldt_struct *new_ldt;
-   struct mm_struct *old_mm;
int retval = 0;
 
-   init_rwsem(>context.ldt_usr_sem);
-
-   old_mm = current->mm;
-   if (!old_mm) {
-   mm->context.ldt = NULL;
+   if (!old_mm)
return 0;
-   }
 
mutex_lock(_mm->context.lock);
-   if (!old_mm->context.ldt) {
-   mm->context.ldt = NULL;
+   if (!old_mm->context.ldt)
goto out_unlock;
-   }
 
new_ldt = alloc_ldt_struct(old_mm->context.ldt->nr_entries);
if (!new_ldt) {
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -627,13 +627,10 @@ static void do_multicpu_tests(void)
 static int finish_exec_test(void)
 {
/*
-* In a sensible world, this would be check_invalid_segment(0, 1);
-* For better or for worse, though, the LDT