// SPDX-License-Identifier: GPL-2.0-only /* ----------------------------------------------------------------------- * * * Copyright 2014 Intel Corporation; author: H. Peter Anvin *
* ----------------------------------------------------------------------- */
/* * The IRET instruction, when returning to a 16-bit segment, only * restores the bottom 16 bits of the user space stack pointer. This * causes some 16-bit software to break, but it also leaks kernel state * to user space. * * This works around this by creating percpu "ministacks", each of which * is mapped 2^16 times 64K apart. When we detect that the return SS is * on the LDT, we copy the IRET frame to the ministack and use the * relevant alias to return to userspace. The ministacks are mapped * readonly, so if the IRET fault we promote #GP to #DF which is an IST * vector and thus has its own stack; we then do the fixup in the #DF * handler. * * This file sets up the ministacks and the related page tables. The * actual ministack invocation is in entry_64.S.
*/
/* * Note: we only need 6*8 = 48 bytes for the espfix stack, but round * it up to a cache line to avoid unnecessary sharing.
*/ #define ESPFIX_STACK_SIZE (8*8UL) #define ESPFIX_STACKS_PER_PAGE (PAGE_SIZE/ESPFIX_STACK_SIZE)
/* There is address space for how many espfix pages? */ #define ESPFIX_PAGE_SPACE (1UL << (P4D_SHIFT-PAGE_SHIFT-16))
#define ESPFIX_MAX_CPUS (ESPFIX_STACKS_PER_PAGE * ESPFIX_PAGE_SPACE) #if CONFIG_NR_CPUS > ESPFIX_MAX_CPUS # error "Need more virtual address space for the ESPFIX hack" #endif
#define PGALLOC_GFP (GFP_KERNEL | __GFP_ZERO)
/* This contains the *bottom* address of the espfix stack */
DEFINE_PER_CPU_READ_MOSTLY(unsignedlong, espfix_stack);
DEFINE_PER_CPU_READ_MOSTLY(unsignedlong, espfix_waddr);
/* Initialization mutex - should this be a spinlock? */ static DEFINE_MUTEX(espfix_init_mutex);
/* * This returns the bottom address of the espfix stack for a specific CPU. * The math allows for a non-power-of-two ESPFIX_STACK_SIZE, in which case * we have to account for some amount of padding at the end of each page.
*/ staticinlineunsignedlong espfix_base_addr(unsignedint cpu)
{ unsignedlong page, slot; unsignedlong addr;
pte_p = pte_offset_kernel(&pmd, addr);
stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0)); /* * __PAGE_KERNEL_* includes _PAGE_GLOBAL, which we want since * this is mapped to userspace.
*/
pte = __pte(__pa(stack_page) | ((__PAGE_KERNEL_RO | _PAGE_ENC) & ptemask)); for (n = 0; n < ESPFIX_PTE_CLONES; n++)
set_pte(&pte_p[n*PTE_STRIDE], pte);
/* Job is done for this CPU and any CPU which shares this page */
WRITE_ONCE(espfix_pages[page], stack_page);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.