Collected vdso/vsyscall fixes for 3.1
Subsystems (6)
v2 cover Collected vdso/vsyscall fixes for 3.1
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.
Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Add user_64bit_mode paravirt op
x86-64: Add vsyscall:emulate_vsyscall trace event
arch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.h
Signature · 1 line
1.7.6
PATCH v2 1/6 x86-64: Pad vDSO to a page boundary
This avoids an information leak to userspace.
--- arch/x86/vdso/vdso.S | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/vdso/vdso.S +1 -0
@@ -9,6 +9,7 @@ __PAGE_ALIGNED_DATA vdso_start: .incbin "arch/x86/vdso/vdso.so" vdso_end: + .align PAGE_SIZE /* extra data here leaks to userspace. */ .previous
Signature · 1 line
1.7.6
PATCH v2 1/6 x86-64: Pad vDSO to a page boundary
In reply to Andy LutomirskiThis avoids an information leak to userspace.
--- arch/x86/vdso/vdso.S | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/vdso/vdso.S +1 -0
@@ -9,6 +9,7 @@ __PAGE_ALIGNED_DATA vdso_start: .incbin "arch/x86/vdso/vdso.so" vdso_end: + .align PAGE_SIZE /* extra data here leaks to userspace. */ .previous
Signature · 1 line
1.7.6
PATCH v2 1/6 x86-64: Pad vDSO to a page boundary
In reply to Andy LutomirskiThis avoids an information leak to userspace.
--- arch/x86/vdso/vdso.S | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/vdso/vdso.S +1 -0
@@ -9,6 +9,7 @@ __PAGE_ALIGNED_DATA vdso_start: .incbin "arch/x86/vdso/vdso.so" vdso_end: + .align PAGE_SIZE /* extra data here leaks to userspace. */ .previous
Signature · 1 line
1.7.6
PATCH v2 2/6 x86-64: Move the "user" vsyscall segment out of the data segment.
In reply to Andy LutomirskiThe kernel's loader doesn't seem to care, but gold complains.
--- arch/x86/kernel/vmlinux.lds.S | 36 ++++++++++++++++++------------------ 1 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/kernel/vmlinux.lds.S +18 -18
@@ -154,6 +154,24 @@ SECTIONS #ifdef CONFIG_X86_64 + . = ALIGN(PAGE_SIZE); + __vvar_page = .; + + .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { + + /* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) \ + . = offset; \ + *(.vvar_ ## name) +#define __VVAR_KERNEL_LDS +#include <asm/vvar.h> +#undef __VVAR_KERNEL_LDS +#undef EMIT_VVAR + + } :data + + . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); + #define VSYSCALL_ADDR (-10*1024*1024) #define VLOAD_OFFSET (VSYSCALL_ADDR - __vsyscall_0 + LOAD_OFFSET)
@@ -162,7 +180,6 @@ SECTIONS #define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0) #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET) - . = ALIGN(4096); __vsyscall_0 = .; . = VSYSCALL_ADDR;
@@ -185,23 +202,6 @@ SECTIONS #undef VVIRT_OFFSET #undef VVIRT - __vvar_page = .; - - .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { - - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = offset; \ - *(.vvar_ ## name) -#define __VVAR_KERNEL_LDS -#include <asm/vvar.h> -#undef __VVAR_KERNEL_LDS -#undef EMIT_VVAR - - } :data - - . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); - #endif /* CONFIG_X86_64 */ /* Init code and data - will be freed after init */
Signature · 1 line
1.7.6
PATCH v2 2/6 x86-64: Move the "user" vsyscall segment out of the data segment.
In reply to Andy LutomirskiThe kernel's loader doesn't seem to care, but gold complains.
--- arch/x86/kernel/vmlinux.lds.S | 36 ++++++++++++++++++------------------ 1 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/kernel/vmlinux.lds.S +18 -18
@@ -154,6 +154,24 @@ SECTIONS #ifdef CONFIG_X86_64 + . = ALIGN(PAGE_SIZE); + __vvar_page = .; + + .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { + + /* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) \ + . = offset; \ + *(.vvar_ ## name) +#define __VVAR_KERNEL_LDS +#include <asm/vvar.h> +#undef __VVAR_KERNEL_LDS +#undef EMIT_VVAR + + } :data + + . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); + #define VSYSCALL_ADDR (-10*1024*1024) #define VLOAD_OFFSET (VSYSCALL_ADDR - __vsyscall_0 + LOAD_OFFSET)
@@ -162,7 +180,6 @@ SECTIONS #define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0) #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET) - . = ALIGN(4096); __vsyscall_0 = .; . = VSYSCALL_ADDR;
@@ -185,23 +202,6 @@ SECTIONS #undef VVIRT_OFFSET #undef VVIRT - __vvar_page = .; - - .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { - - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = offset; \ - *(.vvar_ ## name) -#define __VVAR_KERNEL_LDS -#include <asm/vvar.h> -#undef __VVAR_KERNEL_LDS -#undef EMIT_VVAR - - } :data - - . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); - #endif /* CONFIG_X86_64 */ /* Init code and data - will be freed after init */
Signature · 1 line
1.7.6
PATCH v2 3/6 x86-64: Work around gold bug 13023
In reply to Andy LutomirskiGold has trouble assigning numbers to the location counter inside of an output section description. The bug was triggered by 9fd67b4ed0714ab718f1f9bd14c344af336a6df7, which consolidated all of the vsyscall sections into a single section. The workaround is IMO still nicer than the old way of doing it.
This produces an apparently valid kernel image and passes my vdso tests on both GNU ld version 2.21.51.0.6-2.fc15 20110118 and GNU gold (version 2.21.51.0.6-2.fc15 20110118) 1.10 as distributed by Fedora 15.
--- arch/x86/kernel/vmlinux.lds.S | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-)
arch/x86/kernel/vmlinux.lds.S +10 -6
@@ -158,10 +158,12 @@ SECTIONS __vvar_page = .; .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { + /* work around gold bug 13023 */ + __vvar_beginning_hack = .; - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = offset; \ + /* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) \ + . = __vvar_beginning_hack + offset; \ *(.vvar_ ## name) #define __VVAR_KERNEL_LDS #include <asm/vvar.h>
@@ -184,15 +186,17 @@ SECTIONS . = VSYSCALL_ADDR; .vsyscall : AT(VLOAD(.vsyscall)) { + /* work around gold bug 13023 */ + __vsyscall_beginning_hack = .; *(.vsyscall_0) - . = 1024; + . = __vsyscall_beginning_hack + 1024; *(.vsyscall_1) - . = 2048; + . = __vsyscall_beginning_hack + 2048; *(.vsyscall_2) - . = 4096; /* Pad the whole page. */ + . = __vsyscall_beginning_hack + 4096; /* Pad the whole page. */ } :user =0xcc . = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
Signature · 1 line
1.7.6
PATCH v2 3/6 x86-64: Work around gold bug 13023
In reply to Andy LutomirskiGold has trouble assigning numbers to the location counter inside of an output section description. The bug was triggered by 9fd67b4ed0714ab718f1f9bd14c344af336a6df7, which consolidated all of the vsyscall sections into a single section. The workaround is IMO still nicer than the old way of doing it.
This produces an apparently valid kernel image and passes my vdso tests on both GNU ld version 2.21.51.0.6-2.fc15 20110118 and GNU gold (version 2.21.51.0.6-2.fc15 20110118) 1.10 as distributed by Fedora 15.
--- arch/x86/kernel/vmlinux.lds.S | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-)
arch/x86/kernel/vmlinux.lds.S +10 -6
@@ -158,10 +158,12 @@ SECTIONS __vvar_page = .; .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { + /* work around gold bug 13023 */ + __vvar_beginning_hack = .; - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = offset; \ + /* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) \ + . = __vvar_beginning_hack + offset; \ *(.vvar_ ## name) #define __VVAR_KERNEL_LDS #include <asm/vvar.h>
@@ -184,15 +186,17 @@ SECTIONS . = VSYSCALL_ADDR; .vsyscall : AT(VLOAD(.vsyscall)) { + /* work around gold bug 13023 */ + __vsyscall_beginning_hack = .; *(.vsyscall_0) - . = 1024; + . = __vsyscall_beginning_hack + 1024; *(.vsyscall_1) - . = 2048; + . = __vsyscall_beginning_hack + 2048; *(.vsyscall_2) - . = 4096; /* Pad the whole page. */ + . = __vsyscall_beginning_hack + 4096; /* Pad the whole page. */ } :user =0xcc . = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
Signature · 1 line
1.7.6
PATCH v2 4/6 x86-64/xen: Enable the vvar mapping
In reply to Andy LutomirskiXen needs to handle VVAR_PAGE, introduced in git commit:9fd67b4ed0714ab718f1f9bd14c344af336a6df7
x86-64: Give vvars their own page
Otherwise we die during bootup with a message like:
(XEN) mm.c:940:d10 Error getting mfn 1888 (pfn 1e3e48) from L1 entry
8000000001888465 for l1e_owner=10, pg_owner=10 (XEN) mm.c:5049:d10 ptwr_emulate: could not get_page_from_l1e() [ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null) [ 0.000000] IP: [<ffffffff8103a930>] xen_set_pte+0x20/0xe0
--- arch/x86/xen/mmu.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/x86/xen/mmu.c +3 -1
@@ -1916,6 +1916,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)# endif #else case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: +case VVAR_PAGE :#endif case FIX_TEXT_POKE0 :case FIX_TEXT_POKE1 :
@@ -1956,7 +1957,8 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)#ifdef CONFIG_X86_64 /* Replicate changes to map the vsyscall page into the user pagetable vsyscall mapping. */ -if (idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) { +if ((idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) || + idx ==VVAR_PAGE ) {unsigned long vaddr =__fix_to_virt (idx);set_pte_vaddr_pud (level3_user_vsyscall, vaddr, pte); }
Signature · 1 line
1.7.6
PATCH v2 4/6 x86-64/xen: Enable the vvar mapping
In reply to Andy LutomirskiXen needs to handle VVAR_PAGE, introduced in git commit:9fd67b4ed0714ab718f1f9bd14c344af336a6df7
x86-64: Give vvars their own page
Otherwise we die during bootup with a message like:
(XEN) mm.c:940:d10 Error getting mfn 1888 (pfn 1e3e48) from L1 entry
8000000001888465 for l1e_owner=10, pg_owner=10 (XEN) mm.c:5049:d10 ptwr_emulate: could not get_page_from_l1e() [ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null) [ 0.000000] IP: [<ffffffff8103a930>] xen_set_pte+0x20/0xe0
--- arch/x86/xen/mmu.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/x86/xen/mmu.c +3 -1
@@ -1916,6 +1916,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)# endif #else case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: +case VVAR_PAGE :#endif case FIX_TEXT_POKE0 :case FIX_TEXT_POKE1 :
@@ -1956,7 +1957,8 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)#ifdef CONFIG_X86_64 /* Replicate changes to map the vsyscall page into the user pagetable vsyscall mapping. */ -if (idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) { +if ((idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) || + idx ==VVAR_PAGE ) {unsigned long vaddr =__fix_to_virt (idx);set_pte_vaddr_pud (level3_user_vsyscall, vaddr, pte); }
Signature · 1 line
1.7.6
PATCH v2 5/6 x86-64: Add user_64bit_mode paravirt op
In reply to Andy LutomirskiThree places in the kernel assume that the only long mode CPL 3 selector is __USER_CS. This is not true on Xen -- Xen's sysretq changes cs to the magic value 0xe033.
Two of the places are corner cases, but as of "x86-64: Improve vsyscall emulation CS and RIP handling" (c9712944b2a12373cb6ff8059afcfb7e826a6c54), vsyscalls will segfault if called with Xen's extra CS selector. This causes a panic when older init builds die.
It seems impossible to make Xen use __USER_CS reliably without taking a performance hit on every system call, so this fixes the tests instead with a new paravirt op. It's a little ugly because ptrace.h can't include paravirt.h.
--- arch/x86/include/asm/desc.h | 4 ++-- arch/x86/include/asm/paravirt_types.h | 6 ++++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++++++++ arch/x86/kernel/paravirt.c | 4 ++++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vsyscall_64.c | 6 +----- arch/x86/mm/fault.c | 2 +- arch/x86/xen/enlighten.c | 4 ++++ 8 files changed, 38 insertions(+), 9 deletions(-)
arch/x86/include/asm/desc.h +2 -2
@@ -27,8 +27,8 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in desc->base2 = (info->base_addr &0xff000000 ) >>24 ;/* -* Don't allow setting of the lm bit. It is useless anyway -* because 64bit system calls require __USER_CS: +* Don't allow setting of the lm bit. It would confuse +* user_64bit_mode and would get overridden by sysret anyway. */ desc->l =0 ; }
arch/x86/include/asm/paravirt_types.h +6 -0
@@ -41,6 +41,7 @@#include <asm/desc_defs.h> #include <asm/kmap_types.h> +#include <asm/pgtable_types.h> struct page ;struct thread_struct ;
@@ -63,6 +64,11 @@ struct paravirt_callee_save {struct pv_info {unsigned int kernel_rpl;int shared_kernel_pmd; + +#ifdef CONFIG_X86_64 +u16 extra_user_64bit_cs;/* __USER_CS if none */ +#endif +int paravirt_enabled;const char *name; };
arch/x86/include/asm/ptrace.h +19 -0
@@ -131,6 +131,9 @@ struct pt_regs {#ifdef __KERNEL__#include <linux/init.h> +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt_types.h> +#endif struct cpuinfo_x86 ;struct task_struct ;
@@ -187,6 +190,22 @@ static inline int v8086_mode(struct pt_regs *regs)#endif } +#ifdef CONFIG_X86_64 +static inline bool user_64bit_mode (struct pt_regs *regs) +{ +#ifndef CONFIG_PARAVIRT +/* +* On non-paravirt systems, this is the only long mode CPL 3 +* selector. We do not allow long mode selectors in the LDT. +*/ +return regs->cs == __USER_CS; +#else +/* Headers are too twisted for this to go in paravirt.h. */ +return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs; +#endif +} +#endif +/* * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode * when it traps. The previous stack will be directly underneath the saved
arch/x86/kernel/paravirt.c +4 -0
@@ -307,6 +307,10 @@ struct pv_info pv_info = { .paravirt_enabled = 0, .kernel_rpl = 0, .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */ + +#ifdef CONFIG_X86_64 + .extra_user_64bit_cs = __USER_CS, +#endif };struct pv_init_ops pv_init_ops = {
arch/x86/kernel/step.c +1 -1
@@ -74,7 +74,7 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)#ifdef CONFIG_X86_64 case 0x40 ... 0x4f: -if (regs->cs != __USER_CS) +if (!user_64bit_mode (regs))/* 32-bit mode: register increment */ return 0 ;/* 64-bit mode: REX prefix */
arch/x86/kernel/vsyscall_64.c +1 -5
@@ -127,11 +127,7 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)local_irq_enable (); -/* -* Real 64-bit user mode code has cs == __USER_CS. Anything else -* is bogus. -*/ -if (regs->cs != __USER_CS) { +if (!user_64bit_mode (regs)) {/* * If we trapped from kernel mode, we might as well OOPS now * instead of returning to some random address and OOPSing
arch/x86/mm/fault.c +1 -1
@@ -105,7 +105,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,* but for now it's good enough to assume that long * mode only uses well known segments or kernel. */ -return (!user_mode (regs)) || (regs->cs == __USER_CS); +return (!user_mode (regs) ||user_64bit_mode (regs));#endif case 0x60 :/* 0x64 thru 0x67 are valid prefixes in all modes. */
arch/x86/xen/enlighten.c +4 -0
@@ -951,6 +951,10 @@ static const struct pv_info xen_info __initconst = { .paravirt_enabled = 1, .shared_kernel_pmd = 0, +#ifdef CONFIG_X86_64 + .extra_user_64bit_cs = FLAT_USER_CS64, +#endif + .name = "Xen", };
Signature · 1 line
1.7.6
PATCH v2 5/6 x86-64: Add user_64bit_mode paravirt op
In reply to Andy LutomirskiThree places in the kernel assume that the only long mode CPL 3 selector is __USER_CS. This is not true on Xen -- Xen's sysretq changes cs to the magic value 0xe033.
Two of the places are corner cases, but as of "x86-64: Improve vsyscall emulation CS and RIP handling" (c9712944b2a12373cb6ff8059afcfb7e826a6c54), vsyscalls will segfault if called with Xen's extra CS selector. This causes a panic when older init builds die.
It seems impossible to make Xen use __USER_CS reliably without taking a performance hit on every system call, so this fixes the tests instead with a new paravirt op. It's a little ugly because ptrace.h can't include paravirt.h.
--- arch/x86/include/asm/desc.h | 4 ++-- arch/x86/include/asm/paravirt_types.h | 6 ++++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++++++++ arch/x86/kernel/paravirt.c | 4 ++++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vsyscall_64.c | 6 +----- arch/x86/mm/fault.c | 2 +- arch/x86/xen/enlighten.c | 4 ++++ 8 files changed, 38 insertions(+), 9 deletions(-)
arch/x86/include/asm/desc.h +2 -2
@@ -27,8 +27,8 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in desc->base2 = (info->base_addr &0xff000000 ) >>24 ;/* -* Don't allow setting of the lm bit. It is useless anyway -* because 64bit system calls require __USER_CS: +* Don't allow setting of the lm bit. It would confuse +* user_64bit_mode and would get overridden by sysret anyway. */ desc->l =0 ; }
arch/x86/include/asm/paravirt_types.h +6 -0
@@ -41,6 +41,7 @@#include <asm/desc_defs.h> #include <asm/kmap_types.h> +#include <asm/pgtable_types.h> struct page ;struct thread_struct ;
@@ -63,6 +64,11 @@ struct paravirt_callee_save {struct pv_info {unsigned int kernel_rpl;int shared_kernel_pmd; + +#ifdef CONFIG_X86_64 +u16 extra_user_64bit_cs;/* __USER_CS if none */ +#endif +int paravirt_enabled;const char *name; };
arch/x86/include/asm/ptrace.h +19 -0
@@ -131,6 +131,9 @@ struct pt_regs {#ifdef __KERNEL__#include <linux/init.h> +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt_types.h> +#endif struct cpuinfo_x86 ;struct task_struct ;
@@ -187,6 +190,22 @@ static inline int v8086_mode(struct pt_regs *regs)#endif } +#ifdef CONFIG_X86_64 +static inline bool user_64bit_mode (struct pt_regs *regs) +{ +#ifndef CONFIG_PARAVIRT +/* +* On non-paravirt systems, this is the only long mode CPL 3 +* selector. We do not allow long mode selectors in the LDT. +*/ +return regs->cs == __USER_CS; +#else +/* Headers are too twisted for this to go in paravirt.h. */ +return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs; +#endif +} +#endif +/* * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode * when it traps. The previous stack will be directly underneath the saved
arch/x86/kernel/paravirt.c +4 -0
@@ -307,6 +307,10 @@ struct pv_info pv_info = { .paravirt_enabled = 0, .kernel_rpl = 0, .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */ + +#ifdef CONFIG_X86_64 + .extra_user_64bit_cs = __USER_CS, +#endif };struct pv_init_ops pv_init_ops = {
arch/x86/kernel/step.c +1 -1
@@ -74,7 +74,7 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)#ifdef CONFIG_X86_64 case 0x40 ... 0x4f: -if (regs->cs != __USER_CS) +if (!user_64bit_mode (regs))/* 32-bit mode: register increment */ return 0 ;/* 64-bit mode: REX prefix */
arch/x86/kernel/vsyscall_64.c +1 -5
@@ -127,11 +127,7 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)local_irq_enable (); -/* -* Real 64-bit user mode code has cs == __USER_CS. Anything else -* is bogus. -*/ -if (regs->cs != __USER_CS) { +if (!user_64bit_mode (regs)) {/* * If we trapped from kernel mode, we might as well OOPS now * instead of returning to some random address and OOPSing
arch/x86/mm/fault.c +1 -1
@@ -105,7 +105,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,* but for now it's good enough to assume that long * mode only uses well known segments or kernel. */ -return (!user_mode (regs)) || (regs->cs == __USER_CS); +return (!user_mode (regs) ||user_64bit_mode (regs));#endif case 0x60 :/* 0x64 thru 0x67 are valid prefixes in all modes. */
arch/x86/xen/enlighten.c +4 -0
@@ -951,6 +951,10 @@ static const struct pv_info xen_info __initconst = { .paravirt_enabled = 1, .shared_kernel_pmd = 0, +#ifdef CONFIG_X86_64 + .extra_user_64bit_cs = FLAT_USER_CS64, +#endif + .name = "Xen", };
Signature · 1 line
1.7.6
PATCH v2 6/6 x86-64: Add vsyscall:emulate_vsyscall trace event
In reply to Andy LutomirskiVsyscall emulation is slow, so make it easy to track down.
--- arch/x86/kernel/vsyscall_64.c | 6 ++++++ arch/x86/kernel/vsyscall_trace.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 0 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.h
arch/x86/kernel/vsyscall_64.c +6 -0
@@ -50,6 +50,9 @@#include <asm/vgtod.h> #include <asm/traps.h> +#define CREATE_TRACE_POINTS +#include "vsyscall_trace.h" +DEFINE_VVAR (int, vgetcpu_mode); DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) = {
@@ -146,6 +149,9 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)* and int 0xcc is two bytes long. */ vsyscall_nr =addr_to_vsyscall_nr (regs->ip -2 ); + +trace_emulate_vsyscall (vsyscall_nr); +if (vsyscall_nr <0 ) {warn_bad_vsyscall (KERN_WARNING , regs,"illegal int 0xcc (exploit attempt?)" );
arch/x86/kernel/vsyscall_trace.h new file +29 -0
@@ -0,0 +1,29 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM vsyscall + +#if !defined(__VSYSCALL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ ) +#define __VSYSCALL_TRACE_H + +#include <linux/tracepoint.h> + +TRACE_EVENT (emulate_vsyscall, + + TP_PROTO(int nr), + +TP_ARGS (nr), + +TP_STRUCT__entry (__field (int, nr)), + +TP_fast_assign ( + __entry->nr = nr; + ), + +TP_printk ("nr = %d" , __entry->nr) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../arch/x86/kernel +#define TRACE_INCLUDE_FILE vsyscall_trace +#include <trace/define_trace.h>
Signature · 1 line
1.7.6
PATCH v2 6/6 x86-64: Add vsyscall:emulate_vsyscall trace event
In reply to Andy LutomirskiVsyscall emulation is slow, so make it easy to track down.
--- arch/x86/kernel/vsyscall_64.c | 6 ++++++ arch/x86/kernel/vsyscall_trace.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 0 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.h
arch/x86/kernel/vsyscall_64.c +6 -0
@@ -50,6 +50,9 @@#include <asm/vgtod.h> #include <asm/traps.h> +#define CREATE_TRACE_POINTS +#include "vsyscall_trace.h" +DEFINE_VVAR (int, vgetcpu_mode); DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) = {
@@ -146,6 +149,9 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)* and int 0xcc is two bytes long. */ vsyscall_nr =addr_to_vsyscall_nr (regs->ip -2 ); + +trace_emulate_vsyscall (vsyscall_nr); +if (vsyscall_nr <0 ) {warn_bad_vsyscall (KERN_WARNING , regs,"illegal int 0xcc (exploit attempt?)" );
arch/x86/kernel/vsyscall_trace.h new file +29 -0
@@ -0,0 +1,29 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM vsyscall + +#if !defined(__VSYSCALL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ ) +#define __VSYSCALL_TRACE_H + +#include <linux/tracepoint.h> + +TRACE_EVENT (emulate_vsyscall, + + TP_PROTO(int nr), + +TP_ARGS (nr), + +TP_STRUCT__entry (__field (int, nr)), + +TP_fast_assign ( + __entry->nr = nr; + ), + +TP_printk ("nr = %d" , __entry->nr) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../arch/x86/kernel +#define TRACE_INCLUDE_FILE vsyscall_trace +#include <trace/define_trace.h>
Signature · 1 line
1.7.6
Re: [PATCH v2 4/6] x86-64/xen: Enable the vvar mapping
In reply to Andy LutomirskiQuoted 6 lines · Andy Lutomirski
Xen needs to handle
VVAR_PAGE, introduced in git commit:9fd67b4ed0714ab718f1f9bd14c344af336a6df7
x86-64: Give vvars their own pageOtherwise we die during bootup with a message like:
Quoted 8 lines
(XEN) mm.c:940:d10 Error getting mfn 1888 (pfn 1e3e48) from L1 entry
8000000001888465 for l1e_owner=10, pg_owner=10 (XEN) mm.c:5049:d10 ptwr_emulate: could not get_page_from_l1e() [ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null) [ 0.000000] IP: [<ffffffff8103a930>] xen_set_pte+0x20/0xe0Signed-off-by Andy Lutomirski <[email protected]>Reported-by Konrad Rzeszutek Wilk <[email protected]>
Quoted 28 lines
--- arch/x86/xen/mmu.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)arch/x86/xen/mmu.c +3
-1@@ -1916,6 +1916,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)# endif #else case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: +case VVAR_PAGE :#endif case FIX_TEXT_POKE0 :case FIX_TEXT_POKE1 :@@ -1956,7 +1957,8 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)#ifdef CONFIG_X86_64 /* Replicate changes to map the vsyscall page into the user pagetable vsyscall mapping. */ -if (idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) { +if ((idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) || + idx ==VVAR_PAGE ) {unsigned long vaddr =__fix_to_virt (idx);set_pte_vaddr_pud (level3_user_vsyscall, vaddr, pte); }Signature · 1 line
1.7.6
Re: [PATCH v2 4/6] x86-64/xen: Enable the vvar mapping
In reply to Andy LutomirskiQuoted 6 lines · Andy Lutomirski
Xen needs to handle
VVAR_PAGE, introduced in git commit:9fd67b4ed0714ab718f1f9bd14c344af336a6df7
x86-64: Give vvars their own pageOtherwise we die during bootup with a message like:
Quoted 8 lines
(XEN) mm.c:940:d10 Error getting mfn 1888 (pfn 1e3e48) from L1 entry
8000000001888465 for l1e_owner=10, pg_owner=10 (XEN) mm.c:5049:d10 ptwr_emulate: could not get_page_from_l1e() [ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null) [ 0.000000] IP: [<ffffffff8103a930>] xen_set_pte+0x20/0xe0Signed-off-by Andy Lutomirski <[email protected]>Reported-by Konrad Rzeszutek Wilk <[email protected]>
Quoted 28 lines
--- arch/x86/xen/mmu.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)arch/x86/xen/mmu.c +3
-1@@ -1916,6 +1916,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)# endif #else case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: +case VVAR_PAGE :#endif case FIX_TEXT_POKE0 :case FIX_TEXT_POKE1 :@@ -1956,7 +1957,8 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)#ifdef CONFIG_X86_64 /* Replicate changes to map the vsyscall page into the user pagetable vsyscall mapping. */ -if (idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) { +if ((idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) || + idx ==VVAR_PAGE ) {unsigned long vaddr =__fix_to_virt (idx);set_pte_vaddr_pud (level3_user_vsyscall, vaddr, pte); }Signature · 1 line
1.7.6
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
Hm, you seemed to have the x86 maintainers on your email..
Quoted 33 lines
[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Adduser_64bit_modeparavirt op
x86-64: Add vsyscall:emulate_vsyscall trace eventarch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.hSignature · 1 line
1.7.6
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
Hm, you seemed to have the x86 maintainers on your email..
Quoted 33 lines
[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Adduser_64bit_modeparavirt op
x86-64: Add vsyscall:emulate_vsyscall trace eventarch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.hSignature · 1 line
1.7.6
Quoted 10 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
I put them on the To list for you.
Quoted 33 lines
Quoted 33 lines
[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Adduser_64bit_modeparavirt op
x86-64: Add vsyscall:emulate_vsyscall trace eventarch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.hSignature · 1 line
1.7.6
Quoted 10 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
I put them on the To list for you.
Quoted 33 lines
Quoted 33 lines
[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Adduser_64bit_modeparavirt op
x86-64: Add vsyscall:emulate_vsyscall trace eventarch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.hSignature · 1 line
1.7.6
Quoted 10 lines · Konrad Rzeszutek Wilk
Quoted 9 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
Quoted 6 lines
Quoted 1 line
Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
I put them on the To list for you.
Are you sure about that coffee? I'm pretty sure I had [email protected] in there.
--Andy
Quoted 10 lines · Konrad Rzeszutek Wilk
Quoted 9 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
Quoted 6 lines
Quoted 1 line
Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
I put them on the To list for you.
Are you sure about that coffee? I'm pretty sure I had [email protected] in there.
--Andy
Hello Andy,
Quoted 23 lines · you
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Adduser_64bit_modeparavirt op
x86-64: Add vsyscall:emulate_vsyscall trace event
Quoted 14 lines
arch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.h
Compile and boot tested on Xen 4.1.1 and baremetal on x86_64, it fixes my boot panic under Xen.
Hello Andy,
Quoted 23 lines · you
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)[1] https://gitorious.org/linux-test-utils/linux-clock-tests
Changes from v1:
- Improve changelog message for "x86-64/xen: Enable the vvar mapping"
- Fix 32-bit build.
- Add patch 6.Andy Lutomirski (6):
x86-64: Pad vDSO to a page boundary
x86-64: Move the "user" vsyscall segment out of the data segment.
x86-64: Work around gold bug 13023
x86-64/xen: Enable the vvar mapping
x86-64: Adduser_64bit_modeparavirt op
x86-64: Add vsyscall:emulate_vsyscall trace event
Quoted 14 lines
arch/x86/include/asm/desc.h | 4 +- arch/x86/include/asm/paravirt_types.h | 6 ++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++ arch/x86/kernel/paravirt.c | 4 +++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 46 ++++++++++++++++++--------------- arch/x86/kernel/vsyscall_64.c | 12 +++++--- arch/x86/kernel/vsyscall_trace.h | 29 ++++++++++++++++++++ arch/x86/mm/fault.c | 2 +- arch/x86/vdso/vdso.S | 1 + arch/x86/xen/enlighten.c | 4 +++ arch/x86/xen/mmu.c | 4 ++- 12 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/x86/kernel/vsyscall_trace.h
Compile and boot tested on Xen 4.1.1 and baremetal on x86_64, it fixes my boot panic under Xen.
[tip:x86/vdso] x86-64: Pad vDSO to a page boundary
In reply to Andy LutomirskiCommit-ID: 1bdfac19b3ecfca545281c15c7aea7ebc2eaef31 Gitweb: http://git.kernel.org/tip/1bdfac19b3ecfca545281c15c7aea7ebc2eaef31 Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 3 Aug 2011 09:31:49 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 4 Aug 2011 16:13:34 -0700
x86-64: Pad vDSO to a page boundary
This avoids an information leak to userspace.
--- arch/x86/vdso/vdso.S | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/vdso/vdso.S +1 -0
@@ -9,6 +9,7 @@ __PAGE_ALIGNED_DATA vdso_start: .incbin "arch/x86/vdso/vdso.so" vdso_end: + .align PAGE_SIZE /* extra data here leaks to userspace. */ .previous
[tip:x86/vdso] x86-64: Move the "user" vsyscall segment out of the data segment.
In reply to Andy LutomirskiCommit-ID: 9c40818da5b39fca236029059ab839857b1ef56c Gitweb: http://git.kernel.org/tip/9c40818da5b39fca236029059ab839857b1ef56c Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 3 Aug 2011 09:31:50 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 4 Aug 2011 16:13:35 -0700
x86-64: Move the "user" vsyscall segment out of the data segment.
The kernel's loader doesn't seem to care, but gold complains.
--- arch/x86/kernel/vmlinux.lds.S | 36 ++++++++++++++++++------------------ 1 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/kernel/vmlinux.lds.S +18 -18
@@ -154,6 +154,24 @@ SECTIONS #ifdef CONFIG_X86_64 + . = ALIGN(PAGE_SIZE); + __vvar_page = .; + + .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { + + /* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) \ + . = offset; \ + *(.vvar_ ## name) +#define __VVAR_KERNEL_LDS +#include <asm/vvar.h> +#undef __VVAR_KERNEL_LDS +#undef EMIT_VVAR + + } :data + + . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); + #define VSYSCALL_ADDR (-10*1024*1024) #define VLOAD_OFFSET (VSYSCALL_ADDR - __vsyscall_0 + LOAD_OFFSET)
@@ -162,7 +180,6 @@ SECTIONS #define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0) #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET) - . = ALIGN(4096); __vsyscall_0 = .; . = VSYSCALL_ADDR;
@@ -185,23 +202,6 @@ SECTIONS #undef VVIRT_OFFSET #undef VVIRT - __vvar_page = .; - - .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { - - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = offset; \ - *(.vvar_ ## name) -#define __VVAR_KERNEL_LDS -#include <asm/vvar.h> -#undef __VVAR_KERNEL_LDS -#undef EMIT_VVAR - - } :data - - . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); - #endif /* CONFIG_X86_64 */ /* Init code and data - will be freed after init */
[tip:x86/vdso] x86-64: Work around gold bug 13023
In reply to Andy LutomirskiCommit-ID: f670bb760e7d32ec9c690e748a1d5d04921363ab Gitweb: http://git.kernel.org/tip/f670bb760e7d32ec9c690e748a1d5d04921363ab Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 3 Aug 2011 09:31:51 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 4 Aug 2011 16:13:38 -0700
x86-64: Work around gold bug 13023
Gold has trouble assigning numbers to the location counter inside of an output section description. The bug was triggered by 9fd67b4ed0714ab718f1f9bd14c344af336a6df7, which consolidated all of the vsyscall sections into a single section. The workaround is IMO still nicer than the old way of doing it.
This produces an apparently valid kernel image and passes my vdso tests on both GNU ld version 2.21.51.0.6-2.fc15 20110118 and GNU gold (version 2.21.51.0.6-2.fc15 20110118) 1.10 as distributed by Fedora 15.
--- arch/x86/kernel/vmlinux.lds.S | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-)
arch/x86/kernel/vmlinux.lds.S +10 -6
@@ -158,10 +158,12 @@ SECTIONS __vvar_page = .; .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { + /* work around gold bug 13023 */ + __vvar_beginning_hack = .; - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = offset; \ + /* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) \ + . = __vvar_beginning_hack + offset; \ *(.vvar_ ## name) #define __VVAR_KERNEL_LDS #include <asm/vvar.h>
@@ -184,15 +186,17 @@ SECTIONS . = VSYSCALL_ADDR; .vsyscall : AT(VLOAD(.vsyscall)) { + /* work around gold bug 13023 */ + __vsyscall_beginning_hack = .; *(.vsyscall_0) - . = 1024; + . = __vsyscall_beginning_hack + 1024; *(.vsyscall_1) - . = 2048; + . = __vsyscall_beginning_hack + 2048; *(.vsyscall_2) - . = 4096; /* Pad the whole page. */ + . = __vsyscall_beginning_hack + 4096; /* Pad the whole page. */ } :user =0xcc . = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
[tip:x86/vdso] x86-64, xen: Enable the vvar mapping
In reply to Andy LutomirskiCommit-ID: 5d5791af4c0d4fd32093882357506355c3357503 Gitweb: http://git.kernel.org/tip/5d5791af4c0d4fd32093882357506355c3357503 Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 3 Aug 2011 09:31:52 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 4 Aug 2011 16:13:47 -0700
x86-64, xen: Enable the vvar mapping
Xen needs to handle VVAR_PAGE, introduced in git commit:9fd67b4ed0714ab718f1f9bd14c344af336a6df7
x86-64: Give vvars their own page
Otherwise we die during bootup with a message like:
(XEN) mm.c:940:d10 Error getting mfn 1888 (pfn 1e3e48) from L1 entry
8000000001888465 for l1e_owner=10, pg_owner=10 (XEN) mm.c:5049:d10 ptwr_emulate: could not get_page_from_l1e() [ 0.000000] BUG: unable to handle kernel NULL pointer dereference at (null) [ 0.000000] IP: [<ffffffff8103a930>] xen_set_pte+0x20/0xe0
--- arch/x86/xen/mmu.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/x86/xen/mmu.c +3 -1
@@ -1829,6 +1829,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)# endif #else case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: +case VVAR_PAGE :#endif case FIX_TEXT_POKE0 :case FIX_TEXT_POKE1 :
@@ -1869,7 +1870,8 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)#ifdef CONFIG_X86_64 /* Replicate changes to map the vsyscall page into the user pagetable vsyscall mapping. */ -if (idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) { +if ((idx >=VSYSCALL_LAST_PAGE && idx <=VSYSCALL_FIRST_PAGE ) || + idx ==VVAR_PAGE ) {unsigned long vaddr =__fix_to_virt (idx);set_pte_vaddr_pud (level3_user_vsyscall, vaddr, pte); }
[tip:x86/vdso] x86-64: Add user_64bit_mode paravirt op
In reply to Andy LutomirskiCommit-ID: 318f5a2a672152328c9fb4dead504b89ec738a43 Gitweb: http://git.kernel.org/tip/318f5a2a672152328c9fb4dead504b89ec738a43 Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 3 Aug 2011 09:31:53 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 4 Aug 2011 16:13:49 -0700
x86-64: Add user_64bit_mode paravirt op
Three places in the kernel assume that the only long mode CPL 3 selector is __USER_CS. This is not true on Xen -- Xen's sysretq changes cs to the magic value 0xe033.
Two of the places are corner cases, but as of "x86-64: Improve vsyscall emulation CS and RIP handling" (c9712944b2a12373cb6ff8059afcfb7e826a6c54), vsyscalls will segfault if called with Xen's extra CS selector. This causes a panic when older init builds die.
It seems impossible to make Xen use __USER_CS reliably without taking a performance hit on every system call, so this fixes the tests instead with a new paravirt op. It's a little ugly because ptrace.h can't include paravirt.h.
--- arch/x86/include/asm/desc.h | 4 ++-- arch/x86/include/asm/paravirt_types.h | 6 ++++++ arch/x86/include/asm/ptrace.h | 19 +++++++++++++++++++ arch/x86/kernel/paravirt.c | 4 ++++ arch/x86/kernel/step.c | 2 +- arch/x86/kernel/vsyscall_64.c | 6 +----- arch/x86/mm/fault.c | 2 +- arch/x86/xen/enlighten.c | 4 ++++ 8 files changed, 38 insertions(+), 9 deletions(-)
arch/x86/include/asm/desc.h +2 -2
@@ -27,8 +27,8 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in desc->base2 = (info->base_addr &0xff000000 ) >>24 ;/* -* Don't allow setting of the lm bit. It is useless anyway -* because 64bit system calls require __USER_CS: +* Don't allow setting of the lm bit. It would confuse +* user_64bit_mode and would get overridden by sysret anyway. */ desc->l =0 ; }
arch/x86/include/asm/paravirt_types.h +6 -0
@@ -41,6 +41,7 @@#include <asm/desc_defs.h> #include <asm/kmap_types.h> +#include <asm/pgtable_types.h> struct page ;struct thread_struct ;
@@ -63,6 +64,11 @@ struct paravirt_callee_save {struct pv_info {unsigned int kernel_rpl;int shared_kernel_pmd; + +#ifdef CONFIG_X86_64 +u16 extra_user_64bit_cs;/* __USER_CS if none */ +#endif +int paravirt_enabled;const char *name; };
arch/x86/include/asm/ptrace.h +19 -0
@@ -131,6 +131,9 @@ struct pt_regs {#ifdef __KERNEL__#include <linux/init.h> +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt_types.h> +#endif struct cpuinfo_x86 ;struct task_struct ;
@@ -187,6 +190,22 @@ static inline int v8086_mode(struct pt_regs *regs)#endif } +#ifdef CONFIG_X86_64 +static inline bool user_64bit_mode (struct pt_regs *regs) +{ +#ifndef CONFIG_PARAVIRT +/* +* On non-paravirt systems, this is the only long mode CPL 3 +* selector. We do not allow long mode selectors in the LDT. +*/ +return regs->cs == __USER_CS; +#else +/* Headers are too twisted for this to go in paravirt.h. */ +return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs; +#endif +} +#endif +/* * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode * when it traps. The previous stack will be directly underneath the saved
arch/x86/kernel/paravirt.c +4 -0
@@ -299,6 +299,10 @@ struct pv_info pv_info = { .paravirt_enabled = 0, .kernel_rpl = 0, .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */ + +#ifdef CONFIG_X86_64 + .extra_user_64bit_cs = __USER_CS, +#endif };struct pv_init_ops pv_init_ops = {
arch/x86/kernel/step.c +1 -1
@@ -74,7 +74,7 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)#ifdef CONFIG_X86_64 case 0x40 ... 0x4f: -if (regs->cs != __USER_CS) +if (!user_64bit_mode (regs))/* 32-bit mode: register increment */ return 0 ;/* 64-bit mode: REX prefix */
arch/x86/kernel/vsyscall_64.c +1 -5
@@ -127,11 +127,7 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)local_irq_enable (); -/* -* Real 64-bit user mode code has cs == __USER_CS. Anything else -* is bogus. -*/ -if (regs->cs != __USER_CS) { +if (!user_64bit_mode (regs)) {/* * If we trapped from kernel mode, we might as well OOPS now * instead of returning to some random address and OOPSing
arch/x86/mm/fault.c +1 -1
@@ -105,7 +105,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,* but for now it's good enough to assume that long * mode only uses well known segments or kernel. */ -return (!user_mode (regs)) || (regs->cs == __USER_CS); +return (!user_mode (regs) ||user_64bit_mode (regs));#endif case 0x60 :/* 0x64 thru 0x67 are valid prefixes in all modes. */
arch/x86/xen/enlighten.c +4 -0
@@ -937,6 +937,10 @@ static const struct pv_info xen_info __initconst = { .paravirt_enabled = 1, .shared_kernel_pmd = 0, +#ifdef CONFIG_X86_64 + .extra_user_64bit_cs = FLAT_USER_CS64, +#endif + .name = "Xen", };
[tip:x86/vdso] x86-64: Add vsyscall:emulate_vsyscall trace event
In reply to Andy LutomirskiCommit-ID: c149a665ac488e0dac22a42287f45ad1bda06ff1 Gitweb: http://git.kernel.org/tip/c149a665ac488e0dac22a42287f45ad1bda06ff1 Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 3 Aug 2011 09:31:54 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 4 Aug 2011 16:13:53 -0700
x86-64: Add vsyscall:emulate_vsyscall trace event
Vsyscall emulation is slow, so make it easy to track down.
--- arch/x86/kernel/vsyscall_64.c | 6 ++++++ arch/x86/kernel/vsyscall_trace.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 0 deletions(-)
arch/x86/kernel/vsyscall_64.c +6 -0
@@ -50,6 +50,9 @@#include <asm/vgtod.h> #include <asm/traps.h> +#define CREATE_TRACE_POINTS +#include "vsyscall_trace.h" +DEFINE_VVAR (int, vgetcpu_mode); DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) = {
@@ -146,6 +149,9 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)* and int 0xcc is two bytes long. */ vsyscall_nr =addr_to_vsyscall_nr (regs->ip -2 ); + +trace_emulate_vsyscall (vsyscall_nr); +if (vsyscall_nr <0 ) {warn_bad_vsyscall (KERN_WARNING , regs,"illegal int 0xcc (exploit attempt?)" );
arch/x86/kernel/vsyscall_trace.h new file +29 -0
@@ -0,0 +1,29 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM vsyscall + +#if !defined(__VSYSCALL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ ) +#define __VSYSCALL_TRACE_H + +#include <linux/tracepoint.h> + +TRACE_EVENT (emulate_vsyscall, + + TP_PROTO(int nr), + +TP_ARGS (nr), + +TP_STRUCT__entry (__field (int, nr)), + +TP_fast_assign ( + __entry->nr = nr; + ), + +TP_printk ("nr = %d" , __entry->nr) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../arch/x86/kernel +#define TRACE_INCLUDE_FILE vsyscall_trace +#include <trace/define_trace.h>
Quoted 11 lines · Andrew Lutomirski
Quoted 9 lines · Konrad Rzeszutek Wilk
Quoted 8 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
Quoted 6 lines
Quoted 5 lines
Quoted 1 line
Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
I put them on the To list for you.
Are you sure about that coffee? I'm pretty sure I had [email protected] in there.
What's the state of this series? Has tip.git picked it up, or does it need another go-around?
I just booted a Linus tree and got a backtrace that looks like this issue, though I haven't looked into it in detail yet.
Thanks,
J
Quoted 11 lines · Andrew Lutomirski
Quoted 9 lines · Konrad Rzeszutek Wilk
Quoted 8 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)
Quoted 6 lines
Quoted 5 lines
Quoted 1 line
Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
I put them on the To list for you.
Are you sure about that coffee? I'm pretty sure I had [email protected] in there.
What's the state of this series? Has tip.git picked it up, or does it need another go-around?
I just booted a Linus tree and got a backtrace that looks like this issue, though I haven't looked into it in detail yet.
Thanks,
J
Quoted 16 lines · Jeremy Fitzhardinge
Quoted 15 lines · Andrew Lutomirski
Quoted 13 lines · Konrad Rzeszutek Wilk
Quoted 9 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
Quoted 8 lines
Quoted 2 lines
Quoted 1 line
I put them on the To list for you.
Are you sure about that coffee? I'm pretty sure I had [email protected] in there.
What's the state of this series? Has tip.git picked it up, or does it need another go-around?
I just booted a Linus tree and got a backtrace that looks like this issue, though I haven't looked into it in detail yet.
It's in tip/x86/vdso. I don't know it's status on the way from there to -linus.
--Andy
Quoted 16 lines · Jeremy Fitzhardinge
Quoted 15 lines · Andrew Lutomirski
Quoted 13 lines · Konrad Rzeszutek Wilk
Quoted 9 lines · Konrad Rzeszutek Wilk
Quoted 7 lines · Andy Lutomirski
This fixes various problems that cropped up with the vdso patches.
- Patch 1 fixes an information leak to userspace.
- Patches 2 and 3 fix the kernel build on gold.
- Patches 4 and 5 fix Xen (I hope).
- Patch 6 (optional) adds a trace event to vsyscall emulation. It will make it easier to handle performance regression reports :)Hm, you seemed to have the x86 maintainers on your email..
I definitly need some coffee. What I meant was that you missing putting the x86 maintainers on this patchset. They are the ones that will handle this.
Quoted 8 lines
Quoted 2 lines
Quoted 1 line
I put them on the To list for you.
Are you sure about that coffee? I'm pretty sure I had [email protected] in there.
What's the state of this series? Has tip.git picked it up, or does it need another go-around?
I just booted a Linus tree and got a backtrace that looks like this issue, though I haven't looked into it in detail yet.
It's in tip/x86/vdso. I don't know it's status on the way from there to -linus.
--Andy