There are a series of memory corruption vulnerabilities in Samsung Exynos kernels, due to improper error checks, after dma_buf_vmap calls. These bugs can be abused by various privileged processes to cause NULL pointer accesses and crash the kernel.

Vulnerability Details

The kernel uses the dma_buf_vmap function if it needs to map a dma buffer into the kernel address space to access its content. This function returns a NULL pointer if it encounters an error during its execution. While some drivers employ a null check on the returned pointer, many call sites incorrectly use the IS_ERR macro which explicitly allows NULL pointers. Some locations miss the check completely before accessing the returned pointer.

This vulnerability is further amplified by the fact that dma_buf_vmap is often used to map user supplied ION buffers into the kernel virtual address space. A malicious user can always pass an ION buffer to the kernel that causes the dma_buf_vmap call to fail and return with a NULL pointer. This can be achieved for example by allocating a sufficiently large buffer. Even if the ION buffer is allocated by the kernel the dma_buf_vmap could fail due to various reasons.

Because of the missing or wrong check the returned pointer is treated as valid, causing a kernel NULL pointer dereference error which crashes and reboots the device. A malicious user could leverage these vulnerabilities to put the device into a crash loop rendering it dysfunctional.

Below is the description of the dma_buf_vmap function from the kernel sources. As the comment states, on error a NULL pointer is returned.

/**
 * dma_buf_vmap - Create virtual mapping for the buffer object into kernel
 * address space. Same restrictions as for vmap and friends apply.
 * @dmabuf: [in]  buffer to vmap
 *
 * This call may fail due to lack of virtual mapping address space.
 * These calls are optional in drivers. The intended use for them
 * is for mapping objects linear in kernel space for high use objects.
 * Please attempt to use kmap/kunmap before thinking about these interfaces.
 *
 * Returns NULL on error.
 */

The following code snippet demonstrates a vulnerable call site where the return value is checked with the IS_ERR macro.

int npu_memory_map(struct npu_memory *memory, struct npu_memory_buffer *buffer)
{
  [...]
  vaddr = dma_buf_vmap(buffer->dma_buf);
  // 1. IS_ERR allows NULL value there is an IS_ERR_OR_NULL macro to check for it
  if (IS_ERR(vaddr)) {
    npu_err("Failed to get vaddr (err %pK)\n", vaddr);
    ret = -EFAULT;
    goto p_err;
  }
  buffer->vaddr = vaddr;
  [...]
}

Below is a list of places where this bug pattern manifests with a user supplied ION buffer. This list was created with static and dynamic analysis, I tried to be thorough, however this is not intended to be an exhaustive list. There could be further places affected by the same vulnerability especially on different kernel versions or devices. The sole purpose of this list is to highlight that the vulnerability is not an isolated incident but a recurring pattern.

  • /dev/vertex10:
    • npu_memory_map in drivers/vision/npu/core/npu-memory.c uses IS_ERR macro
    • __vb_map_dmabuf in drivers/vision/vision-core/vision-buffer.c uses IS_ERR macro
  • /dev/fb0:
    • The decon framebuffer device is not used after the proper drm driver (mali) is initialised, however it is extensively used by the recovery system. What makes this an interesting example is that dma_buf_vmap is called multiple places and some of them completely miss the check while others implement it correctly
    • decon_set_hdr_info in drivers/video/fbdev/exynos/dpu30/decon_core.c misses the check
    • decon_set_dpp_config in drivers/video/fbdev/exynos/dpu30/decon_core.c misses the check
    • The ION buffer is passed in decon_set_win_config ioctl handler
  • /dev/videoXXX:
    • mfc_mem_ion_alloc in drivers/media/platform/exynos/mfc/mfc_mem.c uses IS_ERR macro

While the access to these devices is restricted to privileged processes by selinux, together they provide a significant attack surface.

Affected Devices (Verified)

Samsung S20 Exynos 990, SM-G980F

Fix

Samsung OTA images, released after October 2021, contain the fix for the vulnerability.

Timeline

  • 2021.04.27. Bug reported to Samsung Mobile Security
  • 2021.05.21. Samsung Mobile Security confirmes the vulnerability, SVE-2021-21621 is assigned
  • 2021.10.01. Samsung releases security bulletin, CVE-2021-25491 is assigned, OTA firmware update distribution begins