forked from Minki/linux
69218e4799
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 <boris.ostrovsky@oracle.com> for testing and recommending changes for Xen support. Signed-off-by: Thomas Garnier <thgarnie@google.com> Cc: Alexander Potapenko <glider@google.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Borislav Petkov <bp@suse.de> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Kosina <jikos@kernel.org> Cc: Joerg Roedel <joro@8bytes.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: Kees Cook <keescook@chromium.org> Cc: Len Brown <len.brown@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Lorenzo Stoakes <lstoakes@gmail.com> Cc: Luis R . Rodriguez <mcgrof@kernel.org> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Michal Hocko <mhocko@suse.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Rafael J . Wysocki <rjw@rjwysocki.net> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Stanislaw Gruszka <sgruszka@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Vitaly Kuznetsov <vkuznets@redhat.com> Cc: kasan-dev@googlegroups.com Cc: kernel-hardening@lists.openwall.com Cc: kvm@vger.kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-efi@vger.kernel.org Cc: linux-mm@kvack.org Cc: linux-pm@vger.kernel.org Cc: xen-devel@lists.xenproject.org Cc: zijun_hu <zijun_hu@htc.com> Link: http://lkml.kernel.org/r/20170314170508.100882-2-thgarnie@google.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
170 lines
4.8 KiB
C
170 lines
4.8 KiB
C
/*
|
|
* fixmap.h: compile-time virtual memory allocation
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 1998 Ingo Molnar
|
|
*
|
|
* Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
|
|
* x86_32 and x86_64 integration by Gustavo F. Padovan, February 2009
|
|
*/
|
|
|
|
#ifndef _ASM_X86_FIXMAP_H
|
|
#define _ASM_X86_FIXMAP_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
#include <linux/kernel.h>
|
|
#include <asm/acpi.h>
|
|
#include <asm/apicdef.h>
|
|
#include <asm/page.h>
|
|
#ifdef CONFIG_X86_32
|
|
#include <linux/threads.h>
|
|
#include <asm/kmap_types.h>
|
|
#else
|
|
#include <uapi/asm/vsyscall.h>
|
|
#endif
|
|
|
|
/*
|
|
* We can't declare FIXADDR_TOP as variable for x86_64 because vsyscall
|
|
* uses fixmaps that relies on FIXADDR_TOP for proper address calculation.
|
|
* Because of this, FIXADDR_TOP x86 integration was left as later work.
|
|
*/
|
|
#ifdef CONFIG_X86_32
|
|
/* used by vmalloc.c, vsyscall.lds.S.
|
|
*
|
|
* Leave one empty page between vmalloc'ed areas and
|
|
* the start of the fixmap.
|
|
*/
|
|
extern unsigned long __FIXADDR_TOP;
|
|
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
|
|
#else
|
|
#define FIXADDR_TOP (round_up(VSYSCALL_ADDR + PAGE_SIZE, 1<<PMD_SHIFT) - \
|
|
PAGE_SIZE)
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Here we define all the compile-time 'special' virtual
|
|
* addresses. The point is to have a constant address at
|
|
* compile time, but to set the physical address only
|
|
* in the boot process.
|
|
* for x86_32: We allocate these special addresses
|
|
* from the end of virtual memory (0xfffff000) backwards.
|
|
* Also this lets us do fail-safe vmalloc(), we
|
|
* can guarantee that these special addresses and
|
|
* vmalloc()-ed addresses never overlap.
|
|
*
|
|
* These 'compile-time allocated' memory buffers are
|
|
* fixed-size 4k pages (or larger if used with an increment
|
|
* higher than 1). Use set_fixmap(idx,phys) to associate
|
|
* physical memory with fixmap indices.
|
|
*
|
|
* TLB entries of such buffers will not be flushed across
|
|
* task switches.
|
|
*/
|
|
enum fixed_addresses {
|
|
#ifdef CONFIG_X86_32
|
|
FIX_HOLE,
|
|
#else
|
|
#ifdef CONFIG_X86_VSYSCALL_EMULATION
|
|
VSYSCALL_PAGE = (FIXADDR_TOP - VSYSCALL_ADDR) >> PAGE_SHIFT,
|
|
#endif
|
|
#endif
|
|
FIX_DBGP_BASE,
|
|
FIX_EARLYCON_MEM_BASE,
|
|
#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
|
|
FIX_OHCI1394_BASE,
|
|
#endif
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
|
|
#endif
|
|
#ifdef CONFIG_X86_IO_APIC
|
|
FIX_IO_APIC_BASE_0,
|
|
FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
|
|
#endif
|
|
FIX_RO_IDT, /* Virtual mapping for read-only IDT */
|
|
#ifdef CONFIG_X86_32
|
|
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
|
|
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
|
|
#ifdef CONFIG_PCI_MMCONFIG
|
|
FIX_PCIE_MCFG,
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_PARAVIRT
|
|
FIX_PARAVIRT_BOOTMAP,
|
|
#endif
|
|
FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */
|
|
FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
|
|
#ifdef CONFIG_X86_INTEL_MID
|
|
FIX_LNW_VRTC,
|
|
#endif
|
|
/* Fixmap entries to remap the GDTs, one per processor. */
|
|
FIX_GDT_REMAP_BEGIN,
|
|
FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1,
|
|
|
|
__end_of_permanent_fixed_addresses,
|
|
|
|
/*
|
|
* 512 temporary boot-time mappings, used by early_ioremap(),
|
|
* before ioremap() is functional.
|
|
*
|
|
* If necessary we round it up to the next 512 pages boundary so
|
|
* that we can have a single pgd entry and a single pte table:
|
|
*/
|
|
#define NR_FIX_BTMAPS 64
|
|
#define FIX_BTMAPS_SLOTS 8
|
|
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
|
|
FIX_BTMAP_END =
|
|
(__end_of_permanent_fixed_addresses ^
|
|
(__end_of_permanent_fixed_addresses + TOTAL_FIX_BTMAPS - 1)) &
|
|
-PTRS_PER_PTE
|
|
? __end_of_permanent_fixed_addresses + TOTAL_FIX_BTMAPS -
|
|
(__end_of_permanent_fixed_addresses & (TOTAL_FIX_BTMAPS - 1))
|
|
: __end_of_permanent_fixed_addresses,
|
|
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
|
|
#ifdef CONFIG_X86_32
|
|
FIX_WP_TEST,
|
|
#endif
|
|
#ifdef CONFIG_INTEL_TXT
|
|
FIX_TBOOT_BASE,
|
|
#endif
|
|
__end_of_fixed_addresses
|
|
};
|
|
|
|
|
|
extern void reserve_top_address(unsigned long reserve);
|
|
|
|
#define FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
|
|
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
|
|
|
|
extern int fixmaps_set;
|
|
|
|
extern pte_t *kmap_pte;
|
|
#define kmap_prot PAGE_KERNEL
|
|
extern pte_t *pkmap_page_table;
|
|
|
|
void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
|
|
void native_set_fixmap(enum fixed_addresses idx,
|
|
phys_addr_t phys, pgprot_t flags);
|
|
|
|
#ifndef CONFIG_PARAVIRT
|
|
static inline void __set_fixmap(enum fixed_addresses idx,
|
|
phys_addr_t phys, pgprot_t flags)
|
|
{
|
|
native_set_fixmap(idx, phys, flags);
|
|
}
|
|
#endif
|
|
|
|
#include <asm-generic/fixmap.h>
|
|
|
|
#define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
|
|
#define __late_clear_fixmap(idx) __set_fixmap(idx, 0, __pgprot(0))
|
|
|
|
void __early_set_fixmap(enum fixed_addresses idx,
|
|
phys_addr_t phys, pgprot_t flags);
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
#endif /* _ASM_X86_FIXMAP_H */
|