summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown2016-03-12 13:39:17 +0100
committerMichael Brown2016-03-12 13:39:17 +0100
commitcc9f31ee0cfd4ef9cf05ef0621fc933814489b3d (patch)
tree8ddce36152aa0ade33b80aba9f451770025ce5ce /src/arch
parent[arp] Validate length of ARP packet (diff)
downloadipxe-cc9f31ee0cfd4ef9cf05ef0621fc933814489b3d.tar.gz
ipxe-cc9f31ee0cfd4ef9cf05ef0621fc933814489b3d.tar.xz
ipxe-cc9f31ee0cfd4ef9cf05ef0621fc933814489b3d.zip
[librm] Do not unconditionally preserve flags across virt_call()
Commit 196f0f2 ("[librm] Convert prot_call() to a real-mode near call") introduced a regression in which any deliberate modification to the low 16 bits of the CPU flags (in struct i386_all_regs) would be overwritten with the original flags value at the time of entry to prot_call(). The regression arose because the alignment requirements of the protected-mode stack necessitated the insertion of two bytes of padding immediately below the prot_call() return address. The solution chosen was to extend the existing "pushfl / popfl" pair to "pushfw;pushfl / popfl;popfw". The extra "pushfw / popfw" appears at first glance to be a no-op, but fails to take into account the fact that the flags restored by popfl may have been deliberately modified by the protected-mode function. Fix by replacing "pushfw / popfw" with "pushw %ss / popw %ss". While %ss does appear within struct i386_all_regs, any modification to the stored value has always been ignored by prot_call() anyway. The most visible symptom of this regression was that SAN booting would fail since every INT 13 call would be chained to the original INT 13 vector. Reported-by: Vishvananda Ishaya <vishvananda@gmail.com> Reported-by: Jamie Thompson <forum.ipxe@jamie-thompson.co.uk> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/transitions/librm.S4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/arch/x86/transitions/librm.S b/src/arch/x86/transitions/librm.S
index bb04ad67..3a585a92 100644
--- a/src/arch/x86/transitions/librm.S
+++ b/src/arch/x86/transitions/librm.S
@@ -940,7 +940,7 @@ VC_OFFSET_END:
.globl virt_call
virt_call:
/* Preserve registers, flags and GDT on external RM stack */
- pushfw /* padding */
+ pushw %ss /* padding */
pushfl
pushal
pushw %gs
@@ -1030,7 +1030,7 @@ vc_rmode:
*/
addr32 movl -20(%esp), %esp
popfl
- popfw /* padding */
+ popw %ss /* padding */
/* Return and discard function parameters */
ret $( VC_OFFSET_END - VC_OFFSET_PARAMS )