Coordinated Disclosure Timeline
- 2022-11-17: Issue reported to Arm security team
- 2022-11-18: Report acknowledged and sent to relevant team for investigation
- 2022-12-01: Arm was able to confirm and reproduce the issue. The issue appeared to have been fixed internally while fixing a low severity DoS bug and the patch would be included in the r42 branch in the future. However, as this issue is a UAF with a higher vulnerability, Arm informed me that this issue will be assessed with a different severity and CVSS score.
- 2022-12-05: After reviewing the severity, Arm decided to assign a CVE for the issue based on the assessment of a CVSS score of 9.3.
- 2023-01-27: Mali driver version r42, which fixes the issue, is publicly released.
- 2023-02-02: Arm asked for the issue to be embargoed for disclosure until 2023/03/04 to allow users to integrate the update, which we agreed.
- 2023-02-24: Arm informed us that CVE-2022-46395 is assigned to the issue.
- 2023-05-01: Fixed in the Android security bulletin in May.
Summary
Imported memory from user space can be accessed after it has been freed
Product
Arm Mali
Tested Version
x86_64 VM built with Mali driver version r40p0 and Pixel 6 with Patch level: November 2022 Android 13.
Details
Issue: Freed imported user memory can be accessed via vmap in the Arm Mali GPU driver (GHSL-2022-127
)
When importing memory of the type BASE_MEM_IMPORT_TYPE_USER_BUFFER
and the KBASE_REG_SHARE_BOTH
flag is not passed, pages from user space will not be pinned during the creation of the memory region. In this case, the backing pages of the region are pinned when the BASE_JD_REQ_EXTERNAL_RESOURCES
gpu soft job is submitted, during which the user space pages that form the backing pages of the region will have their references increased until the gpu job is completed.
After the backing pages are pinned, the KBASE_IOCTL_STICKY_RESOURCE_MAP
ioctl can be used to call kbase_map_external_resource
to increase the current_mapping_usage_count
of the kbase_alloc_import_user_buf
of the memory region. Then when the BASE_JD_REQ_EXTERNAL_RESOURCES
completes, it’ll decrease the current_mapping_usage_count
by one, instead of dropping its references to the backing pages.
After this, the backing pages can then be freed by using the KBASE_IOCTL_STICKY_RESOURCE_UNMAP
ioctl, which is not protected by the kbase_jd_context::lock
. There are various gpu softjobs where a user supplied gpu address gets vmap
and written to, some of these are protected only by the kbase_jd_context::lock
. For example, in kbase_jit_allocate_process
:
static int kbase_jit_allocate_process(struct kbase_jd_atom *katom)
{
...
for (i = 0, info = katom->softjob_data; i < count; i++, info++) {
u64 entry_mmu_flags = 0;
/*
* Write the address of the JIT allocation to the user provided
* GPU allocation.
*/
ptr = kbase_vmap_prot(kctx, info->gpu_alloc_addr, sizeof(*ptr),
KBASE_REG_CPU_WR, &mapping); //<------- 1.
...
new_addr = reg->start_pfn << PAGE_SHIFT;
*ptr = new_addr; //<------- 2.
...
kbase_vunmap(kctx, &mapping);
}
In the above, info->gpu_alloc_addr
in 1. is provided by the user, which is vmapped and gets written to in 2. In particular, the user can supply the address of the backing page of a BASE_MEM_IMPORT_TYPE_USER_BUFFER
as the gpu_alloc_addr
.
As the code region between 1. and 2. is only protected by the kbase_jd_context::lock
, it is possible to have this softjob race with the KBASE_IOCTL_STICKY_RESOURCE_UNMAP
ioctl which drops the reference to the backing page of gpu_alloc_addr
between 1. and 2. in the above. This then causes the backing page to be freed and 2. will then write to memory that is already freed.
Impact
Allows read and write access to already freed memory, possibly enabling an attacker to gain code execution in the kernel.
CVE
- CVE-2022-46395
Credit
This issue was discovered and reported by GHSL team member @m-y-mo (Man Yue Mo).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2022-127
in any communication regarding this issue.