]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0170-x86-ldt-Prevent-LDT-inheritance-on-exec.patch
revert buggy SCSI error handler commit
[pve-kernel.git] / patches / kernel / 0170-x86-ldt-Prevent-LDT-inheritance-on-exec.patch
1 From ac21d052bf1fbdb4162b1fa522703f4f003f37c1 Mon Sep 17 00:00:00 2001
2 From: Thomas Gleixner <tglx@linutronix.de>
3 Date: Thu, 14 Dec 2017 12:27:31 +0100
4 Subject: [PATCH 170/242] x86/ldt: Prevent LDT inheritance on exec
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 CVE-2017-5754
10
11 The LDT is inherited across fork() or exec(), but that makes no sense
12 at all because exec() is supposed to start the process clean.
13
14 The reason why this happens is that init_new_context_ldt() is called from
15 init_new_context() which obviously needs to be called for both fork() and
16 exec().
17
18 It would be surprising if anything relies on that behaviour, so it seems to
19 be safe to remove that misfeature.
20
21 Split the context initialization into two parts. Clear the LDT pointer and
22 initialize the mutex from the general context init and move the LDT
23 duplication to arch_dup_mmap() which is only called on fork().
24
25 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
26 Signed-off-by: Peter Zijlstra <peterz@infradead.org>
27 Cc: Andy Lutomirski <luto@kernel.org>
28 Cc: Andy Lutomirsky <luto@kernel.org>
29 Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
30 Cc: Borislav Petkov <bp@alien8.de>
31 Cc: Borislav Petkov <bpetkov@suse.de>
32 Cc: Brian Gerst <brgerst@gmail.com>
33 Cc: Dave Hansen <dave.hansen@intel.com>
34 Cc: Dave Hansen <dave.hansen@linux.intel.com>
35 Cc: David Laight <David.Laight@aculab.com>
36 Cc: Denys Vlasenko <dvlasenk@redhat.com>
37 Cc: Eduardo Valentin <eduval@amazon.com>
38 Cc: Greg KH <gregkh@linuxfoundation.org>
39 Cc: H. Peter Anvin <hpa@zytor.com>
40 Cc: Josh Poimboeuf <jpoimboe@redhat.com>
41 Cc: Juergen Gross <jgross@suse.com>
42 Cc: Linus Torvalds <torvalds@linux-foundation.org>
43 Cc: Will Deacon <will.deacon@arm.com>
44 Cc: aliguori@amazon.com
45 Cc: dan.j.williams@intel.com
46 Cc: hughd@google.com
47 Cc: keescook@google.com
48 Cc: kirill.shutemov@linux.intel.com
49 Cc: linux-mm@kvack.org
50 Signed-off-by: Ingo Molnar <mingo@kernel.org>
51 (cherry picked from commit a4828f81037f491b2cc986595e3a969a6eeb2fb5)
52 Signed-off-by: Andy Whitcroft <apw@canonical.com>
53 Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
54 (cherry picked from commit f90d254204df4b336731f23bb5417226f51e8651)
55 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
56 ---
57 arch/x86/include/asm/mmu_context.h | 21 ++++++++++++++-------
58 arch/x86/kernel/ldt.c | 18 +++++-------------
59 tools/testing/selftests/x86/ldt_gdt.c | 9 +++------
60 3 files changed, 22 insertions(+), 26 deletions(-)
61
62 diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
63 index dd865c2acb9d..47ec51a821e8 100644
64 --- a/arch/x86/include/asm/mmu_context.h
65 +++ b/arch/x86/include/asm/mmu_context.h
66 @@ -56,11 +56,17 @@ struct ldt_struct {
67 /*
68 * Used for LDT copy/destruction.
69 */
70 -int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm);
71 +static inline void init_new_context_ldt(struct mm_struct *mm)
72 +{
73 + mm->context.ldt = NULL;
74 + init_rwsem(&mm->context.ldt_usr_sem);
75 +}
76 +int ldt_dup_context(struct mm_struct *oldmm, struct mm_struct *mm);
77 void destroy_context_ldt(struct mm_struct *mm);
78 #else /* CONFIG_MODIFY_LDT_SYSCALL */
79 -static inline int init_new_context_ldt(struct task_struct *tsk,
80 - struct mm_struct *mm)
81 +static inline void init_new_context_ldt(struct mm_struct *mm) { }
82 +static inline int ldt_dup_context(struct mm_struct *oldmm,
83 + struct mm_struct *mm)
84 {
85 return 0;
86 }
87 @@ -136,15 +142,16 @@ static inline int init_new_context(struct task_struct *tsk,
88 mm->context.ctx_id = atomic64_inc_return(&last_mm_ctx_id);
89 atomic64_set(&mm->context.tlb_gen, 0);
90
91 - #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
92 +#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
93 if (cpu_feature_enabled(X86_FEATURE_OSPKE)) {
94 /* pkey 0 is the default and always allocated */
95 mm->context.pkey_allocation_map = 0x1;
96 /* -1 means unallocated or invalid */
97 mm->context.execute_only_pkey = -1;
98 }
99 - #endif
100 - return init_new_context_ldt(tsk, mm);
101 +#endif
102 + init_new_context_ldt(mm);
103 + return 0;
104 }
105 static inline void destroy_context(struct mm_struct *mm)
106 {
107 @@ -180,7 +187,7 @@ do { \
108 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
109 {
110 paravirt_arch_dup_mmap(oldmm, mm);
111 - return 0;
112 + return ldt_dup_context(oldmm, mm);
113 }
114
115 static inline void arch_exit_mmap(struct mm_struct *mm)
116 diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
117 index 3e7208f0c350..74a5aaf13f3c 100644
118 --- a/arch/x86/kernel/ldt.c
119 +++ b/arch/x86/kernel/ldt.c
120 @@ -130,28 +130,20 @@ static void free_ldt_struct(struct ldt_struct *ldt)
121 }
122
123 /*
124 - * we do not have to muck with descriptors here, that is
125 - * done in switch_mm() as needed.
126 + * Called on fork from arch_dup_mmap(). Just copy the current LDT state,
127 + * the new task is not running, so nothing can be installed.
128 */
129 -int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm)
130 +int ldt_dup_context(struct mm_struct *old_mm, struct mm_struct *mm)
131 {
132 struct ldt_struct *new_ldt;
133 - struct mm_struct *old_mm;
134 int retval = 0;
135
136 - init_rwsem(&mm->context.ldt_usr_sem);
137 -
138 - old_mm = current->mm;
139 - if (!old_mm) {
140 - mm->context.ldt = NULL;
141 + if (!old_mm)
142 return 0;
143 - }
144
145 mutex_lock(&old_mm->context.lock);
146 - if (!old_mm->context.ldt) {
147 - mm->context.ldt = NULL;
148 + if (!old_mm->context.ldt)
149 goto out_unlock;
150 - }
151
152 new_ldt = alloc_ldt_struct(old_mm->context.ldt->nr_entries);
153 if (!new_ldt) {
154 diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
155 index 8e290c9b2c3f..783e1a754b78 100644
156 --- a/tools/testing/selftests/x86/ldt_gdt.c
157 +++ b/tools/testing/selftests/x86/ldt_gdt.c
158 @@ -626,13 +626,10 @@ static void do_multicpu_tests(void)
159 static int finish_exec_test(void)
160 {
161 /*
162 - * In a sensible world, this would be check_invalid_segment(0, 1);
163 - * For better or for worse, though, the LDT is inherited across exec.
164 - * We can probably change this safely, but for now we test it.
165 + * Older kernel versions did inherit the LDT on exec() which is
166 + * wrong because exec() starts from a clean state.
167 */
168 - check_valid_segment(0, 1,
169 - AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB,
170 - 42, true);
171 + check_invalid_segment(0, 1);
172
173 return nerrs ? 1 : 0;
174 }
175 --
176 2.14.2
177