Browse Source

[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>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
cc9f31ee0c
1 changed files with 2 additions and 2 deletions
  1. 2
    2
      src/arch/x86/transitions/librm.S

+ 2
- 2
src/arch/x86/transitions/librm.S View File

@@ -940,7 +940,7 @@ VC_OFFSET_END:
940 940
 	.globl virt_call
941 941
 virt_call:
942 942
 	/* Preserve registers, flags and GDT on external RM stack */
943
-	pushfw	/* padding */
943
+	pushw	%ss /* padding */
944 944
 	pushfl
945 945
 	pushal
946 946
 	pushw	%gs
@@ -1030,7 +1030,7 @@ vc_rmode:
1030 1030
 	 */
1031 1031
 	addr32 movl -20(%esp), %esp
1032 1032
 	popfl
1033
-	popfw	/* padding */
1033
+	popw	%ss /* padding */
1034 1034
 
1035 1035
 	/* Return and discard function parameters */
1036 1036
 	ret	$( VC_OFFSET_END - VC_OFFSET_PARAMS )

Loading…
Cancel
Save