Skip to content

Instantly share code, notes, and snippets.

@azat
Created June 19, 2021 13:49
Show Gist options
  • Save azat/2ee360fd4f2828d363b0926431afacc6 to your computer and use it in GitHub Desktop.
Save azat/2ee360fd4f2828d363b0926431afacc6 to your computer and use it in GitHub Desktop.
/// Test case for alternative stack overflow in TLS
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <csignal>
#include <cassert>
#include <string>
#include <algorithm>
#include <thread>
static_assert(MINSIGSTKSZ == 2048);
alignas(4096) static thread_local char alt_stack[2048];
static thread_local char data_char[512];
static thread_local int data_int;
void handler(int sig, siginfo_t *, void *)
{
signal(sig, SIG_DFL);
/// This will overflow alt_stack, and overwrite other variables in TLS
char local_data_char[4096];
memset(local_data_char, 'B', sizeof(local_data_char));
assert(data_int == 1);
assert(std::find_if_not(data_char, data_char+sizeof(data_char), [](char a) { return a == 'A'; }) == data_char+sizeof(data_char));
_Exit(0);
}
int main()
{
std::thread thread([]() {
stack_t altstack{};
altstack.ss_sp = alt_stack;
altstack.ss_size = sizeof(alt_stack);
if (sigaltstack(&altstack, NULL))
perror("sigaltstack");
struct sigaction sa{};
sa.sa_sigaction = handler;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
if (sigaddset(&sa.sa_mask, SIGSEGV))
perror("sigaddset");
if (sigaction(SIGSEGV, &sa, NULL))
perror("sigaction");
if (sigaction(SIGSEGV, NULL, &sa))
perror("sigaction");
assert(sa.sa_flags & SA_ONSTACK);
data_int = 1;
memset(data_char, 'A', sizeof(data_char));
*(volatile char *)NULL = 0;
});
thread.join();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment