From 66bdab40af557354c85079ccf91657cacd7acab2 Mon Sep 17 00:00:00 2001 From: Sir Richard Date: Tue, 2 Feb 2010 22:56:13 +0000 Subject: [PATCH] [NTOS]: Yet another fix for KiEnterInterruptTrap: Set correct DS/ES before touching the TrapFrame. [NTOS]: Make this operation an inline so any possible future code will not make this mistake twice. Thanks to Physicus for the bug report. svn path=/trunk/; revision=45381 --- reactos/ntoskrnl/include/internal/trap_x.h | 59 +++++++++++----------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/trap_x.h b/reactos/ntoskrnl/include/internal/trap_x.h index b89989ffc23..9fe6b1852c4 100644 --- a/reactos/ntoskrnl/include/internal/trap_x.h +++ b/reactos/ntoskrnl/include/internal/trap_x.h @@ -490,7 +490,31 @@ KiUserSystemCall(IN PKTRAP_FRAME TrapFrame) : "r"(TrapFrame->SegCs) ); } - + +VOID +FORCEINLINE +KiSetSaneSegments(IN PKTRAP_FRAME TrapFrame) +{ + ULONG Ds, Es; + + /* + * We really have to get a good DS/ES first before touching any data. + * + * These two reads will either go in a register (with optimizations ON) or + * a stack variable (which is on SS:ESP, guaranteed to be good/valid). + * + * Because the assembly is marked volatile, the order of instructions is + * as-is, otherwise the optimizer could simply get rid of our DS/ES. + * + */ + Ds = Ke386GetDs(); + Es = Ke386GetEs(); + Ke386SetDs(KGDT_R3_DATA | RPL_MASK); + Ke386SetEs(KGDT_R3_DATA | RPL_MASK); + TrapFrame->SegDs = Ds; + TrapFrame->SegEs = Es; +} + // // Generic Exit Routine // @@ -700,8 +724,6 @@ VOID FORCEINLINE KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame) { - ULONG Ds, Es; - /* Check for V86 mode, otherwise check for ring 3 code */ if (__builtin_expect(KiIsV8086TrapSafe(TrapFrame), 0)) { @@ -718,14 +740,9 @@ KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame) } else if (__builtin_expect(KiIsUserTrapSafe(TrapFrame), 1)) /* Ring 3 is more common */ { - /* Save DS/ES and load correct values */ - Es = Ke386GetEs(); - Ds = Ke386GetDs(); - TrapFrame->SegDs = Ds; - TrapFrame->SegEs = Es; - Ke386SetDs(KGDT_R3_DATA | RPL_MASK); - Ke386SetEs(KGDT_R3_DATA | RPL_MASK); - + /* Switch to sane segments */ + KiSetSaneSegments(TrapFrame); + /* Save FS/GS */ TrapFrame->SegFs = Ke386GetFs(); TrapFrame->SegGs = Ke386GetGs(); @@ -760,24 +777,8 @@ VOID FORCEINLINE KiEnterTrap(IN PKTRAP_FRAME TrapFrame) { - ULONG Ds, Es; - - /* - * We really have to get a good DS/ES first before touching any data. - * - * These two reads will either go in a register (with optimizations ON) or - * a stack variable (which is on SS:ESP, guaranteed to be good/valid). - * - * Because the assembly is marked volatile, the order of instructions is - * as-is, otherwise the optimizer could simply get rid of our DS/ES. - * - */ - Ds = Ke386GetDs(); - Es = Ke386GetEs(); - Ke386SetDs(KGDT_R3_DATA | RPL_MASK); - Ke386SetEs(KGDT_R3_DATA | RPL_MASK); - TrapFrame->SegDs = Ds; - TrapFrame->SegEs = Es; + /* Switch to sane segments */ + KiSetSaneSegments(TrapFrame); /* Now we can save the other segments and then switch to the correct FS */ TrapFrame->SegFs = Ke386GetFs();