Messages in this thread Patch in this message | | | From | Ingo Molnar <> | Subject | [PATCH 29/43] x86/mm/kaiser: Map dynamically-allocated LDTs | Date | Fri, 24 Nov 2017 18:23:57 +0100 |
| |
From: Dave Hansen <dave.hansen@linux.intel.com>
Normally, a process has a NULL mm->context.ldt. But, there is a syscall for a process to set a new one. If a process does that, the LDT be mapped into the user page tables, just like the default copy.
The original KAISER patch missed this case.
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: daniel.gruss@iaik.tugraz.at Cc: hughd@google.com Cc: keescook@google.com Cc: linux-mm@kvack.org Cc: luto@kernel.org Cc: michael.schwarz@iaik.tugraz.at Cc: moritz.lipp@iaik.tugraz.at Cc: richard.fellner@student.tugraz.at Link: https://lkml.kernel.org/r/20171123003455.275397F7@viggo.jf.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/kernel/ldt.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 1c1eae961340..d6ab1144fdbf 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -11,6 +11,7 @@ #include <linux/gfp.h> #include <linux/sched.h> #include <linux/string.h> +#include <linux/kaiser.h> #include <linux/mm.h> #include <linux/smp.h> #include <linux/syscalls.h> @@ -57,11 +58,21 @@ static void flush_ldt(void *__mm) refresh_ldt_segments(); } +static void __free_ldt_struct(struct ldt_struct *ldt) +{ + if (ldt->nr_entries * LDT_ENTRY_SIZE > PAGE_SIZE) + vfree_atomic(ldt->entries); + else + free_page((unsigned long)ldt->entries); + kfree(ldt); +} + /* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */ static struct ldt_struct *alloc_ldt_struct(unsigned int num_entries) { struct ldt_struct *new_ldt; unsigned int alloc_size; + int ret; if (num_entries > LDT_ENTRIES) return NULL; @@ -89,6 +100,12 @@ static struct ldt_struct *alloc_ldt_struct(unsigned int num_entries) return NULL; } + ret = kaiser_add_mapping((unsigned long)new_ldt->entries, alloc_size, + __PAGE_KERNEL | _PAGE_GLOBAL); + if (ret) { + __free_ldt_struct(new_ldt); + return NULL; + } new_ldt->nr_entries = num_entries; return new_ldt; } @@ -115,12 +132,10 @@ static void free_ldt_struct(struct ldt_struct *ldt) if (likely(!ldt)) return; + kaiser_remove_mapping((unsigned long)ldt->entries, + ldt->nr_entries * LDT_ENTRY_SIZE); paravirt_free_ldt(ldt->entries, ldt->nr_entries); - if (ldt->nr_entries * LDT_ENTRY_SIZE > PAGE_SIZE) - vfree_atomic(ldt->entries); - else - free_page((unsigned long)ldt->entries); - kfree(ldt); + __free_ldt_struct(ldt); } /* -- 2.14.1
| |