lkml.org 
[lkml]   [2016]   [Jan]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: sigaltstack breaks swapcontext()
From
Date
06.01.2016 21:05, Andy Lutomirski пишет:
> On Wed, Jan 6, 2016 at 7:45 AM, Stas Sergeev <stsp@list.ru> wrote:
>> Hello.
>>
>> swapcontext() can be used with signal handlers,
>> it swaps the signal masks together with the other
>> parts of the context.
>> Unfortunately, linux implements the sigaltstack()
>> in a way that makes it impossible to use with
>> swapcontext().
>> Per the man page, sigaltstack is allowed to return
>> EPERM if the process is altering its sigaltstack while
>> running on sigaltstack. This is likely needed to
>> consistently return oss->ss_flags, that indicates
>> whether the process is being on sigaltstack or not.
>> Unfortunately, linux takes that permission to return
>> EPERM too literally: it returns EPERM even if you
>> don't want to change to another sigaltstack, but
>> only want to disable sigaltstack with SS_DISABLE.
>> To my reading of a man page, this is not a desired
>> behaviour. Moreover, you can't use swapcontext()
>> without disabling sigaltstack first, or the stack will
>> be re-used and overwritten by a subsequent signal.
>>
> The EPERM thing is probably also to preserve the behavior that nested
> SA_ONSTACK signals are supposed to work.
Could you please clarify?
If I set up another stack inside the sighandler, the
nested SA_ONSTACK signal can just use that new stack,
which seems safe and sane. So I don't think EPERM helps
the nested signals, or could you explain the possible breakage
scenario?

>> The work-around from this, is not even trivial: I have
>> to use the shm tricks to duplicate the sigaltstack in
>> the VA space, and move the stack pointer to another
>> mirror before calling sigaltstack. Then I use longjmp()
>> to restore the stack pointer. Then I can finally use
>> swapcontext(). This is an unpleasant work-around.
>>
>> The fix on a kernel side looks simple: kernel should
>> just use ss_flags to determine whether the sigaltstack
>> is active. I can make a patch for that, but the problem
>> is that the arch-specific code is not using any helper
>> function to check for sigaltstack; instead it just uses
>> "if (ss_size)" checks.
> Huh? I'm not sure I understand what you're talking about. It seems
> reasonable to have the invariant that ss_size != 0 if and only if an
> alt stack is enabled, and do_sigaltstack seems to enforce that
> invariant.
But we have that (IMO quite silly) requirement that the
returned oss->ss_flags is consistent.
So if inside the signal handler I use SS_DISABLE and
the kernel translates this into "ss_size = 0", the next
call to sigaltstack() will return 0 in oss->ss_flags.

>> So the patch will need to update
>> all arches... I wonder if maybe someone can fix that
>> problem and update the arch-specific code. If not,
>> I'll probably need to update only the x86-specific code
>> and add an arch-specific define, which is a bit nasty.
> Just change do_sigaltstack?
But if its that easy and we do not even need a consistent
oss->ss_flags - why not to remove the EPERM check entirely,
rather than only for SS_DISABLE? Note that if it is removed
only for SS_DISABLE and yet SS_DISABLE is translated to
"ss_size=0", then by the next sigaltstack() call you can do
whatever you want: the EPERM check will be entirely bypassed.
So if you are fine with even this, I can send the patch to
completely remove the check. Much easier for me. :)
I think the semantic of oss->ss_size is quite bad, but it is
already documented, so I am not sure.


\
 
 \ /
  Last update: 2016-01-06 20:01    [W:0.330 / U:0.108 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site