b50f8e42ba
If longjmp restores the stack frame to an address which is beyond the stack frame at the time of the longjmp call it would install an uninitialized stack frame. If compiled with _FORTIFY_SOURCE defined, longjmp will now bail out in this situation.
87 lines
1.3 KiB
C
87 lines
1.3 KiB
C
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <paths.h>
|
|
#include <setjmp.h>
|
|
#include <signal.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
static jmp_buf b;
|
|
|
|
|
|
static void
|
|
__attribute__ ((noinline))
|
|
f (void)
|
|
{
|
|
char buf[1000];
|
|
asm volatile ("" : "=m" (buf));
|
|
|
|
if (setjmp (b) != 0)
|
|
{
|
|
puts ("second longjmp succeeded");
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
|
|
static bool expected_to_fail;
|
|
|
|
|
|
static void
|
|
handler (int sig)
|
|
{
|
|
if (expected_to_fail)
|
|
_exit (0);
|
|
else
|
|
{
|
|
static const char msg[] = "unexpected longjmp failure\n";
|
|
TEMP_FAILURE_RETRY (write (STDOUT_FILENO, msg, sizeof (msg) - 1));
|
|
_exit (1);
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
struct sigaction sa;
|
|
sa.sa_handler = handler;
|
|
sa.sa_flags = 0;
|
|
sigemptyset (&sa.sa_mask);
|
|
|
|
sigaction (SIGABRT, &sa, NULL);
|
|
|
|
/* Avoid all the buffer overflow messages on stderr. */
|
|
int fd = open (_PATH_DEVNULL, O_WRONLY);
|
|
if (fd == -1)
|
|
close (STDERR_FILENO);
|
|
else
|
|
{
|
|
dup2 (fd, STDERR_FILENO);
|
|
close (fd);
|
|
}
|
|
setenv ("LIBC_FATAL_STDERR_", "1", 1);
|
|
|
|
|
|
expected_to_fail = false;
|
|
|
|
if (setjmp (b) == 0)
|
|
{
|
|
longjmp (b, 1);
|
|
/* NOTREACHED */
|
|
printf ("first longjmp returned\n");
|
|
return 1;
|
|
}
|
|
|
|
|
|
expected_to_fail = true;
|
|
|
|
f ();
|
|
longjmp (b, 1);
|
|
|
|
puts ("second longjmp returned");
|
|
return 1;
|
|
}
|