| From 5a3cc1e7c7fe84a875e629cf68626818580a97ee Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 14 May 2022 13:07:11 +0800 |
| Subject: net: vmxnet3: fix possible NULL pointer dereference in |
| vmxnet3_rq_cleanup() |
| |
| From: Zixuan Fu <r33s3n6@gmail.com> |
| |
| [ Upstream commit edf410cb74dc612fd47ef5be319c5a0bcd6e6ccd ] |
| |
| In vmxnet3_rq_create(), when dma_alloc_coherent() fails, |
| vmxnet3_rq_destroy() is called. It sets rq->rx_ring[i].base to NULL. Then |
| vmxnet3_rq_create() returns an error to its callers mxnet3_rq_create_all() |
| -> vmxnet3_change_mtu(). Then vmxnet3_change_mtu() calls |
| vmxnet3_force_close() -> dev_close() in error handling code. And the driver |
| calls vmxnet3_close() -> vmxnet3_quiesce_dev() -> vmxnet3_rq_cleanup_all() |
| -> vmxnet3_rq_cleanup(). In vmxnet3_rq_cleanup(), |
| rq->rx_ring[ring_idx].base is accessed, but this variable is NULL, causing |
| a NULL pointer dereference. |
| |
| To fix this possible bug, an if statement is added to check whether |
| rq->rx_ring[0].base is NULL in vmxnet3_rq_cleanup() and exit early if so. |
| |
| The error log in our fault-injection testing is shown as follows: |
| |
| [ 65.220135] BUG: kernel NULL pointer dereference, address: 0000000000000008 |
| ... |
| [ 65.222633] RIP: 0010:vmxnet3_rq_cleanup_all+0x396/0x4e0 [vmxnet3] |
| ... |
| [ 65.227977] Call Trace: |
| ... |
| [ 65.228262] vmxnet3_quiesce_dev+0x80f/0x8a0 [vmxnet3] |
| [ 65.228580] vmxnet3_close+0x2c4/0x3f0 [vmxnet3] |
| [ 65.228866] __dev_close_many+0x288/0x350 |
| [ 65.229607] dev_close_many+0xa4/0x480 |
| [ 65.231124] dev_close+0x138/0x230 |
| [ 65.231933] vmxnet3_force_close+0x1f0/0x240 [vmxnet3] |
| [ 65.232248] vmxnet3_change_mtu+0x75d/0x920 [vmxnet3] |
| ... |
| |
| Fixes: d1a890fa37f27 ("net: VMware virtual Ethernet NIC driver: vmxnet3") |
| Reported-by: TOTE Robot <oslab@tsinghua.edu.cn> |
| Signed-off-by: Zixuan Fu <r33s3n6@gmail.com> |
| Link: https://lore.kernel.org/r/20220514050711.2636709-1-r33s3n6@gmail.com |
| Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/vmxnet3/vmxnet3_drv.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c |
| index 8ab86bbdbf5e..bc3192cf48e3 100644 |
| --- a/drivers/net/vmxnet3/vmxnet3_drv.c |
| +++ b/drivers/net/vmxnet3/vmxnet3_drv.c |
| @@ -1668,6 +1668,10 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq, |
| u32 i, ring_idx; |
| struct Vmxnet3_RxDesc *rxd; |
| |
| + /* ring has already been cleaned up */ |
| + if (!rq->rx_ring[0].base) |
| + return; |
| + |
| for (ring_idx = 0; ring_idx < 2; ring_idx++) { |
| for (i = 0; i < rq->rx_ring[ring_idx].size; i++) { |
| #ifdef __BIG_ENDIAN_BITFIELD |
| -- |
| 2.35.1 |
| |