[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] x86/xpti: Hide almost all of .text and all .data/.rodata/.bss mappings



On 13/02/18 20:45, Andrew Cooper wrote:
> The current XPTI implementation isolates the directmap (and therefore a lot of
> guest data), but a large quantity of CPU0's state (including its stack)
> remains visible.
> 
> Furthermore, an attacker able to read .text is in a vastly superior position
> to normal when it comes to fingerprinting Xen for known vulnerabilities, or
> scanning for ROP/Spectre gadgets.
> 
> Collect together the entrypoints in .text.entry (currently 3x4k frames, but
> can almost certainly be slimmed down), and create a common mapping which is
> inserted into each per-cpu shadow.  The stubs are also inserted into this
> mapping by pointing at the in-use L2.  This allows stubs allocated later (SMP
> boot, or CPU hotplug) to work without further changes to the common mappings.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> ---
> CC: Jan Beulich <JBeulich@xxxxxxxx>
> CC: Wei Liu <wei.liu2@xxxxxxxxxx>
> CC: Juergen Gross <jgross@xxxxxxxx>
> 
> RFC, because I don't think the stubs handling is particularly sensible.
> 
> We allocate 4k of virtual address space per CPU, but squash loads of CPUs
> together onto a single MFN.  The stubs ought to be isolated as well (as they
> leak the virtual addresses of each stack), which can be done by allocating an
> MFN per CPU (and simplifies cpu_smpboot_alloc() somewhat).  At this point, we
> can't use a common set of mappings, and will have to clone the single stub and
> .entry.text into each PCPUs copy of the pagetables.
> 
> Also, my plan to cause .text.entry to straddle a 512TB boundary (and therefore
> avoid any further pagetable allocations) has come a little unstuck because of
> CONFIG_BIGMEM.  I'm still working out whether there is a sensible way to
> rearrange the virtual layout for this plan to work.
> ---
>  xen/arch/x86/smpboot.c             | 37 ++++++++++++++++++++++++++++++++-----
>  xen/arch/x86/x86_64/compat/entry.S |  2 ++
>  xen/arch/x86/x86_64/entry.S        |  4 +++-
>  xen/arch/x86/xen.lds.S             |  7 +++++++
>  4 files changed, 44 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
> index 2ebef03..2519141 100644
> --- a/xen/arch/x86/smpboot.c
> +++ b/xen/arch/x86/smpboot.c
> @@ -622,6 +622,9 @@ unsigned long alloc_stub_page(unsigned int cpu, unsigned 
> long *mfn)
>          unmap_domain_page(memset(__map_domain_page(pg), 0xcc, PAGE_SIZE));
>      }
>  
> +    /* Confirm that all stubs fit in a single L2 pagetable. */
> +    BUILD_BUG_ON(NR_CPUS * PAGE_SIZE > (1u << L2_PAGETABLE_SHIFT));

So we limit NR_CPUS to be max 512 now?

Maybe you should use STUB_BUF_SIZE instead of PAGE_SIZE?

