NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/57946: longjmp fails to restore stack first before restoring signal mask on most architectures



>Number:         57946
>Category:       lib
>Synopsis:       longjmp fails to restore stack first before restoring signal mask on most architectures
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 19 04:25:01 +0000 2024
>Originator:     Taylor R Campbell
>Release:        current, 10, 9, 8, ...
>Organization:
The NetBSD FoundaSQUIRREL
>Environment:
arm, hppa, i386, ia64, mips, sh3, sparc, sparc64, amd64
>Description:
longjmp(3) is supposed to restore various saved state, including registers, stack pointer, and signal mask, and then come flying out of the corresponding call to setjmp(3).

However, if a signal is already pending, and longjmp(3) restores the signal mask first, the signal handler will be triggered before the stack pointer has been restored -- which means if the signal handler itself called longjmp, it may recursively enter on the signal stack rather than the original stack.
>How-To-Repeat:
// https://www.openwall.com/lists/musl/2024/02/18/16
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

static volatile long cnt = 1000000;
jmp_buf jb;

void handle(int s)
{
      volatile int x;
      if (cnt % 1000 == 0) printf("%p\n", &x);
      if (!cnt--) return;
      raise(s);
      longjmp(jb, 1);
}

int main()
{
      if (setjmp(jb)) return 0;
      signal(SIGALRM, handle);
      raise(SIGALRM);
}

>Fix:
Restore signal mask last in longjmp (and in siglongjmp for the savemask case).



Home | Main Index | Thread Index | Old Index