qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] x86: enforce DPL checking on task gate switches invoked through IDT
@ 2012-08-17 15:30 Alex ZUEPKE
  2012-08-27 16:39 ` Alex ZUEPKE
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Alex ZUEPKE @ 2012-08-17 15:30 UTC (permalink / raw)
  To: qemu-devel

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)


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 <azu@sysgo.com>
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 5fff8d5..23c5542 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -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);

^ permalink raw reply related	[flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH] x86: enforce DPL checking on task gate switches invoked through IDT
@ 2012-08-17  9:14 Alex ZUEPKE
  0 siblings, 0 replies; 6+ messages in thread
From: Alex ZUEPKE @ 2012-08-17  9:14 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 518 bytes --]

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

[-- Attachment #2: x86_task_gate_priv_check.patch --]
[-- Type: text/x-diff, Size: 1558 bytes --]

 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 <azu@sysgo.de>
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 5fff8d5..23c5542 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -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);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-09-01 11:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-17 15:30 [Qemu-devel] [PATCH] x86: enforce DPL checking on task gate switches invoked through IDT Alex ZUEPKE
2012-08-27 16:39 ` Alex ZUEPKE
2012-08-31 16:54 ` Don Slutz
2012-08-31 17:01   ` Peter Maydell
2012-09-01 11:42 ` Blue Swirl
  -- strict thread matches above, loose matches on Subject: below --
2012-08-17  9:14 Alex ZUEPKE

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).