Coordinated Disclosure Timeline
- 03/12/2020 Reported to Qualcomm security team.
- 14/12/2020 Qualcomm security team confirms that they are able to verify the vulnerability and rated it as Medium severity.
- 08/09/2021 Enquire Qualcomm security team about when the fix will be available
- 08/09/2021 Qualcomm security team replied saying that the fix were available in their customer security bulletin in April 2021 and the vulnerability was assigned CVE-2021-1969, but did not say when the patch will be made public.
- 01/10/2021 The fix is available publicly in the October bulletin.
Summary
Information leak in Qualcomm npu driver due to use of uninitialized varaible
Product
msm kernel
Tested Version
Samsung Galaxy A71: SM-A715F/DS AP: A715FXXU3ATJ2 and CP: A715FXXU3ATI5, Kernel version 4.14.117-19828683 and build ID QP1A.190711.020.A715FXXU3ATJ2
Details
In the MSM_NPU_RECEIVE_EVENT
ioctl call, a msm_npu_event
is copied back to user [1]:
static int npu_receive_event(struct npu_client *client,
unsigned long arg)
{
...
if (list_empty(&client->evt_list)) {
...
} else {
kevt = list_first_entry(&client->evt_list,
struct npu_kevent, list);
list_del(&kevt->list);
npu_process_kevent(kevt);
ret = copy_to_user(argp, &kevt->evt,
sizeof(struct msm_npu_event));
Although various fields of this msm_npu_event
have been initialized when created [2]:
kevt.evt.type = MSM_NPU_EVENT_TYPE_EXEC_V2_DONE;
kevt.evt.u.exec_v2_done.network_hdl =
exe_rsp_pkt->network_hdl;
kevt.evt.u.exec_v2_done.exec_result =
exe_rsp_pkt->header.status;
kevt.evt.u.exec_v2_done.stats_buf_size = stats_size;
kevt.reserved[0] = (uint64_t)network->stats_buf;
kevt.reserved[1] = (uint64_t)network->stats_buf_u;
if (npu_queue_event(network->client, &kevt))
the problem is that the u
field of msm_npu_event
is a union
[3]:
struct msm_npu_event {
uint32_t type;
union {
struct msm_npu_event_execute_done exec_done;
struct msm_npu_event_execute_v2_done exec_v2_done;
struct msm_npu_event_ssr ssr;
uint8_t data[128];
} u;
uint32_t reserved[4];
};
and msm_npu_event_execute_v2_done
, which is initialized in [2], is only of size 20 bytes [4]. This means that there are another 108 bytes not initialized in the field u
(as data[128]
is of size 128 bytes), plus the 32 bytes reserved
field uninitialized. So when copied back to userland in [1], a lot of uninitialized data in the kernel will also be copied back.
- https://android.googlesource.com/kernel/msm/+/refs/heads/android-msm-coral-4.14-android11/drivers/media/platform/msm/npu/npu_dev.c#1611
- https://android.googlesource.com/kernel/msm/+/refs/heads/android-msm-coral-4.14-android11/drivers/media/platform/msm/npu/npu_mgr.c#813
- https://android.googlesource.com/kernel/msm/+/refs/heads/android-msm-coral-4.14-android11/include/uapi/linux/msm_npu.h#276
- https://android.googlesource.com/kernel/msm/+/refs/heads/android-msm-coral-4.14-android11/include/uapi/linux/msm_npu.h#265
CVE
- CVE-2021-1969
Impact
Trivially exploitable to leak kernel address and bypass KASLR from the untrusted app domain.
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 the GHSL-2021-1031
in any communication regarding this issue.