VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46188

CVE-2026-46188

Description

In the Linux kernel, the following vulnerability has been resolved:

octeon_ep_vf: add NULL check for napi_build_skb()

napi_build_skb() can return NULL on allocation failure. In __octep_vf_oq_process_rx(), the result is used directly without a NULL check in both the single-buffer and multi-fragment paths, leading to a NULL pointer dereference.

Add NULL checks after both napi_build_skb() calls, properly advancing descriptors and consuming remaining fragments on failure.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Missing NULL check in napi_build_skb() in octeon_ep_vf driver leads to denial of service.

Vulnerability

In the Linux kernel, the octeon_ep_vf network driver for Cavium OCTEON endpoint virtual functions has a NULL pointer dereference vulnerability in the __octep_vf_oq_process_rx() function, present in both the single-buffer and multi-fragment receive paths. The function napi_build_skb() can return NULL when memory allocation fails, and its return value is used without a NULL check, leading to a kernel crash. This affects all kernel versions containing the vulnerable code prior to the commit that adds the NULL check [1].

Exploitation

An attacker with the ability to send network packets to a system using the octeon_ep_vf driver can trigger this vulnerability by causing memory pressure on the receiving side, such that napi_build_skb() fails to allocate a socket buffer. No authentication is required; the attacker only needs network access to trigger the receive processing. The race condition or memory exhaustion can be exploited to force the allocation failure and subsequent dereference [1].

Impact

Successful exploitation results in a NULL pointer dereference in the kernel's network stack, leading to a denial of service by crashing the system (oops or panic). There is no evidence of privilege escalation or remote code execution; the impact is limited to availability [1].

Mitigation

The vulnerability is fixed in the Linux kernel by commit 6fef6640bbf360e254cc0174365ed30ce3a07572, which adds NULL checks after napi_build_skb() calls and properly handles fragments on failure. Users should update their kernel to include this patch. No workaround is available; the affected driver must be loaded for exploitation, but if the hardware is not in use, the driver can be blacklisted [1].

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

8
60246cdd4c51

octeon_ep_vf: add NULL check for napi_build_skb()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid CarlierFixed in 6.12.88via kernel-cna
2 files changed · +68 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
b0f4711b426a

octeon_ep_vf: add NULL check for napi_build_skb()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid CarlierFixed in 6.18.30via kernel-cna
2 files changed · +68 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
6fef6640bbf3

octeon_ep_vf: add NULL check for napi_build_skb()

2 files changed · +68 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
dd66b4285470

octeon_ep_vf: add NULL check for napi_build_skb()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid CarlierFixed in 7.1-rc1via kernel-cna
2 files changed · +56 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+28 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index 7bd1b9b8d7f5a1..d9824740824239 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -414,10 +414,15 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			desc_used++;
    @@ -427,6 +432,27 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+28 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index 7bd1b9b8d7f5a1..d9824740824239 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -414,10 +414,15 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			desc_used++;
    @@ -427,6 +432,27 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
dd66b4285470

octeon_ep_vf: add NULL check for napi_build_skb()

2 files changed · +56 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+28 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index 7bd1b9b8d7f5a1..d9824740824239 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -414,10 +414,15 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			desc_used++;
    @@ -427,6 +432,27 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+28 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index 7bd1b9b8d7f5a1..d9824740824239 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -414,10 +414,15 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			desc_used++;
    @@ -427,6 +432,27 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx = octep_vf_oq_next_idx(oq, read_idx);
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
60246cdd4c51

octeon_ep_vf: add NULL check for napi_build_skb()

2 files changed · +68 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
6fef6640bbf3

octeon_ep_vf: add NULL check for napi_build_skb()

2 files changed · +68 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
b0f4711b426a

octeon_ep_vf: add NULL check for napi_build_skb()

2 files changed · +68 6
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c+34 3 modified
    diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    index b579d5b545c46d..8347e696937cdb 100644
    --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
    @@ -409,10 +409,17 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
     			rx_ol_flags = 0;
     		}
    -		rx_bytes += buff_info->len;
    -
     		if (buff_info->len <= oq->max_single_buffer_size) {
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			skb_put(skb, buff_info->len);
     			read_idx++;
    @@ -424,6 +431,31 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
     			u16 data_len;
     
     			skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
    +			if (!skb) {
    +				oq->stats->alloc_failures++;
    +				desc_used++;
    +				read_idx++;
    +				if (read_idx == oq->max_count)
    +					read_idx = 0;
    +				data_len = buff_info->len - oq->max_single_buffer_size;
    +				while (data_len) {
    +					dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
    +						       PAGE_SIZE, DMA_FROM_DEVICE);
    +					buff_info = (struct octep_vf_rx_buffer *)
    +						    &oq->buff_info[read_idx];
    +					buff_info->page = NULL;
    +					if (data_len < oq->buffer_size)
    +						data_len = 0;
    +					else
    +						data_len -= oq->buffer_size;
    +					desc_used++;
    +					read_idx++;
    +					if (read_idx == oq->max_count)
    +						read_idx = 0;
    +				}
    +				continue;
    +			}
    +			rx_bytes += buff_info->len;
     			skb_reserve(skb, data_offset);
     			/* Head fragment includes response header(s);
     			 * subsequent fragments contains only data.
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing NULL check on the return value of napi_build_skb() in __octep_vf_oq_process_rx() allows a NULL pointer dereference when memory allocation fails."

Attack vector

An attacker on the same network as a system using the octeon_ep_vf driver can trigger the vulnerability by sending network packets that cause the kernel to exhaust memory, making napi_build_skb() return NULL [patch_id=2897925]. The function __octep_vf_oq_process_rx() in drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c then dereferences the NULL pointer directly in both the single-buffer and multi-fragment RX paths, causing a kernel NULL pointer dereference and likely a system crash (denial of service) [patch_id=2897925]. No authentication is required; the attacker only needs to be able to send Ethernet frames to the affected interface.

Affected code

The vulnerable function is __octep_vf_oq_process_rx() in drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c [patch_id=2897925]. Both the single-buffer branch (when buff_info->len <= oq->max_single_buffer_size) and the multi-fragment branch lacked NULL checks on the return value of napi_build_skb() [patch_id=2897925].

What the fix does

The patch adds NULL checks after both napi_build_skb() calls in __octep_vf_oq_process_rx() [patch_id=2897925]. On allocation failure in the single-buffer path, it increments the alloc_failures statistic, advances the descriptor index, and skips to the next packet via continue. In the multi-fragment path, it additionally iterates through remaining fragments, unmapping DMA pages and clearing buffer info pointers, to properly clean up resources before continuing [patch_id=2897925]. The rx_bytes accumulation was also moved after the NULL check to avoid accounting for dropped packets.

Preconditions

  • configThe system must be using the octeon_ep_vf network driver.
  • networkThe attacker must be able to send network packets to the affected interface.
  • inputMemory pressure must be high enough that napi_build_skb() allocation fails.

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.