* valid on every instruction boundary. (Note: these are all
* semantically ACCESS_ONCE() due to tss's volatile qualifier.)
*
- * rsp0 refers to the primary stack. #MC, #DF, NMI and #DB handlers
+ * rsp0 refers to the primary stack. #MC, NMI, #DB and #DF handlers
* each get their own stacks. No IO Bitmap.
*/
tss->rsp0 = stack_bottom;
- tss->ist[IST_MCE - 1] = stack_top + IST_MCE * PAGE_SIZE;
- tss->ist[IST_DF - 1] = stack_top + IST_DF * PAGE_SIZE;
- tss->ist[IST_NMI - 1] = stack_top + IST_NMI * PAGE_SIZE;
- tss->ist[IST_DB - 1] = stack_top + IST_DB * PAGE_SIZE;
+ tss->ist[IST_MCE - 1] = stack_top + (1 + IST_MCE) * PAGE_SIZE;
+ tss->ist[IST_NMI - 1] = stack_top + (1 + IST_NMI) * PAGE_SIZE;
+ tss->ist[IST_DB - 1] = stack_top + (1 + IST_DB) * PAGE_SIZE;
+ tss->ist[IST_DF - 1] = stack_top + (1 + IST_DF) * PAGE_SIZE;
tss->bitmap = IOBMP_INVALID_OFFSET;
/* All other stack pointers poisioned. */
void memguard_guard_stack(void *p)
{
- /* IST_MAX IST pages + at least 1 guard page + primary stack. */
- BUILD_BUG_ON((IST_MAX + 1) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE);
+ map_pages_to_xen((unsigned long)p, virt_to_mfn(p), 1, _PAGE_NONE);
- memguard_guard_range(p + IST_MAX * PAGE_SIZE,
- STACK_SIZE - PRIMARY_STACK_SIZE - IST_MAX * PAGE_SIZE);
+ p += PRIMARY_SHSTK_SLOT * PAGE_SIZE;
+ map_pages_to_xen((unsigned long)p, virt_to_mfn(p), 1, _PAGE_NONE);
}
void memguard_unguard_stack(void *p)
{
- memguard_unguard_range(p + IST_MAX * PAGE_SIZE,
- STACK_SIZE - PRIMARY_STACK_SIZE - IST_MAX * PAGE_SIZE);
-}
-
-bool memguard_is_stack_guard_page(unsigned long addr)
-{
- addr &= STACK_SIZE - 1;
+ map_pages_to_xen((unsigned long)p, virt_to_mfn(p), 1, PAGE_HYPERVISOR_RW);
- return addr >= IST_MAX * PAGE_SIZE &&
- addr < STACK_SIZE - PRIMARY_STACK_SIZE;
+ p += PRIMARY_SHSTK_SLOT * PAGE_SIZE;
+ map_pages_to_xen((unsigned long)p, virt_to_mfn(p), 1, PAGE_HYPERVISOR_RW);
}
void arch_dump_shared_mem_info(void)
/* Install direct map page table entries for stack, IDT, and TSS. */
for ( off = rc = 0; !rc && off < STACK_SIZE; off += PAGE_SIZE )
- if ( !memguard_is_stack_guard_page(off) )
- rc = clone_mapping(__va(__pa(stack_base[cpu])) + off, rpt);
+ rc = clone_mapping(__va(__pa(stack_base[cpu])) + off, rpt);
if ( !rc )
rc = clone_mapping(idt_tables[cpu], rpt);
/*
* Notes for get_stack_trace_bottom() and get_stack_dump_bottom()
*
- * Stack pages 0 - 3:
+ * Stack pages 1 - 4:
* These are all 1-page IST stacks. Each of these stacks have an exception
* frame and saved register state at the top. The interesting bound for a
* trace is the word adjacent to this, while the bound for a dump is the
* very top, including the exception frame.
*
- * Stack pages 4 and 5:
- * None of these are particularly interesting. With MEMORY_GUARD, page 5 is
- * explicitly not present, so attempting to dump or trace it is
- * counterproductive. Without MEMORY_GUARD, it is possible for a call chain
- * to use the entire primary stack and wander into page 5. In this case,
- * consider these pages an extension of the primary stack to aid debugging
- * hopefully rare situations where the primary stack has effective been
- * overflown.
+ * Stack pages 0 and 5:
+ * Shadow stacks. These are mapped read-only, and used by CET-SS capable
+ * processors. They will never contain regular stack data.
*
* Stack pages 6 and 7:
* These form the primary stack, and have a cpu_info at the top. For a
{
switch ( get_stack_page(sp) )
{
- case 0 ... 3:
+ case 1 ... 4:
return ROUNDUP(sp, PAGE_SIZE) -
offsetof(struct cpu_user_regs, es) - sizeof(unsigned long);
-#ifndef MEMORY_GUARD
- case 4 ... 5:
-#endif
case 6 ... 7:
return ROUNDUP(sp, STACK_SIZE) -
sizeof(struct cpu_info) - sizeof(unsigned long);
{
switch ( get_stack_page(sp) )
{
- case 0 ... 3:
+ case 1 ... 4:
return ROUNDUP(sp, PAGE_SIZE) - sizeof(unsigned long);
-#ifndef MEMORY_GUARD
- case 4 ... 5:
-#endif
case 6 ... 7:
return ROUNDUP(sp, STACK_SIZE) - sizeof(unsigned long);
/* Primary stack is restricted to 8kB by guard pages. */
#define PRIMARY_STACK_SIZE 8192
+/* Primary shadow stack is slot 5 of 8, immediately under the primary stack. */
+#define PRIMARY_SHSTK_SLOT 5
+
/* Total size of syscall and emulation stubs. */
#define STUB_BUF_SHIFT (L1_CACHE_SHIFT > 7 ? L1_CACHE_SHIFT : 7)
#define STUB_BUF_SIZE (1 << STUB_BUF_SHIFT)
*
* 7 - Primary stack (with a struct cpu_info at the top)
* 6 - Primary stack
- * 5 - Optionally not present (MEMORY_GUARD)
- * 4 - Unused; optionally not present (MEMORY_GUARD)
- * 3 - Unused; optionally not present (MEMORY_GUARD)
- * 2 - MCE IST stack
- * 1 - NMI IST stack
- * 0 - Double Fault IST stack
+ * 5 - Primay Shadow Stack (read-only)
+ * 4 - #DF IST stack
+ * 3 - #DB IST stack
+ * 2 - NMI IST stack
+ * 1 - #MC IST stack
+ * 0 - IST Shadow Stacks (4x 1k, read-only)
*/
/*
void memguard_guard_stack(void *p);
void memguard_unguard_stack(void *p);
-bool __attribute_const__ memguard_is_stack_guard_page(unsigned long addr);
struct mmio_ro_emulate_ctxt {
unsigned long cr2;
DECLARE_PER_CPU(struct tss_page, tss_page);
#define IST_NONE 0UL
-#define IST_DF 1UL
+#define IST_MCE 1UL
#define IST_NMI 2UL
-#define IST_MCE 3UL
-#define IST_DB 4UL
+#define IST_DB 3UL
+#define IST_DF 4UL
#define IST_MAX 4UL
/* Set the Interrupt Stack Table used by a particular IDT entry. */