From a35d07a831f32ecea104b0d9cc97fbedf6018a20 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 18:38:11 +0000 Subject: [PATCH] Handle a case when non-canonical address is loaded into the fsbase or gsbase MSR. MFC after: 3 days --- sys/amd64/amd64/exception.S | 30 ++++++++++++++++++++++++++++-- sys/amd64/amd64/trap.c | 8 ++++++++ sys/amd64/include/md_var.h | 4 ++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 3d6401e3cd04..bbc304a48d61 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -668,7 +668,8 @@ ld_fs: movw %ax,%fs movl $MSR_FSBASE,%ecx movl PCB_FSBASE(%r8),%eax movl PCB_FSBASE+4(%r8),%edx - wrmsr + .globl ld_fsbase +ld_fsbase: wrmsr 1: /* Restore %gs and gsbase */ movw TF_GS(%rsp),%si @@ -685,7 +686,8 @@ ld_gs: movw %si,%gs movl $MSR_KGSBASE,%ecx movl PCB_GSBASE(%r8),%eax movl PCB_GSBASE+4(%r8),%edx - wrmsr + .globl ld_gsbase +ld_gsbase: wrmsr 1: .globl ld_es ld_es: movw TF_ES(%rsp),%es .globl ld_ds @@ -798,6 +800,30 @@ gs_load_fault: call trap movw $KUG32SEL,TF_GS(%rsp) jmp doreti + + ALIGN_TEXT + .globl fsbase_load_fault +fsbase_load_fault: + movl $T_PROTFLT,TF_TRAPNO(%rsp) + movq %rsp, %rdi + call trap + movq PCPU(CURTHREAD),%r8 + movq TD_PCB(%r8),%r8 + movq $0,PCB_FSBASE(%r8) + jmp doreti + + ALIGN_TEXT + .globl gsbase_load_fault +gsbase_load_fault: + popfq + movl $T_PROTFLT,TF_TRAPNO(%rsp) + movq %rsp, %rdi + call trap + movq PCPU(CURTHREAD),%r8 + movq TD_PCB(%r8),%r8 + movq $0,PCB_GSBASE(%r8) + jmp doreti + #ifdef HWPMC_HOOKS ENTRY(end_exceptions) #endif diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index bd7ee6358969..a1cb75a9d5b8 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -566,6 +566,14 @@ trap(struct trapframe *frame) frame->tf_gs = _ugssel; goto out; } + if (frame->tf_rip == (long)ld_gsbase) { + frame->tf_rip = (long)gsbase_load_fault; + goto out; + } + if (frame->tf_rip == (long)ld_fsbase) { + frame->tf_rip = (long)fsbase_load_fault; + goto out; + } if (PCPU_GET(curpcb)->pcb_onfault != NULL) { frame->tf_rip = (long)PCPU_GET(curpcb)->pcb_onfault; diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 2b43b37cc184..88f3e1dbaed8 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -83,10 +83,14 @@ void ld_ds(void) __asm(__STRING(ld_ds)); void ld_es(void) __asm(__STRING(ld_es)); void ld_fs(void) __asm(__STRING(ld_fs)); void ld_gs(void) __asm(__STRING(ld_gs)); +void ld_fsbase(void) __asm(__STRING(ld_fsbase)); +void ld_gsbase(void) __asm(__STRING(ld_gsbase)); void ds_load_fault(void) __asm(__STRING(ds_load_fault)); void es_load_fault(void) __asm(__STRING(es_load_fault)); void fs_load_fault(void) __asm(__STRING(fs_load_fault)); void gs_load_fault(void) __asm(__STRING(gs_load_fault)); +void fsbase_load_fault(void) __asm(__STRING(fsbase_load_fault)); +void gsbase_load_fault(void) __asm(__STRING(gsbase_load_fault)); void dump_add_page(vm_paddr_t); void dump_drop_page(vm_paddr_t); void initializecpu(void);