Re: Patch "x86-64, espfix: Don't leak bits 31:16 of %esp returning to 16-bit stack" has been added to the 3.4-stable tree

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

 



On Fri, Jul 18, 2014 at 02:59:02PM -0700, Andrew Lutomirski wrote:
> Still not ready :(


This should now be resolved with commit
7209a75d2009dbf7745e2fd354abf25c3deb3ca3 (x86_64/entry/xen: Do not
invoke espfix64 on Xen), right?

thanks,

greg k-h

> 
> On Fri, Jul 18, 2014 at 2:55 PM,  <gregkh@xxxxxxxxxxxxxxxxxxx> wrote:
> >
> > This is a note to let you know that I've just added the patch titled
> >
> >     x86-64, espfix: Don't leak bits 31:16 of %esp returning to 16-bit stack
> >
> > to the 3.4-stable tree which can be found at:
> >     http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
> >
> > The filename of the patch is:
> >      x86-64-espfix-don-t-leak-bits-31-16-of-esp-returning-to-16-bit-stack.patch
> > and it can be found in the queue-3.4 subdirectory.
> >
> > If you, or anyone else, feels it should not be added to the stable tree,
> > please let <stable@xxxxxxxxxxxxxxx> know about it.
> >
> >
> > From 3891a04aafd668686239349ea58f3314ea2af86b Mon Sep 17 00:00:00 2001
> > From: "H. Peter Anvin" <hpa@xxxxxxxxxxxxxxx>
> > Date: Tue, 29 Apr 2014 16:46:09 -0700
> > Subject: x86-64, espfix: Don't leak bits 31:16 of %esp returning to 16-bit stack
> >
> > From: "H. Peter Anvin" <hpa@xxxxxxxxxxxxxxx>
> >
> > commit 3891a04aafd668686239349ea58f3314ea2af86b upstream.
> >
> > 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.  We have a software workaround for that ("espfix") for
> > the 32-bit kernel, but it relies on a nonzero stack segment base which
> > is not available in 64-bit mode.
> >
> > In checkin:
> >
> >     b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels
> >
> > we "solved" this by forbidding 16-bit segments on 64-bit kernels, with
> > the logic that 16-bit support is crippled on 64-bit kernels anyway (no
> > V86 support), but it turns out that people are doing stuff like
> > running old Win16 binaries under Wine and expect it to work.
> >
> > 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 IRET faults 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.
> >
> > (Making #GP an IST exception would make the msr_safe functions unsafe
> > in NMI/MC context, and quite possibly have other effects.)
> >
> > Special thanks to:
> >
> > - Andy Lutomirski, for the suggestion of using very small stack slots
> >   and copy (as opposed to map) the IRET frame there, and for the
> >   suggestion to mark them readonly and let the fault promote to #DF.
> > - Konrad Wilk for paravirt fixup and testing.
> > - Borislav Petkov for testing help and useful comments.
> >
> > Reported-by: Brian Gerst <brgerst@xxxxxxxxx>
> > Signed-off-by: H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>
> > Link: http://lkml.kernel.org/r/1398816946-3351-1-git-send-email-hpa@xxxxxxxxxxxxxxx
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
> > Cc: Borislav Petkov <bp@xxxxxxxxx>
> > Cc: Andrew Lutomriski <amluto@xxxxxxxxx>
> > Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
> > Cc: Dirk Hohndel <dirk@xxxxxxxxxxx>
> > Cc: Arjan van de Ven <arjan.van.de.ven@xxxxxxxxx>
> > Cc: comex <comexk@xxxxxxxxx>
> > Cc: Alexander van Heukelum <heukelum@xxxxxxxxxxx>
> > Cc: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
> > Cc: <stable@xxxxxxxxxxxxxxx> # consider after upstream merge
> > Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> >
> > ---
> >  Documentation/x86/x86_64/mm.txt         |    2
> >  arch/x86/include/asm/pgtable_64_types.h |    2
> >  arch/x86/include/asm/setup.h            |    3
> >  arch/x86/kernel/Makefile                |    1
> >  arch/x86/kernel/entry_64.S              |   73 ++++++++++-
> >  arch/x86/kernel/espfix_64.c             |  208 ++++++++++++++++++++++++++++++++
> >  arch/x86/kernel/ldt.c                   |   11 -
> >  arch/x86/kernel/smpboot.c               |    7 +
> >  arch/x86/mm/dump_pagetables.c           |   31 +++-
> >  init/main.c                             |    4
> >  10 files changed, 316 insertions(+), 26 deletions(-)
> >
> > --- a/Documentation/x86/x86_64/mm.txt
> > +++ b/Documentation/x86/x86_64/mm.txt
> > @@ -12,6 +12,8 @@ ffffc90000000000 - ffffe8ffffffffff (=45
> >  ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
> >  ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
> >  ... unused hole ...
> > +ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks
> > +... unused hole ...
> >  ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
> >  ffffffffa0000000 - fffffffffff00000 (=1536 MB) module mapping space
> >
> > --- a/arch/x86/include/asm/pgtable_64_types.h
> > +++ b/arch/x86/include/asm/pgtable_64_types.h
> > @@ -59,5 +59,7 @@ typedef struct { pteval_t pte; } pte_t;
> >  #define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
> >  #define MODULES_END      _AC(0xffffffffff000000, UL)
> >  #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
> > +#define ESPFIX_PGD_ENTRY _AC(-2, UL)
> > +#define ESPFIX_BASE_ADDR (ESPFIX_PGD_ENTRY << PGDIR_SHIFT)
> >
> >  #endif /* _ASM_X86_PGTABLE_64_DEFS_H */
> > --- a/arch/x86/include/asm/setup.h
> > +++ b/arch/x86/include/asm/setup.h
> > @@ -59,6 +59,9 @@ extern void x86_ce4100_early_setup(void)
> >  static inline void x86_ce4100_early_setup(void) { }
> >  #endif
> >
> > +extern void init_espfix_bsp(void);
> > +extern void init_espfix_ap(void);
> > +
> >  #ifndef _SETUP
> >
> >  /*
> > --- a/arch/x86/kernel/Makefile
> > +++ b/arch/x86/kernel/Makefile
> > @@ -28,6 +28,7 @@ obj-$(CONFIG_X86_64)  += sys_x86_64.o x86
> >  obj-y                  += syscall_$(BITS).o
> >  obj-$(CONFIG_X86_64)   += vsyscall_64.o
> >  obj-$(CONFIG_X86_64)   += vsyscall_emu_64.o
> > +obj-$(CONFIG_X86_64)   += espfix_64.o
> >  obj-y                  += bootflag.o e820.o
> >  obj-y                  += pci-dma.o quirks.o topology.o kdebugfs.o
> >  obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
> > --- a/arch/x86/kernel/entry_64.S
> > +++ b/arch/x86/kernel/entry_64.S
> > @@ -55,6 +55,7 @@
> >  #include <asm/paravirt.h>
> >  #include <asm/ftrace.h>
> >  #include <asm/percpu.h>
> > +#include <asm/pgtable_types.h>
> >  #include <linux/err.h>
> >
> >  /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
> > @@ -899,10 +900,18 @@ restore_args:
> >         RESTORE_ARGS 1,8,1
> >
> >  irq_return:
> > +       /*
> > +        * Are we returning to a stack segment from the LDT?  Note: in
> > +        * 64-bit mode SS:RSP on the exception stack is always valid.
> > +        */
> > +       testb $4,(SS-RIP)(%rsp)
> > +       jnz irq_return_ldt
> > +
> > +irq_return_iret:
> >         INTERRUPT_RETURN
> >
> >         .section __ex_table, "a"
> > -       .quad irq_return, bad_iret
> > +       .quad irq_return_iret, bad_iret
> >         .previous
> >
> >  #ifdef CONFIG_PARAVIRT
> > @@ -914,6 +923,30 @@ ENTRY(native_iret)
> >         .previous
> >  #endif
> >
> > +irq_return_ldt:
> > +       pushq_cfi %rax
> > +       pushq_cfi %rdi
> > +       SWAPGS
> > +       movq PER_CPU_VAR(espfix_waddr),%rdi
> > +       movq %rax,(0*8)(%rdi)   /* RAX */
> > +       movq (2*8)(%rsp),%rax   /* RIP */
> > +       movq %rax,(1*8)(%rdi)
> > +       movq (3*8)(%rsp),%rax   /* CS */
> > +       movq %rax,(2*8)(%rdi)
> > +       movq (4*8)(%rsp),%rax   /* RFLAGS */
> > +       movq %rax,(3*8)(%rdi)
> > +       movq (6*8)(%rsp),%rax   /* SS */
> > +       movq %rax,(5*8)(%rdi)
> > +       movq (5*8)(%rsp),%rax   /* RSP */
> > +       movq %rax,(4*8)(%rdi)
> > +       andl $0xffff0000,%eax
> > +       popq_cfi %rdi
> > +       orq PER_CPU_VAR(espfix_stack),%rax
> > +       SWAPGS
> > +       movq %rax,%rsp
> > +       popq_cfi %rax
> > +       jmp irq_return_iret
> > +
> >         .section .fixup,"ax"
> >  bad_iret:
> >         /*
> > @@ -977,9 +1010,41 @@ ENTRY(retint_kernel)
> >         call preempt_schedule_irq
> >         jmp exit_intr
> >  #endif
> > -
> >         CFI_ENDPROC
> >  END(common_interrupt)
> > +
> > +       /*
> > +        * If IRET takes a fault on the espfix stack, then we
> > +        * end up promoting it to a doublefault.  In that case,
> > +        * modify the stack to make it look like we just entered
> > +        * the #GP handler from user space, similar to bad_iret.
> > +        */
> > +       ALIGN
> > +__do_double_fault:
> > +       XCPT_FRAME 1 RDI+8
> > +       movq RSP(%rdi),%rax             /* Trap on the espfix stack? */
> > +       sarq $PGDIR_SHIFT,%rax
> > +       cmpl $ESPFIX_PGD_ENTRY,%eax
> > +       jne do_double_fault             /* No, just deliver the fault */
> > +       cmpl $__KERNEL_CS,CS(%rdi)
> > +       jne do_double_fault
> > +       movq RIP(%rdi),%rax
> > +       cmpq $irq_return_iret,%rax
> > +#ifdef CONFIG_PARAVIRT
> > +       je 1f
> > +       cmpq $native_iret,%rax
> > +#endif
> > +       jne do_double_fault             /* This shouldn't happen... */
> > +1:
> > +       movq PER_CPU_VAR(kernel_stack),%rax
> > +       subq $(6*8-KERNEL_STACK_OFFSET),%rax    /* Reset to original stack */
> > +       movq %rax,RSP(%rdi)
> > +       movq $0,(%rax)                  /* Missing (lost) #GP error code */
> > +       movq $general_protection,RIP(%rdi)
> > +       retq
> > +       CFI_ENDPROC
> > +END(__do_double_fault)
> > +
> >  /*
> >   * End of kprobes section
> >   */
> > @@ -1155,7 +1220,7 @@ zeroentry overflow do_overflow
> >  zeroentry bounds do_bounds
> >  zeroentry invalid_op do_invalid_op
> >  zeroentry device_not_available do_device_not_available
> > -paranoiderrorentry double_fault do_double_fault
> > +paranoiderrorentry double_fault __do_double_fault
> >  zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun
> >  errorentry invalid_TSS do_invalid_TSS
> >  errorentry segment_not_present do_segment_not_present
> > @@ -1486,7 +1551,7 @@ error_sti:
> >   */
> >  error_kernelspace:
> >         incl %ebx
> > -       leaq irq_return(%rip),%rcx
> > +       leaq irq_return_iret(%rip),%rcx
> >         cmpq %rcx,RIP+8(%rsp)
> >         je error_swapgs
> >         movl %ecx,%eax  /* zero extend */
> > --- /dev/null
> > +++ b/arch/x86/kernel/espfix_64.c
> > @@ -0,0 +1,208 @@
> > +/* ----------------------------------------------------------------------- *
> > + *
> > + *   Copyright 2014 Intel Corporation; author: H. Peter Anvin
> > + *
> > + *   This program is free software; you can redistribute it and/or modify it
> > + *   under the terms and conditions of the GNU General Public License,
> > + *   version 2, as published by the Free Software Foundation.
> > + *
> > + *   This program is distributed in the hope it will be useful, but WITHOUT
> > + *   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + *   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> > + *   more details.
> > + *
> > + * ----------------------------------------------------------------------- */
> > +
> > +/*
> > + * 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.
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/init_task.h>
> > +#include <linux/kernel.h>
> > +#include <linux/percpu.h>
> > +#include <linux/gfp.h>
> > +#include <linux/random.h>
> > +#include <asm/pgtable.h>
> > +#include <asm/pgalloc.h>
> > +#include <asm/setup.h>
> > +
> > +/*
> > + * 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 << (PGDIR_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 than one PGD for the ESPFIX hack"
> > +#endif
> > +
> > +#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
> > +
> > +/* This contains the *bottom* address of the espfix stack */
> > +DEFINE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack);
> > +DEFINE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr);
> > +
> > +/* Initialization mutex - should this be a spinlock? */
> > +static DEFINE_MUTEX(espfix_init_mutex);
> > +
> > +/* Page allocation bitmap - each page serves ESPFIX_STACKS_PER_PAGE CPUs */
> > +#define ESPFIX_MAX_PAGES  DIV_ROUND_UP(CONFIG_NR_CPUS, ESPFIX_STACKS_PER_PAGE)
> > +static void *espfix_pages[ESPFIX_MAX_PAGES];
> > +
> > +static __page_aligned_bss pud_t espfix_pud_page[PTRS_PER_PUD]
> > +       __aligned(PAGE_SIZE);
> > +
> > +static unsigned int page_random, slot_random;
> > +
> > +/*
> > + * 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.
> > + */
> > +static inline unsigned long espfix_base_addr(unsigned int cpu)
> > +{
> > +       unsigned long page, slot;
> > +       unsigned long addr;
> > +
> > +       page = (cpu / ESPFIX_STACKS_PER_PAGE) ^ page_random;
> > +       slot = (cpu + slot_random) % ESPFIX_STACKS_PER_PAGE;
> > +       addr = (page << PAGE_SHIFT) + (slot * ESPFIX_STACK_SIZE);
> > +       addr = (addr & 0xffffUL) | ((addr & ~0xffffUL) << 16);
> > +       addr += ESPFIX_BASE_ADDR;
> > +       return addr;
> > +}
> > +
> > +#define PTE_STRIDE        (65536/PAGE_SIZE)
> > +#define ESPFIX_PTE_CLONES (PTRS_PER_PTE/PTE_STRIDE)
> > +#define ESPFIX_PMD_CLONES PTRS_PER_PMD
> > +#define ESPFIX_PUD_CLONES (65536/(ESPFIX_PTE_CLONES*ESPFIX_PMD_CLONES))
> > +
> > +#define PGTABLE_PROT     ((_KERNPG_TABLE & ~_PAGE_RW) | _PAGE_NX)
> > +
> > +static void init_espfix_random(void)
> > +{
> > +       unsigned long rand;
> > +
> > +       /*
> > +        * This is run before the entropy pools are initialized,
> > +        * but this is hopefully better than nothing.
> > +        */
> > +       if (!arch_get_random_long(&rand)) {
> > +               /* The constant is an arbitrary large prime */
> > +               rdtscll(rand);
> > +               rand *= 0xc345c6b72fd16123UL;
> > +       }
> > +
> > +       slot_random = rand % ESPFIX_STACKS_PER_PAGE;
> > +       page_random = (rand / ESPFIX_STACKS_PER_PAGE)
> > +               & (ESPFIX_PAGE_SPACE - 1);
> > +}
> > +
> > +void __init init_espfix_bsp(void)
> > +{
> > +       pgd_t *pgd_p;
> > +       pteval_t ptemask;
> > +
> > +       ptemask = __supported_pte_mask;
> > +
> > +       /* Install the espfix pud into the kernel page directory */
> > +       pgd_p = &init_level4_pgt[pgd_index(ESPFIX_BASE_ADDR)];
> > +       pgd_populate(&init_mm, pgd_p, (pud_t *)espfix_pud_page);
> > +
> > +       /* Randomize the locations */
> > +       init_espfix_random();
> > +
> > +       /* The rest is the same as for any other processor */
> > +       init_espfix_ap();
> > +}
> > +
> > +void init_espfix_ap(void)
> > +{
> > +       unsigned int cpu, page;
> > +       unsigned long addr;
> > +       pud_t pud, *pud_p;
> > +       pmd_t pmd, *pmd_p;
> > +       pte_t pte, *pte_p;
> > +       int n;
> > +       void *stack_page;
> > +       pteval_t ptemask;
> > +
> > +       /* We only have to do this once... */
> > +       if (likely(this_cpu_read(espfix_stack)))
> > +               return;         /* Already initialized */
> > +
> > +       cpu = smp_processor_id();
> > +       addr = espfix_base_addr(cpu);
> > +       page = cpu/ESPFIX_STACKS_PER_PAGE;
> > +
> > +       /* Did another CPU already set this up? */
> > +       stack_page = ACCESS_ONCE(espfix_pages[page]);
> > +       if (likely(stack_page))
> > +               goto done;
> > +
> > +       mutex_lock(&espfix_init_mutex);
> > +
> > +       /* Did we race on the lock? */
> > +       stack_page = ACCESS_ONCE(espfix_pages[page]);
> > +       if (stack_page)
> > +               goto unlock_done;
> > +
> > +       ptemask = __supported_pte_mask;
> > +
> > +       pud_p = &espfix_pud_page[pud_index(addr)];
> > +       pud = *pud_p;
> > +       if (!pud_present(pud)) {
> > +               pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP);
> > +               pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask));
> > +               paravirt_alloc_pud(&init_mm, __pa(pmd_p) >> PAGE_SHIFT);
> > +               for (n = 0; n < ESPFIX_PUD_CLONES; n++)
> > +                       set_pud(&pud_p[n], pud);
> > +       }
> > +
> > +       pmd_p = pmd_offset(&pud, addr);
> > +       pmd = *pmd_p;
> > +       if (!pmd_present(pmd)) {
> > +               pte_p = (pte_t *)__get_free_page(PGALLOC_GFP);
> > +               pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask));
> > +               paravirt_alloc_pmd(&init_mm, __pa(pte_p) >> PAGE_SHIFT);
> > +               for (n = 0; n < ESPFIX_PMD_CLONES; n++)
> > +                       set_pmd(&pmd_p[n], pmd);
> > +       }
> > +
> > +       pte_p = pte_offset_kernel(&pmd, addr);
> > +       stack_page = (void *)__get_free_page(GFP_KERNEL);
> > +       pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
> > +       paravirt_alloc_pte(&init_mm, __pa(stack_page) >> PAGE_SHIFT);
> > +       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 */
> > +       ACCESS_ONCE(espfix_pages[page]) = stack_page;
> > +
> > +unlock_done:
> > +       mutex_unlock(&espfix_init_mutex);
> > +done:
> > +       this_cpu_write(espfix_stack, addr);
> > +       this_cpu_write(espfix_waddr, (unsigned long)stack_page
> > +                      + (addr & ~PAGE_MASK));
> > +}
> > --- a/arch/x86/kernel/ldt.c
> > +++ b/arch/x86/kernel/ldt.c
> > @@ -229,17 +229,6 @@ static int write_ldt(void __user *ptr, u
> >                 }
> >         }
> >
> > -       /*
> > -        * On x86-64 we do not support 16-bit segments due to
> > -        * IRET leaking the high bits of the kernel stack address.
> > -        */
> > -#ifdef CONFIG_X86_64
> > -       if (!ldt_info.seg_32bit) {
> > -               error = -EINVAL;
> > -               goto out_unlock;
> > -       }
> > -#endif
> > -
> >         fill_ldt(&ldt, &ldt_info);
> >         if (oldmode)
> >                 ldt.avl = 0;
> > --- a/arch/x86/kernel/smpboot.c
> > +++ b/arch/x86/kernel/smpboot.c
> > @@ -271,6 +271,13 @@ notrace static void __cpuinit start_seco
> >         check_tsc_sync_target();
> >
> >         /*
> > +        * Enable the espfix hack for this CPU
> > +        */
> > +#ifdef CONFIG_X86_64
> > +       init_espfix_ap();
> > +#endif
> > +
> > +       /*
> >          * We need to hold call_lock, so there is no inconsistency
> >          * between the time smp_call_function() determines number of
> >          * IPI recipients, and the time when the determination is made
> > --- a/arch/x86/mm/dump_pagetables.c
> > +++ b/arch/x86/mm/dump_pagetables.c
> > @@ -30,11 +30,13 @@ struct pg_state {
> >         unsigned long start_address;
> >         unsigned long current_address;
> >         const struct addr_marker *marker;
> > +       unsigned long lines;
> >  };
> >
> >  struct addr_marker {
> >         unsigned long start_address;
> >         const char *name;
> > +       unsigned long max_lines;
> >  };
> >
> >  /* indices for address_markers; keep sync'd w/ address_markers below */
> > @@ -45,6 +47,7 @@ enum address_markers_idx {
> >         LOW_KERNEL_NR,
> >         VMALLOC_START_NR,
> >         VMEMMAP_START_NR,
> > +       ESPFIX_START_NR,
> >         HIGH_KERNEL_NR,
> >         MODULES_VADDR_NR,
> >         MODULES_END_NR,
> > @@ -67,6 +70,7 @@ static struct addr_marker address_marker
> >         { PAGE_OFFSET,          "Low Kernel Mapping" },
> >         { VMALLOC_START,        "vmalloc() Area" },
> >         { VMEMMAP_START,        "Vmemmap" },
> > +       { ESPFIX_BASE_ADDR,     "ESPfix Area", 16 },
> >         { __START_KERNEL_map,   "High Kernel Mapping" },
> >         { MODULES_VADDR,        "Modules" },
> >         { MODULES_END,          "End Modules" },
> > @@ -163,7 +167,7 @@ static void note_page(struct seq_file *m
> >                       pgprot_t new_prot, int level)
> >  {
> >         pgprotval_t prot, cur;
> > -       static const char units[] = "KMGTPE";
> > +       static const char units[] = "BKMGTPE";
> >
> >         /*
> >          * If we have a "break" in the series, we need to flush the state that
> > @@ -178,6 +182,7 @@ static void note_page(struct seq_file *m
> >                 st->current_prot = new_prot;
> >                 st->level = level;
> >                 st->marker = address_markers;
> > +               st->lines = 0;
> >                 seq_printf(m, "---[ %s ]---\n", st->marker->name);
> >         } else if (prot != cur || level != st->level ||
> >                    st->current_address >= st->marker[1].start_address) {
> > @@ -188,17 +193,21 @@ static void note_page(struct seq_file *m
> >                 /*
> >                  * Now print the actual finished series
> >                  */
> > -               seq_printf(m, "0x%0*lx-0x%0*lx   ",
> > -                          width, st->start_address,
> > -                          width, st->current_address);
> > -
> > -               delta = (st->current_address - st->start_address) >> 10;
> > -               while (!(delta & 1023) && unit[1]) {
> > -                       delta >>= 10;
> > -                       unit++;
> > +               if (!st->marker->max_lines ||
> > +                   st->lines < st->marker->max_lines) {
> > +                       seq_printf(m, "0x%0*lx-0x%0*lx   ",
> > +                                  width, st->start_address,
> > +                                  width, st->current_address);
> > +
> > +                       delta = (st->current_address - st->start_address) >> 10;
> > +                       while (!(delta & 1023) && unit[1]) {
> > +                               delta >>= 10;
> > +                               unit++;
> > +                       }
> > +                       seq_printf(m, "%9lu%c ", delta, *unit);
> > +                       printk_prot(m, st->current_prot, st->level);
> >                 }
> > -               seq_printf(m, "%9lu%c ", delta, *unit);
> > -               printk_prot(m, st->current_prot, st->level);
> > +               st->lines++;
> >
> >                 /*
> >                  * We print markers for special areas of address space,
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -606,6 +606,10 @@ asmlinkage void __init start_kernel(void
> >         if (efi_enabled(EFI_RUNTIME_SERVICES))
> >                 efi_enter_virtual_mode();
> >  #endif
> > +#ifdef CONFIG_X86_64
> > +       /* Should be run before the first non-init thread is created */
> > +       init_espfix_bsp();
> > +#endif
> >         thread_info_cache_init();
> >         cred_init();
> >         fork_init(totalram_pages);
> >
> >
> > Patches currently in stable-queue which might be from hpa@xxxxxxxxxxxxxxx are
> >
> > queue-3.4/x86-espfix-move-espfix-definitions-into-a-separate-header-file.patch
> > queue-3.4/x86-espfix-make-it-possible-to-disable-16-bit-support.patch
> > queue-3.4/x86-espfix-fix-broken-header-guard.patch
> > queue-3.4/x86-64-espfix-don-t-leak-bits-31-16-of-esp-returning-to-16-bit-stack.patch
> > queue-3.4/x86-espfix-make-espfix64-a-kconfig-option-fix-uml.patch
> --
> To unsubscribe from this list: send the line "unsubscribe stable" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]