lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-Id: <20171227164614.719631597@linuxfoundation.org> Date: Wed, 27 Dec 2017 17:45:48 +0100 From: Greg Kroah-Hartman <gregkh@...uxfoundation.org> To: linux-kernel@...r.kernel.org Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>, stable@...r.kernel.org, "Peter Zijlstra (Intel)" <peterz@...radead.org>, Thomas Gleixner <tglx@...utronix.de>, Andy Lutomirski <luto@...nel.org>, Boris Ostrovsky <boris.ostrovsky@...cle.com>, Borislav Petkov <bp@...en8.de>, Borislav Petkov <bpetkov@...e.de>, Brian Gerst <brgerst@...il.com>, Dave Hansen <dave.hansen@...el.com>, Dave Hansen <dave.hansen@...ux.intel.com>, David Laight <David.Laight@...lab.com>, Denys Vlasenko <dvlasenk@...hat.com>, Eduardo Valentin <eduval@...zon.com>, "H. Peter Anvin" <hpa@...or.com>, Josh Poimboeuf <jpoimboe@...hat.com>, Juergen Gross <jgross@...e.com>, Linus Torvalds <torvalds@...ux-foundation.org>, Will Deacon <will.deacon@....com>, aliguori@...zon.com, dan.j.williams@...el.com, hughd@...gle.com, keescook@...gle.com, kirill.shutemov@...ux.intel.com, linux-mm@...ck.org, Ingo Molnar <mingo@...nel.org> Subject: [PATCH 4.14 15/74] x86/ldt: Rework locking 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Peter Zijlstra <peterz@...radead.org> commit c2b3496bb30bd159e9de42e5c952e1f1f33c9a77 upstream. The LDT is duplicated on fork() and on exec(), which is wrong as exec() should start from a clean state, i.e. without LDT. To fix this the LDT duplication code will be moved into arch_dup_mmap() which is only called for fork(). This introduces a locking problem. arch_dup_mmap() holds mmap_sem of the parent process, but the LDT duplication code needs to acquire mm->context.lock to access the LDT data safely, which is the reverse lock order of write_ldt() where mmap_sem nests into context.lock. Solve this by introducing a new rw semaphore which serializes the read/write_ldt() syscall operations and use context.lock to protect the actual installment of the LDT descriptor. So context.lock stabilizes mm->context.ldt and can nest inside of the new semaphore or mmap_sem. Signed-off-by: Peter Zijlstra (Intel) <peterz@...radead.org> Signed-off-by: Thomas Gleixner <tglx@...utronix.de> Cc: Andy Lutomirski <luto@...nel.org> Cc: Andy Lutomirsky <luto@...nel.org> Cc: Boris Ostrovsky <boris.ostrovsky@...cle.com> Cc: Borislav Petkov <bp@...en8.de> Cc: Borislav Petkov <bpetkov@...e.de> Cc: Brian Gerst <brgerst@...il.com> Cc: Dave Hansen <dave.hansen@...el.com> Cc: Dave Hansen <dave.hansen@...ux.intel.com> Cc: David Laight <David.Laight@...lab.com> Cc: Denys Vlasenko <dvlasenk@...hat.com> Cc: Eduardo Valentin <eduval@...zon.com> Cc: Greg KH <gregkh@...uxfoundation.org> Cc: H. Peter Anvin <hpa@...or.com> Cc: Josh Poimboeuf <jpoimboe@...hat.com> Cc: Juergen Gross <jgross@...e.com> Cc: Linus Torvalds <torvalds@...ux-foundation.org> Cc: Peter Zijlstra <peterz@...radead.org> Cc: Will Deacon <will.deacon@....com> Cc: aliguori@...zon.com Cc: dan.j.williams@...el.com Cc: hughd@...gle.com Cc: keescook@...gle.com Cc: kirill.shutemov@...ux.intel.com Cc: linux-mm@...ck.org Signed-off-by: Ingo Molnar <mingo@...nel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org> --- arch/x86/include/asm/mmu.h | 4 +++- arch/x86/include/asm/mmu_context.h | 2 ++ arch/x86/kernel/ldt.c | 33 +++++++++++++++++++++------------ 3 files changed, 26 insertions(+), 13 deletions(-) --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -3,6 +3,7 @@ #define _ASM_X86_MMU_H #include <linux/spinlock.h> +#include <linux/rwsem.h> #include <linux/mutex.h> #include <linux/atomic.h> @@ -27,7 +28,8 @@ typedef struct { atomic64_t tlb_gen; #ifdef CONFIG_MODIFY_LDT_SYSCALL - struct ldt_struct *ldt; + struct rw_semaphore ldt_usr_sem; + struct ldt_struct *ldt; #endif #ifdef CONFIG_X86_64 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -132,6 +132,8 @@ void enter_lazy_tlb(struct mm_struct *mm static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { + mutex_init(&mm->context.lock); + mm->context.ctx_id = atomic64_inc_return(&last_mm_ctx_id); atomic64_set(&mm->context.tlb_gen, 0); --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -5,6 +5,11 @@ * Copyright (C) 2002 Andi Kleen * * This handles calls from both 32bit and 64bit mode. + * + * Lock order: + * contex.ldt_usr_sem + * mmap_sem + * context.lock */ #include <linux/errno.h> @@ -42,7 +47,7 @@ static void refresh_ldt_segments(void) #endif } -/* context.lock is held for us, so we don't need any locking. */ +/* context.lock is held by the task which issued the smp function call */ static void flush_ldt(void *__mm) { struct mm_struct *mm = __mm; @@ -99,15 +104,17 @@ static void finalize_ldt_struct(struct l paravirt_alloc_ldt(ldt->entries, ldt->nr_entries); } -/* context.lock is held */ -static void install_ldt(struct mm_struct *current_mm, - struct ldt_struct *ldt) +static void install_ldt(struct mm_struct *mm, struct ldt_struct *ldt) { + mutex_lock(&mm->context.lock); + /* Synchronizes with READ_ONCE in load_mm_ldt. */ - smp_store_release(¤t_mm->context.ldt, ldt); + smp_store_release(&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); + /* Activate the LDT for all CPUs using currents mm. */ + on_each_cpu_mask(mm_cpumask(mm), flush_ldt, mm, true); + + mutex_unlock(&mm->context.lock); } static void free_ldt_struct(struct ldt_struct *ldt) @@ -133,7 +140,8 @@ int init_new_context_ldt(struct task_str struct mm_struct *old_mm; int retval = 0; - mutex_init(&mm->context.lock); + init_rwsem(&mm->context.ldt_usr_sem); + old_mm = current->mm; if (!old_mm) { mm->context.ldt = NULL; @@ -180,7 +188,7 @@ static int read_ldt(void __user *ptr, un unsigned long entries_size; int retval; - mutex_lock(&mm->context.lock); + down_read(&mm->context.ldt_usr_sem); if (!mm->context.ldt) { retval = 0; @@ -209,7 +217,7 @@ static int read_ldt(void __user *ptr, un retval = bytecount; out_unlock: - mutex_unlock(&mm->context.lock); + up_read(&mm->context.ldt_usr_sem); return retval; } @@ -269,7 +277,8 @@ static int write_ldt(void __user *ptr, u ldt.avl = 0; } - mutex_lock(&mm->context.lock); + if (down_write_killable(&mm->context.ldt_usr_sem)) + return -EINTR; old_ldt = mm->context.ldt; old_nr_entries = old_ldt ? old_ldt->nr_entries : 0; @@ -291,7 +300,7 @@ static int write_ldt(void __user *ptr, u error = 0; out_unlock: - mutex_unlock(&mm->context.lock); + up_write(&mm->context.ldt_usr_sem); out: return error; }
Powered by blists - more mailing lists