26.10.2015 04:25, Andy Lutomirski пишет:
This is a second attempt to make the improvements from c6f2062935c8
("x86/signal/64: Fix SS handling for signals delivered to 64-bit
programs"), which was reverted by 51adbfbba5c6 ("x86/signal/64: Add
support for SS in the 64-bit signal context").

This adds two new uc_flags flags.  UC_SIGCONTEXT_SS will be set for
all 64-bit signals (including x32).  It indicates that the saved SS
field is valid and that the kernel supports the new behavior.

The goal is to fix a problems with signal handling in 64-bit tasks:
SS wasn't saved in the 64-bit signal context, making it awkward to
determine what SS was at the time of signal delivery and making it
impossible to return to a non-flat SS (as calling sigreturn clobbers
SS).

This also made it extremely difficult for 64-bit tasks to return to
fully-defined 16-bit contexts, because only the kernel can easily do
espfix64, but sigreturn was unable to load or even restore SS:ESP.
(DOSEMU has a monstrous hack to partially work around this.)

If we could go back in time, the correct fix would be to make 64-bit
signals work just like 32-bit signals with respect to SS: save it
in signal context, reset it when delivering a signal, and restore
it in sigreturn.

Unfortunately, doing that (as I tried originally) breaks DOSEMU:
DOSEMU wouldn't reset the signal context's SS when clearing the LDT
and changing the saved CS to 64-bit mode, since it predates the SS
context field existing in the first place.

This patch is a bit more complicated, and it tries to balance a
bunch of goals.  It makes signal delivery due to a bogus SS reliable
without having to set any flags (64-bit signals will always be
delivered to a valid SS), and it makes most cases of changing
ucontext->ss during signal handling work as expected.

I do this by special-casing the interesting case.  On sigreturn,
ucontext->ss will be honored by default, unless the ucontext was
created from scratch by an old program and had a 64-bit CS
(unfortunately, CRIU can do this) or was the result of changing a
32-bit signal context to 64-bit without resetting SS (as DOSEMU
does).

For the benefit of new 64-bit software that uses segmentation (new
versions of DOSEMU might), the new behavior can be detected with a
new ucontext flag UC_SIGCONTEXT_SS.

To avoid compilation issues, __pad0 is left as an alias for ss in
ucontext.

The nitty-gritty details are documented in the header file.

Cc: Stas Sergeev <s...@list.ru>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Cyrill Gorcunov <gorcu...@gmail.com>
Cc: Pavel Emelyanov <xe...@parallels.com>
Signed-off-by: Andy Lutomirski <l...@kernel.org>
Tested-by: Stas Sergeev <s...@list.ru>

Both dosemu2 and 1 work fine.
Still as this approach seems very risky, I'd appreciate if some
of the explanations from this msg:
https://lkml.org/lkml/2015/10/14/726
go into the code comments.
What I find especially useful are your notes about
siglongjmp(), threads, and the fact that running with bad
SS is now impossible on the recent kernels. Without this
info at hands, no one can trust this code perhaps.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to