mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 10:02:02 +02:00
Bluetooth: btintel_pcie: validate device-supplied DMA indices
In btintel_pcie_msix_rx_handle(), the driver processes RX completion
descriptors (urbd1) written by the PCIe device into DMA-coherent memory.
urbd1->frbd_tag (a 16-bit field fully controlled by the device firmware
via DMA) is used directly as an array index into rxq->bufs[] without any
bounds check. rxq->bufs[] has only BTINTEL_PCIE_RX_DESCS_COUNT (64)
entries, while frbd_tag can be any value 0-65535. A malicious or
malfunctioning device can write an out-of-range frbd_tag, causing the
driver to dereference an out-of-bounds data_buf pointer.
Additionally, cr_hia is read from a DMA-shared index array also writable
by the device; if the device sets cr_hia >= rxq->count, the while-loop
never terminates because cr_tia is wrapped via modulo rxq->count and can
never equal an out-of-range cr_hia.
Add bounds validation for cr_hia and frbd_tag in the RX path, and cr_hia
in the TX path. Log invalid values with bt_dev_err before returning.
Fixes: c2b636b3f7 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
Signed-off-by: Ravindra <ravindra@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
f0ca020cbb
commit
37a1112934
|
|
@ -1099,6 +1099,11 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data)
|
|||
|
||||
txq = &data->txq;
|
||||
|
||||
if (cr_hia >= txq->count) {
|
||||
bt_dev_err(data->hdev, "TXQ: invalid cr_hia %u", cr_hia);
|
||||
return;
|
||||
}
|
||||
|
||||
while (cr_tia != cr_hia) {
|
||||
data->tx_wait_done = true;
|
||||
wake_up(&data->tx_wait_q);
|
||||
|
|
@ -1650,6 +1655,11 @@ static void btintel_pcie_msix_rx_handle(struct btintel_pcie_data *data)
|
|||
|
||||
rxq = &data->rxq;
|
||||
|
||||
if (cr_hia >= rxq->count) {
|
||||
bt_dev_err(hdev, "RXQ: invalid cr_hia %u", cr_hia);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The firmware sends multiple CD in a single MSI-X and it needs to
|
||||
* process all received CDs in this interrupt.
|
||||
*/
|
||||
|
|
@ -1657,6 +1667,12 @@ static void btintel_pcie_msix_rx_handle(struct btintel_pcie_data *data)
|
|||
urbd1 = &rxq->urbd1s[cr_tia];
|
||||
ipc_print_urbd1(data->hdev, urbd1, cr_tia);
|
||||
|
||||
if (urbd1->frbd_tag >= rxq->count) {
|
||||
bt_dev_err(hdev, "RXQ: invalid frbd_tag %u",
|
||||
urbd1->frbd_tag);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = &rxq->bufs[urbd1->frbd_tag];
|
||||
if (!buf) {
|
||||
bt_dev_err(hdev, "RXQ: failed to get the DMA buffer for %d",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user