BTW: Is there any reason we don't use a common stub page mapped to each
per-cpu stack area? The stack address can easily be obtained via %rip
relative addressing then (see my patch for the per-vcpu stacks:
https://lists.xen.org/archives/html/xen-devel/2018-02/msg00773.html )


Juergen

> +
>      stub_va = XEN_VIRT_END - (cpu + 1) * PAGE_SIZE;
>      if ( map_pages_to_xen(stub_va, mfn_x(page_to_mfn(pg)), 1,
>                            PAGE_HYPERVISOR_RX | MAP_SMALL_PAGES) )
> @@ -651,9 +654,6 @@ static int clone_mapping(const void *ptr, root_pgentry_t 
> *rpt)
>      l2_pgentry_t *pl2e;
>      l1_pgentry_t *pl1e;
>  
> -    if ( linear < DIRECTMAP_VIRT_START )
> -        return 0;
> -
>      flags = l3e_get_flags(*pl3e);
>      ASSERT(flags & _PAGE_PRESENT);
>      if ( flags & _PAGE_PSE )
> @@ -744,6 +744,9 @@ static __read_mostly int8_t opt_xpti = -1;
>  boolean_param("xpti", opt_xpti);
>  DEFINE_PER_CPU(root_pgentry_t *, root_pgt);
>  
> +static root_pgentry_t common_pgt;
> +extern char _stextentry[], _etextentry[];
> +
>  static int setup_cpu_root_pgt(unsigned int cpu)
>  {
>      root_pgentry_t *rpt;
> @@ -764,8 +767,32 @@ static int setup_cpu_root_pgt(unsigned int cpu)
>          idle_pg_table[root_table_offset(RO_MPT_VIRT_START)];
>      /* SH_LINEAR_PT inserted together with guest mappings. */
>      /* PERDOMAIN inserted during context switch. */
> -    rpt[root_table_offset(XEN_VIRT_START)] =
> -        idle_pg_table[root_table_offset(XEN_VIRT_START)];
> +
> +    /* One-time setup of common_pgt, which maps .text.entry and the stubs. */
> +    if ( unlikely(!root_get_intpte(common_pgt)) )
> +    {
> +        unsigned long stubs_linear = XEN_VIRT_END - 1;
> +        l3_pgentry_t *stubs_main, *stubs_shadow;
> +        char *ptr;
> +
> +        for ( rc = 0, ptr = _stextentry;
> +              !rc && ptr < _etextentry; ptr += PAGE_SIZE )
> +            rc = clone_mapping(ptr, rpt);
> +
> +        if ( rc )
> +            return rc;
> +
> +        stubs_main = 
> l4e_to_l3e(idle_pg_table[l4_table_offset(stubs_linear)]);
> +        stubs_shadow = l4e_to_l3e(rpt[l4_table_offset(stubs_linear)]);
> +
> +        /* Splice into the regular L2 mapping the stubs. */
> +        stubs_shadow[l3_table_offset(stubs_linear)] =
> +            stubs_main[l3_table_offset(stubs_linear)];
> +
> +        common_pgt = rpt[root_table_offset(XEN_VIRT_START)];
> +    }
> +
> +    rpt[root_table_offset(XEN_VIRT_START)] = common_pgt;
>  
>      /* Install direct map page table entries for stack, IDT, and TSS. */
>      for ( off = rc = 0; !rc && off < STACK_SIZE; off += PAGE_SIZE )
> diff --git a/xen/arch/x86/x86_64/compat/entry.S 
> b/xen/arch/x86/x86_64/compat/entry.S
> index 707c746..b001e79 100644
> --- a/xen/arch/x86/x86_64/compat/entry.S
> +++ b/xen/arch/x86/x86_64/compat/entry.S
> @@ -13,6 +13,8 @@
>  #include <public/xen.h>
>  #include <irq_vectors.h>
>  
> +        .section .text.entry, "ax", @progbits
> +
>  ENTRY(entry_int82)
>          ASM_CLAC
>          pushq $0
> diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
> index 58f652d..5c5310d 100644
> --- a/xen/arch/x86/x86_64/entry.S
> +++ b/xen/arch/x86/x86_64/entry.S
> @@ -14,6 +14,8 @@
>  #include <public/xen.h>
>  #include <irq_vectors.h>
>  
> +        .section .text.entry, "ax", @progbits
> +
>  /* %rbx: struct vcpu */
>  ENTRY(switch_to_kernel)
>          leaq  VCPU_trap_bounce(%rbx),%rdx
> @@ -854,7 +856,7 @@ GLOBAL(autogen_entrypoints)
>          .popsection
>          .endm
>  
> -        .text
> +        .previous
>  autogen_stubs: /* Automatically generated stubs. */
>  
>          vec = 0
> diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
> index 0952980..25c6cbc 100644
> --- a/xen/arch/x86/xen.lds.S
> +++ b/xen/arch/x86/xen.lds.S
> @@ -67,6 +67,13 @@ SECTIONS
>         *(.text)
>         *(.text.__x86_indirect_thunk_*)
>         *(.text.page_aligned)
> +
> +       . = ALIGN(PAGE_SIZE);
> +       _stextentry = .;
> +       *(.text.entry)
> +       . = ALIGN(PAGE_SIZE);
> +       _etextentry = .;
> +
>         *(.text.cold)
>         *(.text.unlikely)
>         *(.fixup)
> 


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.