[tip:x86/mm] x86: Remap GDT tables in the fixmap section

2017-03-16 Thread tip-bot for Thomas Garnier
Commit-ID:  69218e47994da614e7af600bf06887750ab6657a
Gitweb: http://git.kernel.org/tip/69218e47994da614e7af600bf06887750ab6657a
Author: Thomas Garnier 
AuthorDate: Tue, 14 Mar 2017 10:05:07 -0700
Committer:  Ingo Molnar 
CommitDate: Thu, 16 Mar 2017 09:06:35 +0100

x86: Remap GDT tables in the fixmap section

Each processor holds a GDT in its per-cpu structure. The sgdt
instruction gives the base address of the current GDT. This address can
be used to bypass KASLR memory randomization. With another bug, an
attacker could target other per-cpu structures or deduce the base of
the main memory section (PAGE_OFFSET).

This patch relocates the GDT table for each processor inside the
fixmap section. The space is reserved based on number of supported
processors.

For consistency, the remapping is done by default on 32 and 64-bit.

Each processor switches to its remapped GDT at the end of
initialization. For hibernation, the main processor returns with the
original GDT and switches back to the remapping at completion.

This patch was tested on both architectures. Hibernation and KVM were
both tested specially for their usage of the GDT.

Thanks to Boris Ostrovsky  for testing and
recommending changes for Xen support.

Signed-off-by: Thomas Garnier 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Andrey Ryabinin 
Cc: Andy Lutomirski 
Cc: Ard Biesheuvel 
Cc: Boris Ostrovsky 
Cc: Borislav Petkov 
Cc: Chris Wilson 
Cc: Christian Borntraeger 
Cc: Dmitry Vyukov 
Cc: Frederic Weisbecker 
Cc: Jiri Kosina 
Cc: Joerg Roedel 
Cc: Jonathan Corbet 
Cc: Josh Poimboeuf 
Cc: Juergen Gross 
Cc: Kees Cook 
Cc: Len Brown 
Cc: Linus Torvalds 
Cc: Lorenzo Stoakes 
Cc: Luis R . Rodriguez 
Cc: Matt Fleming 
Cc: Michal Hocko 
Cc: Paolo Bonzini 
Cc: Paul Gortmaker 
Cc: Pavel Machek 
Cc: Peter Zijlstra 
Cc: Radim Krčmář 
Cc: Rafael J . Wysocki 
Cc: Rusty Russell 
Cc: Stanislaw Gruszka 
Cc: Thomas Gleixner 
Cc: Tim Chen 
Cc: Vitaly Kuznetsov 
Cc: kasan-...@googlegroups.com
Cc: kernel-harden...@lists.openwall.com
Cc: k...@vger.kernel.org
Cc: lgu...@lists.ozlabs.org
Cc: linux-...@vger.kernel.org
Cc: linux-...@vger.kernel.org
Cc: linux...@kvack.org
Cc: linux...@vger.kernel.org
Cc: xen-de...@lists.xenproject.org
Cc: zijun_hu 
Link: http://lkml.kernel.org/r/20170314170508.100882-2-thgar...@google.com
Signed-off-by: Ingo Molnar 
---
 arch/x86/entry/vdso/vma.c |  2 +-
 arch/x86/include/asm/desc.h   | 58 ---
 arch/x86/include/asm/fixmap.h |  4 +++
 arch/x86/include/asm/processor.h  |  1 +
 arch/x86/include/asm/stackprotector.h |  2 +-
 arch/x86/kernel/acpi/sleep.c  |  2 +-
 arch/x86/kernel/apm_32.c  |  6 ++--
 arch/x86/kernel/cpu/common.c  | 29 --
 arch/x86/kernel/setup_percpu.c|  2 +-
 arch/x86/kernel/smpboot.c |  2 +-
 arch/x86/platform/efi/efi_32.c|  4 +--
 arch/x86/power/cpu.c  |  7 +++--
 arch/x86/xen/enlighten.c  |  5 ++-
 arch/x86/xen/mmu.c|  1 +
 arch/x86/xen/smp.c|  2 +-
 drivers/lguest/x86/core.c |  6 ++--
 drivers/pnp/pnpbios/bioscalls.c   | 10 +++---
 17 files changed, 114 insertions(+), 29 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 226ca70..5c5d4d7 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -354,7 +354,7 @@ static void vgetcpu_cpu_init(void *arg)
d.p = 1;/* Present */
d.d = 1;/* 32-bit */
 
-   write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, , 
DESCTYPE_S);
+   write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_PER_CPU, , DESCTYPE_S);
 }
 
 static int vgetcpu_online(unsigned int cpu)
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index 1548ca9..4b5ef0c 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -38,6 +39,7 @@ extern struct desc_ptr idt_descr;
 extern gate_desc idt_table[];
 extern const struct 

[tip:x86/mm] x86: Remap GDT tables in the fixmap section

2017-03-16 Thread tip-bot for Thomas Garnier
Commit-ID:  69218e47994da614e7af600bf06887750ab6657a
Gitweb: http://git.kernel.org/tip/69218e47994da614e7af600bf06887750ab6657a
Author: Thomas Garnier 
AuthorDate: Tue, 14 Mar 2017 10:05:07 -0700
Committer:  Ingo Molnar 
CommitDate: Thu, 16 Mar 2017 09:06:35 +0100

