2022-05-10 21:34:12

by Zixuan Fu

[permalink] [raw]
Subject: [PATCH v2] drivers: net: vmxnet3: fix possible NULL pointer dereference in vmxnet3_rq_cleanup()

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]
...

Reported-by: TOTE Robot <[email protected]>
Signed-off-by: Zixuan Fu <[email protected]>
---
v2:
* Move check to the front and exit early if rq->rx_ring[0].base is NULL.
Thank Jakub Kicinski for helpful advice.
---
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 d9d90baac72a..6b8f3aaa313f 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1666,6 +1666,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.25.1



2022-05-14 03:47:37

by Paolo Abeni

[permalink] [raw]
Subject: Re: [PATCH v2] drivers: net: vmxnet3: fix possible NULL pointer dereference in vmxnet3_rq_cleanup()

On Tue, 2022-05-10 at 21:17 +0800, Zixuan Fu wrote:
> 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]
> ...
>
> Reported-by: TOTE Robot <[email protected]>
> Signed-off-by: Zixuan Fu <[email protected]>

Same remarks here, please provide a new version with a suitable fixes
tag, thanks!

Paolo