diff options
author | Michael Brown | 2016-03-12 13:39:17 +0100 |
---|---|---|
committer | Michael Brown | 2016-03-12 13:39:17 +0100 |
commit | cc9f31ee0cfd4ef9cf05ef0621fc933814489b3d (patch) | |
tree | 8ddce36152aa0ade33b80aba9f451770025ce5ce | |
parent | [arp] Validate length of ARP packet (diff) | |
download | ipxe-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>
-rw-r--r-- | src/arch/x86/transitions/librm.S | 4 |
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 ) |