nvethernet: Harden while loops

Issue:
 Unsigned int variable in loop condition
 can be stuck forever if variable becomes uint_max-1
 for unknown reason

Fix:
 Add acceptable range condition check for loops

Bug 2715343

Change-Id: I0c29d77fd3c2c7e03e3ff3492acea00b94e3319e
Signed-off-by: Mahesh Patil <maheshp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2244699
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mahesh Patil
2019-11-21 12:11:01 -08:00
committed by Revanth Kumar Uppala
parent fa8c188668
commit 5176ea0aa5
3 changed files with 31 additions and 6 deletions

View File

@@ -1653,7 +1653,7 @@ static int ether_tx_swcx_alloc(struct device *dev,
/* Map the linear buffers from the skb first. /* Map the linear buffers from the skb first.
* For TSO only upto TCP header is filled in first desc. * For TSO only upto TCP header is filled in first desc.
*/ */
while (len) { while (valid_tx_len(len)) {
tx_swcx = tx_ring->tx_swcx + cur_tx_idx; tx_swcx = tx_ring->tx_swcx + cur_tx_idx;
if (unlikely(tx_swcx->len)) { if (unlikely(tx_swcx->len)) {
goto desc_not_free; goto desc_not_free;
@@ -1685,7 +1685,7 @@ static int ether_tx_swcx_alloc(struct device *dev,
*/ */
if ((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO) { if ((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO) {
len = skb_headlen(skb) - tx_pkt_cx->total_hdrlen; len = skb_headlen(skb) - tx_pkt_cx->total_hdrlen;
while (len) { while (valid_tx_len(len)) {
tx_swcx = tx_ring->tx_swcx + cur_tx_idx; tx_swcx = tx_ring->tx_swcx + cur_tx_idx;
if (unlikely(tx_swcx->len)) { if (unlikely(tx_swcx->len)) {
@@ -1719,7 +1719,7 @@ static int ether_tx_swcx_alloc(struct device *dev,
offset = 0; offset = 0;
frag = &skb_shinfo(skb)->frags[i]; frag = &skb_shinfo(skb)->frags[i];
len = skb_frag_size(frag); len = skb_frag_size(frag);
while (len) { while (valid_tx_len(len)) {
tx_swcx = tx_ring->tx_swcx + cur_tx_idx; tx_swcx = tx_ring->tx_swcx + cur_tx_idx;
if (unlikely(tx_swcx->len)) { if (unlikely(tx_swcx->len)) {
goto desc_not_free; goto desc_not_free;
@@ -1759,7 +1759,7 @@ desc_not_free:
dma_map_failed: dma_map_failed:
/* Failed to fill current desc. Rollback previous desc's */ /* Failed to fill current desc. Rollback previous desc's */
while (cnt) { while (cnt > 0) {
DECR_TX_DESC_INDEX(cur_tx_idx, 1U); DECR_TX_DESC_INDEX(cur_tx_idx, 1U);
tx_swcx = tx_ring->tx_swcx + cur_tx_idx; tx_swcx = tx_ring->tx_swcx + cur_tx_idx;
if (tx_swcx->buf_phy_addr) { if (tx_swcx->buf_phy_addr) {

View File

@@ -121,10 +121,34 @@
#define ETHER_DEFAULT_PLATFORM_MTU 1500U #define ETHER_DEFAULT_PLATFORM_MTU 1500U
/** /**
* @brief Maximum buffer length per DMA descriptor (4KB). * @brief Maximum buffer length per DMA descriptor (16KB).
*/ */
#define ETHER_TX_MAX_BUFF_SIZE 0x3FFF #define ETHER_TX_MAX_BUFF_SIZE 0x3FFF
/**
* @brief Maximum skb frame(GSO/TSO) size (64KB)
*/
#define ETHER_TX_MAX_FRAME_SIZE GSO_MAX_SIZE
/**
* @brief Check if Tx data buffer length is within bounds.
*
* Algorithm: Check the data length if it is valid.
*
* @param[in] length: Tx data buffer length to check
*
* @retval true if length is valid
* @retval false otherwise
*/
static inline bool valid_tx_len(unsigned int length)
{
if (length > 0U && length <= ETHER_TX_MAX_FRAME_SIZE) {
return true;
} else {
return false;
}
}
/* Descriptors required for maximum contiguous TSO/GSO packet /* Descriptors required for maximum contiguous TSO/GSO packet
* one extra descriptor if there is linear buffer payload * one extra descriptor if there is linear buffer payload
*/ */

View File

@@ -190,7 +190,8 @@ static void ether_realloc_rx_skb(struct ether_priv_data *pdata,
unsigned int local_refill_idx = rx_ring->refill_idx; unsigned int local_refill_idx = rx_ring->refill_idx;
int ret = 0; int ret = 0;
while (local_refill_idx != rx_ring->cur_rx_idx) { while (local_refill_idx != rx_ring->cur_rx_idx &&
local_refill_idx < RX_DESC_CNT) {
rx_swcx = rx_ring->rx_swcx + local_refill_idx; rx_swcx = rx_ring->rx_swcx + local_refill_idx;
rx_desc = rx_ring->rx_desc + local_refill_idx; rx_desc = rx_ring->rx_desc + local_refill_idx;