x86: enforce DPL checking on task gate switches invoked through IDT
PATCH 1/1 x86: enforce DPL checking on task gate switches invoked through IDT
Hi,
x86 software emulation (non-KVM mode) does not check privilege levels on task gate switches ... so one can invoke a kernel's double fault handler from user space -- very bad.
Expected behaviour (testcase works with any linux distribution + gcc):
$ cat test.c
int main(void)
{
__asm__ volatile ("int $8");
}
$ gcc test.c
$ ./a.out
Segmentation fault
$
... and not a kernel panic (double fault)Forgive me for sending this patch as attachment, I'm not used to git.
Best Regards,
Alex
x86 software emulation (non-KVM mode) does not check privilege levels on task gate switches ... so one can invoke a kernel's double fault handler from user space.
Signed-off-by Alex Zuepke <[email protected]>
target-i386/seg_helper.c +5 -2
@@ -578,12 +578,17 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int, e2 =cpu_ldl_kernel (env, ptr +4 );/* check gate type */ type = (e2 >>DESC_TYPE_SHIFT ) &0x1f ; + dpl = (e2 >>DESC_DPL_SHIFT ) &3 ; + cpl = env->hflags &HF_CPL_MASK ;switch (type) {case 5 :/* task gate */ /* must do that check here to return the correct error code */ if (!(e2 &DESC_P_MASK )) {raise_exception_err (env,EXCP0B_NOSEG , intno *8 +2 ); } +/* check privilege if software int */ +if (is_int && dpl < cpl) +raise_exception_err (env,EXCP0D_GPF , intno *8 +2 );switch_tss (env, intno *8 , e1, e2,SWITCH_TSS_CALL , old_eip);if (has_error_code) {int type;
@@ -616,8 +621,6 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,raise_exception_err (env,EXCP0D_GPF , intno *8 +2 );break ; } - dpl = (e2 >>DESC_DPL_SHIFT ) &3 ; - cpl = env->hflags &HF_CPL_MASK ;/* check privilege if software int */ if (is_int && dpl < cpl) {raise_exception_err (env,EXCP0D_GPF , intno *8 +2 );