x86: Remap GDT tables in the fixmap section

Each processor holds a GDT in its per-cpu structure. The sgdt
instruction gives the base address of the current GDT. This address can
be used to bypass KASLR memory randomization. With another bug, an
attacker could target other per-cpu structures or deduce the base of
the main memory section (PAGE_OFFSET).

This patch relocates the GDT table for each processor inside the
fixmap section. The space is reserved based on number of supported
processors.

For consistency, the remapping is done by default on 32 and 64-bit.

Each processor switches to its remapped GDT at the end of
initialization. For hibernation, the main processor returns with the
original GDT and switches back to the remapping at completion.

This patch was tested on both architectures. Hibernation and KVM were
both tested specially for their usage of the GDT.

Thanks to Boris Ostrovsky  for testing and
recommending changes for Xen support.

Signed-off-by: Thomas Garnier 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Andrey Ryabinin 
Cc: Andy Lutomirski 
Cc: Ard Biesheuvel 
Cc: Boris Ostrovsky 
Cc: Borislav Petkov 
Cc: Chris Wilson 
Cc: Christian Borntraeger 
Cc: Dmitry Vyukov 
Cc: Frederic Weisbecker 
Cc: Jiri Kosina 
Cc: Joerg Roedel 
Cc: Jonathan Corbet 
Cc: Josh Poimboeuf 
Cc: Juergen Gross 
Cc: Kees Cook 
Cc: Len Brown 
Cc: Linus Torvalds 
Cc: Lorenzo Stoakes 
Cc: Luis R . Rodriguez 
Cc: Matt Fleming 
Cc: Michal Hocko 
Cc: Paolo Bonzini 
Cc: Paul Gortmaker 
Cc: Pavel Machek 
Cc: Peter Zijlstra 
Cc: Radim Krčmář 
Cc: Rafael J . Wysocki 
Cc: Rusty Russell 
Cc: Stanislaw Gruszka 
Cc: Thomas Gleixner 
Cc: Tim Chen 
Cc: Vitaly Kuznetsov 
Cc: kasan-...@googlegroups.com
Cc: kernel-harden...@lists.openwall.com
Cc: k...@vger.kernel.org
Cc: lgu...@lists.ozlabs.org
Cc: linux-...@vger.kernel.org
Cc: linux-...@vger.kernel.org
Cc: linux...@kvack.org
Cc: linux...@vger.kernel.org
Cc: xen-de...@lists.xenproject.org
Cc: zijun_hu 
Link: http://lkml.kernel.org/r/20170314170508.100882-2-thgar...@google.com
Signed-off-by: Ingo Molnar 
---
 arch/x86/entry/vdso/vma.c |  2 +-
 arch/x86/include/asm/desc.h   | 58 ---
 arch/x86/include/asm/fixmap.h |  4 +++
 arch/x86/include/asm/processor.h  |  1 +
 arch/x86/include/asm/stackprotector.h |  2 +-
 arch/x86/kernel/acpi/sleep.c  |  2 +-
 arch/x86/kernel/apm_32.c  |  6 ++--
 arch/x86/kernel/cpu/common.c  | 29 --
 arch/x86/kernel/setup_percpu.c|  2 +-
 arch/x86/kernel/smpboot.c |  2 +-
 arch/x86/platform/efi/efi_32.c|  4 +--
 arch/x86/power/cpu.c  |  7 +++--
 arch/x86/xen/enlighten.c  |  5 ++-
 arch/x86/xen/mmu.c|  1 +
 arch/x86/xen/smp.c|  2 +-
 drivers/lguest/x86/core.c |  6 ++--
 drivers/pnp/pnpbios/bioscalls.c   | 10 +++---
 17 files changed, 114 insertions(+), 29 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 226ca70..5c5d4d7 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -354,7 +354,7 @@ static void vgetcpu_cpu_init(void *arg)
d.p = 1;/* Present */
d.d = 1;/* 32-bit */
 
-   write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, , 
DESCTYPE_S);
+   write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_PER_CPU, , DESCTYPE_S);
 }
 
 static int vgetcpu_online(unsigned int cpu)
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index 1548ca9..4b5ef0c 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -38,6 +39,7 @@ extern struct desc_ptr idt_descr;
 extern gate_desc idt_table[];
 extern const struct desc_ptr debug_idt_descr;
 extern gate_desc debug_idt_table[];
+extern pgprot_t pg_fixmap_gdt_flags;
 
 struct gdt_page {
struct desc_struct gdt[GDT_ENTRIES];
@@ -45,11 +47,57 @@ struct gdt_page {
 
 DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
 
-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+/* Provide the original GDT */
+static inline struct desc_struct *get_cpu_gdt_rw(unsigned int cpu)
 {
return per_cpu(gdt_page, cpu).gdt;
 }
 
+static inline unsigned long get_cpu_gdt_rw_vaddr(unsigned int cpu)
+{
+   return (unsigned long)get_cpu_gdt_rw(cpu);
+}
+
+/* Provide the current original GDT */
+static inline struct desc_struct *get_current_gdt_rw(void)
+{
+   return this_cpu_ptr(_page)->gdt;
+}
+
+static inline unsigned long get_current_gdt_rw_vaddr(void)
+{
+   return (unsigned