diff options
author | Bert Kenward <bkenward@solarflare.com> | 2017-12-07 12:18:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-12-08 13:25:39 -0500 |
commit | d4a7a8893d4cdbc89d79ac4aa704bf8d4b67b368 (patch) | |
tree | ba5facbcc8cbb76b382a6b607f91ce050e42d552 | |
parent | b6b5e8a691185606dfffff3198c89e3b4fd9d4f6 (diff) |
sfc: pass valid pointers from efx_enqueue_unwind
The bytes_compl and pkts_compl pointers passed to efx_dequeue_buffers
cannot be NULL. Add a paranoid warning to check this condition and fix
the one case where they were NULL.
efx_enqueue_unwind() is called very rarely, during error handling.
Without this fix it would fail with a NULL pointer dereference in
efx_dequeue_buffer, with efx_enqueue_skb in the call stack.
Fixes: e9117e5099ea ("sfc: Firmware-Assisted TSO version 2")
Reported-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Bert Kenward <bkenward@solarflare.com>
Tested-by: Jarod Wilson <jarod@redhat.com>
Acked-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/sfc/tx.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 0ea7e16f2e6e..9937a2450e57 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c | |||
@@ -77,6 +77,7 @@ static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue, | |||
77 | } | 77 | } |
78 | 78 | ||
79 | if (buffer->flags & EFX_TX_BUF_SKB) { | 79 | if (buffer->flags & EFX_TX_BUF_SKB) { |
80 | EFX_WARN_ON_PARANOID(!pkts_compl || !bytes_compl); | ||
80 | (*pkts_compl)++; | 81 | (*pkts_compl)++; |
81 | (*bytes_compl) += buffer->skb->len; | 82 | (*bytes_compl) += buffer->skb->len; |
82 | dev_consume_skb_any((struct sk_buff *)buffer->skb); | 83 | dev_consume_skb_any((struct sk_buff *)buffer->skb); |
@@ -426,12 +427,14 @@ static int efx_tx_map_data(struct efx_tx_queue *tx_queue, struct sk_buff *skb, | |||
426 | static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) | 427 | static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) |
427 | { | 428 | { |
428 | struct efx_tx_buffer *buffer; | 429 | struct efx_tx_buffer *buffer; |
430 | unsigned int bytes_compl = 0; | ||
431 | unsigned int pkts_compl = 0; | ||
429 | 432 | ||
430 | /* Work backwards until we hit the original insert pointer value */ | 433 | /* Work backwards until we hit the original insert pointer value */ |
431 | while (tx_queue->insert_count != tx_queue->write_count) { | 434 | while (tx_queue->insert_count != tx_queue->write_count) { |
432 | --tx_queue->insert_count; | 435 | --tx_queue->insert_count; |
433 | buffer = __efx_tx_queue_get_insert_buffer(tx_queue); | 436 | buffer = __efx_tx_queue_get_insert_buffer(tx_queue); |
434 | efx_dequeue_buffer(tx_queue, buffer, NULL, NULL); | 437 | efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl); |
435 | } | 438 | } |
436 | } | 439 | } |
437 | 440 | ||