[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <55E7774F.6060907@list.ru>
Date: Thu, 3 Sep 2015 01:25:19 +0300
From: Stas Sergeev <stsp@...t.ru>
To: Andy Lutomirski <luto@...capital.net>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>,
Raymond Jennings <shentino@...il.com>,
Cyrill Gorcunov <gorcunov@...il.com>,
Pavel Emelyanov <xemul@...allels.com>,
Linux kernel <linux-kernel@...r.kernel.org>
Subject: Re: [regression] x86/signal/64: Fix SS handling for signals delivered
to 64-bit programs breaks dosemu
03.09.2015 00:39, Andy Lutomirski пишет:
> On Wed, Sep 2, 2015 at 2:01 PM, Stas Sergeev <stsp@...t.ru> wrote:
>> 02.09.2015 22:06, Andy Lutomirski пишет:
>>
>>> On Wed, Sep 2, 2015 at 11:23 AM, Stas Sergeev <stsp@...t.ru> wrote:
>>>> 02.09.2015 21:17, Andy Lutomirski пишет:
>>>>> On Wed, Sep 2, 2015 at 10:46 AM, Stas Sergeev <stsp@...t.ru> wrote:
>>>>>> 02.09.2015 17:21, Andy Lutomirski пишет:
>>>>>>>>> This should work for old DOSEMU. It's a bit gross, but it has the
>>>>>>>>> nice benefit that everyone (even things that aren't DOSEMU) gain the
>>>>>>>>> ability to catch signals thrown from bogus SS contexts, which
>>>>>>>>> probably
>>>>>>>>> improves debugability. It's also nice to not have the SA flag.
>>>>>>>> Pros:
>>>>>>>> - No new SA flag
>>>>>>>> - May improve debugability in some unknown scenario where people
>>>>>>>> do not want to just use the new flag to get their things improved
>>>>>>>>
>>>>>>>> Cons:
>>>>>>>> - Does not allow to cleanly use siglongjmp(), as then there is a risk
>>>>>>>> to jump to 64bit code with bad SS
>>>>>>> What's the issue here? I don't understand.
>>>>>>>
>>>>>>> On musl, (sig)longjmp just restores rsp, rbx, rbp, and r12-r15, so it
>>>>>>> won't be affected. AFAIK all implementations of siglongjmp are likely
>>>>>>> to call sigprocmask or similar, and that will clobber SS. I'm not
>>>>>>> aware of an implementation of siglongjmp that uses sigreturn.
>>>>>> I am not saying siglongjmp() will be affected.
>>>>>> Quite the opposite: it won't, which is bad. :)
>>>>>> If you have always correct SS, you can use siglongjmp(). If you have
>>>>>> broken SS at times, siglongjmp() will be an asking for troubles, as
>>>>>> it exactly does not restore SS.
>>>>>> dosemu could do a good use of siglongjmp() to get back to 64bit code
>>>>>> from its sighandler.
>>>>> This seems like it would be relying unpleasantly heavily on libc
>>>>> internals.
>>>> Could you please clarify?
>>>> If kernel always passes the right SS to the sighandler, then what's
>>>> the problem?
>>> What's the exact siglongjmp usage you have in mind? Signal context
>>> isn't normally involved AFAIK.
>> dosemu needs 2 return pathes:
>> 1. to DOS code
>> 2. to 64bit code (dosemu is not all in a sighandler, right?)
>>
>> How it is currently achieved:
>> dosemu1:
>> 1. sigreturn() + iret (to DOS)
>> 2. modify sigcontext -> sigreturn() (to 64bit asm helper)
>>
>> dosemu2:
>> 1. sigreturn() + iret (to DOS)
>> 2. modify sigcontext -> sigreturn() -> longjmp() (to 64bit C-coded)
> So you're modifying sigcontext such that it returns to a C function
> that calls longjmp?
Yes.
>> How dosemu2 is supposed to do this:
>> 1. sigreturn() (to DOS)
>> 2. siglongjmp() (to 64bit C-coded)
> This should work fine on any kernel, right?
1 - not.
2 - maybe.
If, as you say, siglongjmp() restores SS, I need to try it out.
(there is also a problem that most siglongjmp() implementations
are incompatible with sigaltstack(), but this is not what you can fix).
> The main problem will be
> that you presumably need to remember the old context so you can go
> back to DOS, I assume. So SS needs to be there somewhere.
Its fine if you always save SS to sigcontext.
This is what you proposed already and I think its fine.
dosemu saves entire sigcontext before going out to 64bit.
>>>>>>>> Is the new SA flag such a big deal here to even bother?
>>>>>>> Not really, but given that the new behavior seems clearly better
>>>>>>> behaved than the old, it would be nice to be able to have the good
>>>>>>> behavior, or at least most of it, be the default.
>>>>>> Surely, but how about then having the heuristics you suggest,
>>>>>> only if the new SA_hyz is not set? And when it is set, have a
>>>>>> properly defined and predictable behaviour. Then it seems like
>>>>>> we'll get all the possible wishes covered.
>>>>> That could work. The result is quite similar to explicitly setting
>>>>> UC_STRICT_RESTORE_SS.
>>>> I am much more bothered with delivering the right SS than with
>>>> restoring it on sigreturn().
>>> For 64-bit delivery, ignoring backwards compatibility, delivering
>>> signals with ss = __USER_DS would be the right solution, I think: it's
>>> trivial and it works. Because of backwards compatibility, we need to
>> ... add the SA_hyz flag.
>> I don't understand why do you constantly ignore that part as
>> if it was never spelled. Lets discuss the proposal as a whole, rather
>> than with the random bits thrown away. The flag is exactly for
>> backward compatibility, so why do you present it as a problem
>> without the context of the new flag?
> For backwards compat, we either need the default behavior to be
> unchanged, or we need the default behavior to be something that works
> with existing dosemu. For existing dosemu, the only interesting cases
> (I think) are signal delivery from *valid* 16-bit context, in which
> case we need to preserve SS so that the signal handler can read it out
> with mov ..., %ss, and sigreturn to 64-bit mode for the IRET
> trampoline. For sigreturn, IIUC old dosemu will replace the saved CS
> with a 64-bit code segment selector and won't touch the saved SS
> because it doesn't know about the saved SS. Those dosemu versions
> don't care what SS actually contains after sigreturn, because they're
> immediately going to change it again using IRET. So we just need to
> make sure we return without faulting.
>
> New dosemu2 would like to sigreturn directly back to 16-bit mode, so
> it needs the kernel to honor the saved ss value and restore it,
> possibly changed by dosemu.
>
> We obviously can't require old dosemu to set an SA flag to keep
> working. But, if we can get away with it, I think it's somewhat
> preferable not to require new DOSEMU to set an SA flag either.
>
> This has one major benefit at least: if new dosemu loads some random
> library that installs some async signal handler (SIGALRM for example),
> everything will work with regard to CS and SS.
This case is covered if we do both things together: use
your heuristic when SA_hyz is not set, and don't use it
when its set. In this case dosemu2 will be able to request
the proper SS delivery for its sighandlers, but the 3rd-party
sighandlers will work too.
I think we have never discussed the possibility of doing
both things together, even though I have proposed it many
times.
After discussing this full-blown solution, we can think about
reducing it, either by removing the heuristic or by removing
SA_hyz, but discussing the full one would be nice too.
Your opinion is likely that no one will use this SA_hyz in
presence of the heuristic that "seems to work anyway".
But in the light of extending it for TLS (with a new flag),
I wouldn't be so sure. You can also document it as a
needed flag when user code touches SS, and then it will
be used. dosemu1 code that doesn't use it, will eventually
be forgotten. So IMHO whether it will be used, is fully up
to how will you market it. :)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists