| From 00131620ded4014e8795145ea422193ad9fc8f8a Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 13 Nov 2021 22:24:40 -0500 |
| Subject: atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait |
| |
| From: Zekun Shen <bruceshenzk@gmail.com> |
| |
| [ Upstream commit b922f622592af76b57cbc566eaeccda0b31a3496 ] |
| |
| This bug report shows up when running our research tools. The |
| reports is SOOB read, but it seems SOOB write is also possible |
| a few lines below. |
| |
| In details, fw.len and sw.len are inputs coming from io. A len |
| over the size of self->rpc triggers SOOB. The patch fixes the |
| bugs by adding sanity checks. |
| |
| The bugs are triggerable with compromised/malfunctioning devices. |
| They are potentially exploitable given they first leak up to |
| 0xffff bytes and able to overwrite the region later. |
| |
| The patch is tested with QEMU emulater. |
| This is NOT tested with a real device. |
| |
| Attached is the log we found by fuzzing. |
| |
| BUG: KASAN: slab-out-of-bounds in |
| hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] |
| Read of size 4 at addr ffff888016260b08 by task modprobe/213 |
| CPU: 0 PID: 213 Comm: modprobe Not tainted 5.6.0 #1 |
| Call Trace: |
| dump_stack+0x76/0xa0 |
| print_address_description.constprop.0+0x16/0x200 |
| ? hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] |
| ? hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] |
| __kasan_report.cold+0x37/0x7c |
| ? aq_hw_read_reg_bit+0x60/0x70 [atlantic] |
| ? hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] |
| kasan_report+0xe/0x20 |
| hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] |
| hw_atl_utils_fw_rpc_call+0x95/0x130 [atlantic] |
| hw_atl_utils_fw_rpc_wait+0x176/0x210 [atlantic] |
| hw_atl_utils_mpi_create+0x229/0x2e0 [atlantic] |
| ? hw_atl_utils_fw_rpc_wait+0x210/0x210 [atlantic] |
| ? hw_atl_utils_initfw+0x9f/0x1c8 [atlantic] |
| hw_atl_utils_initfw+0x12a/0x1c8 [atlantic] |
| aq_nic_ndev_register+0x88/0x650 [atlantic] |
| ? aq_nic_ndev_init+0x235/0x3c0 [atlantic] |
| aq_pci_probe+0x731/0x9b0 [atlantic] |
| ? aq_pci_func_init+0xc0/0xc0 [atlantic] |
| local_pci_probe+0xd3/0x160 |
| pci_device_probe+0x23f/0x3e0 |
| |
| Reported-by: Brendan Dolan-Gavitt <brendandg@nyu.edu> |
| Signed-off-by: Zekun Shen <bruceshenzk@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c |
| index 404cbf60d3f2f..da1d185f6d226 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c |
| +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c |
| @@ -559,6 +559,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, |
| goto err_exit; |
| |
| if (fw.len == 0xFFFFU) { |
| + if (sw.len > sizeof(self->rpc)) { |
| + printk(KERN_INFO "Invalid sw len: %x\n", sw.len); |
| + err = -EINVAL; |
| + goto err_exit; |
| + } |
| err = hw_atl_utils_fw_rpc_call(self, sw.len); |
| if (err < 0) |
| goto err_exit; |
| @@ -567,6 +572,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, |
| |
| if (rpc) { |
| if (fw.len) { |
| + if (fw.len > sizeof(self->rpc)) { |
| + printk(KERN_INFO "Invalid fw len: %x\n", fw.len); |
| + err = -EINVAL; |
| + goto err_exit; |
| + } |
| err = |
| hw_atl_utils_fw_downld_dwords(self, |
| self->rpc_addr, |
| -- |
| 2.33.0 |
| |