Honestly, I am not sure I understand what this patch does and why, and it isArrr.
white space damaged, please fix.
On 01/31, Stas Sergeev wrote:Yes.
linux implements the sigaltstack() in a way that makes it impossible toSo iiuc you want to switch the stack from the signal handler running on the
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 temporarily disable sigaltstack with SS_DISABLE.
You can't use swapcontext() without disabling sigaltstack first, or the
stack will be re-used and overwritten by a subsequent signal.
alt stack, and you need to ensure that another SA_ONSTACK signal won't corrupt
the alt stack in between, right?
Perhaps you can update the changelog to explain why do we want this change.Beyond the fact that swapcontext() is then usable for switching
Yes.@@ -2550,8 +2551,11 @@ static inline int sas_ss_flags(unsigned long sp)So this always return SS_ONSTACK if on_sig_stack(), see below.
{
if (!current->sas_ss_size)
return SS_DISABLE;
-
- return on_sig_stack(sp) ? SS_ONSTACK : 0;
+ if (on_sig_stack(sp))
+ return SS_ONSTACK;
+ if (current->sas_ss_flags == SS_DISABLE)
+ return SS_DISABLE;
+ return 0;
+ onsigstack = on_sig_stack(sp);and iiuc the "default" case allows you to write SS_DISABLE into ->sas_ss_flags
+ if (ss_size == 0) {
+ switch (ss_flags) {
+ case 0:
+ error = -EPERM;
+ if (onsigstack)
+ goto out;
+ current->sas_ss_sp = 0;
+ current->sas_ss_size = 0;
+ current->sas_ss_flags = SS_DISABLE;
+ break;
+ case SS_ONSTACK:
+ /* re-enable previously disabled sas */
+ error = -EINVAL;
+ if (current->sas_ss_size == 0)
+ goto out;
+ break;
+ default:
+ break;
+ }
even if on_sig_stack().
So the sequence is
// running on alt stack
sigaltstack(SS_DISABLE);
temporary_run_on_another_stack();
sigaltstack(SS_ONSTACK);
and SS_DISABLE saves us from another SA_ONSTACK signal, right?
But afaics it can only help after we change the stack. Suppose that SA_ONSTACK signalI don't think so. Please see the following hunk:
comess before temporary_run_on_another_stack(). get_sigframe() should be fine after
your changes (afaics), it won't pick the alt stack after SS_DISABLE.
However, unless I missed something save_altstack_ex() will record SS_ONSTACK in
uc_stack->ss_flags, and after return from signal handler restore_altstack() will
enable alt stack again?