From b504253645b901b016d91b31b81f679bfe75ecce Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Thu, 24 Apr 2008 19:34:01 +0000 Subject: [PATCH] Added canonical check for LIDT/LGDT instructions in 64-bit mode --- bochs/cpu/protect_ctrl.cc | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/bochs/cpu/protect_ctrl.cc b/bochs/cpu/protect_ctrl.cc index 7d98898d5..209eb29ee 100644 --- a/bochs/cpu/protect_ctrl.cc +++ b/bochs/cpu/protect_ctrl.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: protect_ctrl.cc,v 1.80 2008-04-22 22:05:38 sshwarts Exp $ +// $Id: protect_ctrl.cc,v 1.81 2008-04-24 19:34:01 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -658,8 +658,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT_Ms(bxInstruction_c *i) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); - write_virtual_word(i->seg(), RMAddr(i), limit_16); write_virtual_dword(i->seg(), RMAddr(i)+2, base_32); + write_virtual_word(i->seg(), RMAddr(i), limit_16); } void BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT_Ms(bxInstruction_c *i) @@ -714,8 +714,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT_Ms(bxInstruction_c *i) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); - Bit16u limit_16 = read_virtual_word(i->seg(), RMAddr(i)); Bit32u base_32 = read_virtual_dword(i->seg(), RMAddr(i) + 2); + Bit16u limit_16 = read_virtual_word(i->seg(), RMAddr(i)); if (i->os32L() == 0) base_32 &= 0x00ffffff; /* ignore upper 8 bits */ @@ -727,29 +727,33 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT_Ms(bxInstruction_c *i) void BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT64_Ms(bxInstruction_c *i) { + BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); + Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit; Bit64u base_64 = BX_CPU_THIS_PTR gdtr.base; BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); - write_virtual_word (i->seg(), RMAddr(i), limit_16); write_virtual_qword(i->seg(), RMAddr(i)+2, base_64); + write_virtual_word (i->seg(), RMAddr(i), limit_16); } void BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT64_Ms(bxInstruction_c *i) { + BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); + Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit; Bit64u base_64 = BX_CPU_THIS_PTR idtr.base; BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); - write_virtual_word(i->seg(), RMAddr(i), limit_16); write_virtual_qword(i->seg(), RMAddr(i)+2, base_64); + write_virtual_word(i->seg(), RMAddr(i), limit_16); } void BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT64_Ms(bxInstruction_c *i) { - BX_ASSERT(protected_mode()); + BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); if (CPL!=0) { BX_ERROR(("LGDT64_Ms: CPL != 0 in long mode")); @@ -760,8 +764,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT64_Ms(bxInstruction_c *i) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); - Bit16u limit_16 = read_virtual_word(i->seg(), RMAddr(i)); Bit64u base_64 = read_virtual_qword(i->seg(), RMAddr(i) + 2); + if (! IsCanonical(base_64)) { + BX_ERROR(("LGDT64_Ms: loaded base64 address is not in canonical form!")); + exception(BX_GP_EXCEPTION, 0, 0); + } + Bit16u limit_16 = read_virtual_word(i->seg(), RMAddr(i)); BX_CPU_THIS_PTR gdtr.limit = limit_16; BX_CPU_THIS_PTR gdtr.base = base_64; @@ -769,7 +777,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT64_Ms(bxInstruction_c *i) void BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT64_Ms(bxInstruction_c *i) { - BX_ASSERT(protected_mode()); + BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); if (CPL != 0) { BX_ERROR(("LIDT64_Ms: CPL != 0 in long mode")); @@ -780,8 +788,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT64_Ms(bxInstruction_c *i) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); - Bit16u limit_16 = read_virtual_word(i->seg(), RMAddr(i)); Bit64u base_64 = read_virtual_qword(i->seg(), RMAddr(i) + 2); + if (! IsCanonical(base_64)) { + BX_ERROR(("LIDT64_Ms: loaded base64 address is not in canonical form!")); + exception(BX_GP_EXCEPTION, 0, 0); + } + Bit16u limit_16 = read_virtual_word(i->seg(), RMAddr(i)); BX_CPU_THIS_PTR idtr.limit = limit_16; BX_CPU_THIS_PTR idtr.base = base_64;