2004-10-30 20:22:25

by Stas Sergeev

[permalink] [raw]
Subject: [patch] i386: restore ESP value on return to userspace

Hi Andrew.

There is a bug in Intel CPUs, which is described here:
http://www.intel.com/design/intarch/specupdt/27287402.PDF
"ISSUE: When a 32-bit IRET is used to return to another privilege level,
and the old level uses a 4G stack (D/B bit in the segment register = 1),
while the new level uses a 64k stack (D/B bit = 0), then only the
lower word of ESP is updated."

This CPU bug hurts the projects like dosemu
and wine, and it can be worked around only
in kernel. Also, as suggested by Pavel Machek,
exporting the high word of kernel's stack
pointer to userspace is an "information leak".
The complete discussion can be found here:
http://groups.google.com/groups?hl=ru&lr=&frame=right&th=f5709268cf83e2da&seekm=2F8IB-7P0-31%40gated-at.bofh.it#link1

Attached patch checks if the userspace
process uses the "small" stack, and if it
does, then kernel switches to the "small"
stack itself and preloads the user's value
into a high word of %esp.
Additional care is taken to switch back to
32bit stack in case of an exception or NMI
while on a 16bit stack in kernel.

Acked-by: Petr Vandrovec <[email protected]>
Signed-off-by: Stas Sergeev <[email protected]>

< End of description >

Andrew, can this please be applied?

Actually, there are two diffs attached.
I was confused by reading this:
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
3.b says that I should *not* specify the
kernel version against which the patch is
made, while 4.c implies that this info is
actually needed, because the patch can be
done against the Linus tree and/or -mm tree.
Also 4.c encourages to make the patches
against the Linus tree (which I find strange)
even if there are rejects with -mm, because
you say you'll work out the rejects yourself.
But my patch is slightly different for Linus
and -mm trees, so resolving the rejects may
not work.
To work around all that confusion, I attached
patches for both trees and hardcoded the kernel
versions into diff file names. Hope this will
do the trick.


Attachments:
linux-2.6.10-rc1-mm2-stk0-1.diff (7.66 kB)
linux-2.6.10-rc1-stk0-1.diff (7.40 kB)
Download all attachments