* Re: [PATCH 07/10] net: emac: fix DMA API mapping and unmapping correctness
From: Paolo Abeni @ 2026-07-02 10:39 UTC (permalink / raw)
To: rosenp; +Cc: netdev, andrew+netdev, davem, edumazet, kuba, pabeni,
linux-kernel
In-Reply-To: <20260630041634.284127-8-rosenp@gmail.com>
From: AI Reviewer <ai@example.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
net: emac: fix DMA API mapping and unmapping correctness
This patch adds dma_mapping_error() checks after every dma_map_single()
and skb_frag_dma_map() call in the ibm emac driver, introduces a shadow
rx_dma[] array in struct emac_instance, and replaces the map-and-leak
pattern in emac_recycle_rx_skb() with dma_sync_single_for_device().
A few questions follow inline.
> net: emac: fix DMA API mapping and unmapping correctness
[Low]
The subject says the fix is for DMA API mapping and unmapping
correctness, but the in-tree comment added by this patch states:
+ * TX buffers still lack dma_unmap calls for the reasons explained in the
+ * original note below (a single skb may be split across multiple BDs on
+ * TAH-equipped EMACs, making per-fragment tracking complex).
Should the subject be scoped to the RX path (for example, "fix DMA API
correctness on the RX path") since the TX-side DMA API violation is
intentionally preserved?
[Low]
The commit message bullet says:
- emac_recycle_rx_skb: map first, check error, then unmap old;
use dma_sync_single_for_device() with SKB_DATA_ALIGN(len + NET_IP_ALIGN)
But emac_recycle_rx_skb() only calls dma_sync_single_for_device() and
performs no map/check/unmap sequence; the "map first, check, unmap old"
sequence is in the emac_poll_rx() MAL_RX_CTRL_FIRST branch. Would it
help to split this bullet across the two functions?
[Low]
The changelog ends with:
For whatever reason after this patch, ath9k stopped throwing DMA
errors with CONFIG_DMA_API_DEBUG.
Is this perhaps an artifact of CONFIG_DMA_API_DEBUG hash exhaustion
caused by the leaked mappings in the pre-patch driver? It might be
worth investigating and stating the mechanism rather than leaving it
as an unexplained side effect.
[Low]
The emac_recycle_rx_skb() change (discarding the returned DMA address
from dma_map_single()) looks like a long-standing functional bug on
systems with IOMMU/SWIOTLB. Would a Fixes: tag and stable consideration
be appropriate for that hunk?
> diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
> index ced9690cddc3..aed1ad21e2ea 100644
> --- a/drivers/net/ethernet/ibm/emac/core.c
> +++ b/drivers/net/ethernet/ibm/emac/core.c
[ ... ]
> @@ -1058,6 +1066,7 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
> /* Second pass, allocate new skbs */
> for (i = 0; i < NUM_RX_BUFF; ++i) {
> struct sk_buff *skb;
> + dma_addr_t dma;
>
> skb = netdev_alloc_skb_ip_align(dev->ndev, rx_skb_size);
> if (!skb) {
> @@ -1066,12 +1075,24 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
> }
>
> BUG_ON(!dev->rx_skb[i]);
> + dma_unmap_single(&dev->ofdev->dev,
> + dev->rx_dma[i],
> + dev->rx_sync_size, DMA_FROM_DEVICE);
> dev_kfree_skb(dev->rx_skb[i]);
>
> - dev->rx_desc[i].data_ptr =
> - dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
> - rx_sync_size, DMA_FROM_DEVICE)
> - + NET_IP_ALIGN;
> + dma = dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
> + rx_sync_size, DMA_FROM_DEVICE);
> + if (dma_mapping_error(&dev->ofdev->dev, dma)) {
> + dev_kfree_skb(skb);
> + dev->rx_skb[i] = NULL;
> + dev->rx_dma[i] = 0;
> + dev->rx_desc[i].data_ptr = 0;
> + dev->rx_desc[i].ctrl = 0;
> + ret = -ENOMEM;
> + goto oom;
> + }
[High]
Can this error path leave the descriptor ring in a state that crashes
the next NAPI poll?
The first pass earlier in emac_resize_rx_ring() initialises every
slot's ctrl with:
dev->rx_desc[i].ctrl = MAL_RX_CTRL_EMPTY |
(i == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
so software (which polls with "if (ctrl & MAL_RX_CTRL_EMPTY) break;")
treats those slots as owned by hardware and skips them. The new error
path here sets ctrl = 0 instead, which clears MAL_RX_CTRL_EMPTY (and
MAL_RX_CTRL_WRAP for the last slot).
The oom: label below unconditionally re-enables RX:
oom:
clear_bit(MAL_COMMAC_RX_STOPPED, &dev->commac.flags);
dev->rx_slot = 0;
mal_enable_rx_channel(dev->mal, dev->mal_rx_chan);
emac_rx_enable(dev);
emac_netif_start(dev);
On the next emac_poll_rx() call, the loop reads ctrl = 0, finds the
EMPTY bit clear, and proceeds with skb = dev->rx_skb[slot] = NULL,
followed by memcpy()/skb_put()/eth_type_trans() on that NULL skb.
Additionally, the slot's rx_skb[i] is now NULL but the loop above
starts each iteration with BUG_ON(!dev->rx_skb[i]). Would a subsequent
MTU change deterministically panic on that BUG_ON()?
Should this error path mirror the first pass and use MAL_RX_CTRL_EMPTY
(plus MAL_RX_CTRL_WRAP for the last slot) rather than zero?
[ ... ]
> @@ -1176,15 +1201,23 @@ static void emac_clear_mal_desc(struct mal_descriptor *desc, int count)
> static int
> __emac_prepare_rx_skb(struct sk_buff *skb, struct emac_instance *dev, int slot)
> {
> + dma_addr_t dma;
> +
> if (unlikely(!skb))
> return -ENOMEM;
>
> dev->rx_skb[slot] = skb;
> dev->rx_desc[slot].data_len = 0;
>
> - dev->rx_desc[slot].data_ptr =
> - dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
> - dev->rx_sync_size, DMA_FROM_DEVICE) + NET_IP_ALIGN;
> + dma = dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
> + dev->rx_sync_size, DMA_FROM_DEVICE);
> + if (dma_mapping_error(&dev->ofdev->dev, dma)) {
> + dev->rx_skb[slot] = NULL;
> + dev_kfree_skb(skb);
> + return -ENOMEM;
> + }
> + dev->rx_desc[slot].data_ptr = dma + NET_IP_ALIGN;
> + dev->rx_dma[slot] = dma;
[Critical]
Can this corrupt the slot state on a DMA mapping failure?
The new skb is installed into the slot before the mapping is performed:
dev->rx_skb[slot] = skb;
dev->rx_desc[slot].data_len = 0;
dma = dma_map_single(...);
if (dma_mapping_error(...)) {
dev->rx_skb[slot] = NULL;
dev_kfree_skb(skb);
return -ENOMEM;
}
On failure, the new skb is freed and rx_skb[slot] is set to NULL, but
dev->rx_desc[slot].data_ptr and dev->rx_dma[slot] still hold the old
mapping, and the previous skb pointer that the caller saved (the
emac_poll_rx() local "skb") is also lost.
The emac_poll_rx() caller paths handle the failure as:
} else if (unlikely(emac_alloc_rx_skb_napi(dev, slot)))
goto oom;
...
oom:
++dev->estats.rx_dropped_oom;
emac_recycle_rx_skb(dev, slot, 0);
emac_recycle_rx_skb() then re-arms the descriptor with
MAL_RX_CTRL_EMPTY, handing the still-mapped old buffer back to
hardware. On the next received packet, dev->rx_skb[slot] is NULL and:
skb = dev->rx_skb[slot];
...
memcpy(copy_skb->data - NET_IP_ALIGN,
skb->data - NET_IP_ALIGN,
len + NET_IP_ALIGN);
would dereference NULL in NAPI context. The MAL_RX_CTRL_FIRST branch
that calls emac_alloc_rx_skb_napi() has the same shape.
Would it be safer to perform the dma_map_single() and error check
before installing the new skb into rx_skb[slot], so the slot still
points at a valid skb and mapping on failure?
[ ... ]
> @@ -1808,12 +1863,17 @@ static int emac_poll_rx(void *param, int budget)
> continue;
> sg:
> if (ctrl & MAL_RX_CTRL_FIRST) {
> + dma_addr_t old_dma = dev->rx_dma[slot];
> +
> BUG_ON(dev->rx_sg_skb);
> if (unlikely(emac_alloc_rx_skb_napi(dev, slot))) {
> DBG(dev, "rx OOM %d" NL, slot);
> ++dev->estats.rx_dropped_oom;
> emac_recycle_rx_skb(dev, slot, 0);
> } else {
> + dma_unmap_single(&dev->ofdev->dev, old_dma,
> + dev->rx_sync_size,
> + DMA_FROM_DEVICE);
> dev->rx_sg_skb = skb;
> skb_put(skb, len);
> }
[High]
The commit message bullet says:
- emac_poll_rx: use rx_dma[] shadow array, unmap old skb before
passing to napi_gro_receive
but the new dma_unmap_single() above only covers the SG
MAL_RX_CTRL_FIRST branch. The non-SG large-packet path
(len >= EMAC_RX_COPY_THRESH) is in emac_poll_rx():
skb = dev->rx_skb[slot];
...
if (len && len < EMAC_RX_COPY_THRESH) {
...
} else if (unlikely(emac_alloc_rx_skb_napi(dev, slot)))
goto oom;
skb_put(skb, len);
push_packet:
skb->protocol = eth_type_trans(skb, dev->ndev);
emac_rx_csum(dev, skb, ctrl);
napi_gro_receive(&dev->mal->napi, skb);
emac_alloc_rx_skb_napi() calls __emac_prepare_rx_skb() which
overwrites dev->rx_dma[slot] with the new mapping, so the previous
mapping address is lost. The original "skb" is then handed to
napi_gro_receive() while still mapped DMA_FROM_DEVICE.
Does this leak one DMA mapping per large-packet RX, and on the
non-coherent PowerPC platforms this patch targets, hand the stack a
buffer that has not been dma_unmap_single()'d?
Should the non-SG large-packet branch also save old_dma before
emac_alloc_rx_skb_napi() and call dma_unmap_single() before
napi_gro_receive(), mirroring the SG-first branch?
[ ... ]
--
This is an AI-generated review.
^ permalink raw reply
* Re: [PATCH net-next v2 0/4] net: convert UDP getsockopt to sockopt_t
From: patchwork-bot+netdevbpf @ 2026-07-02 10:40 UTC (permalink / raw)
To: Breno Leitao
Cc: davem, edumazet, kuba, pabeni, horms, willemdebruijn.kernel,
shuah, sdf.kernel, netdev, linux-kernel, linux-kselftest,
kernel-team
In-Reply-To: <20260630-getsockopt_phase2-v2-0-193335f3d4d1@debian.org>
Hello:
This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Tue, 30 Jun 2026 07:01:25 -0700 you wrote:
> The leaf proto_ops getsockopt callbacks have been moving to the new
> getsockopt_iter()/sockopt_t interface.
>
> I was trying to get SMC into getsockop and retire .getsockopt, but,
> I found the best approach is to keep converting other protocols.
>
> This series starts the same conversion one layer down, at the struct proto
> getsockopt path, beginning with UDP.
>
> [...]
Here is the summary with links:
- [net-next,v2,1/4] net: add sockopt_init_user() for getsockopt conversion
https://git.kernel.org/netdev/net-next/c/b5997f911eec
- [net-next,v2,2/4] udp: convert udp_lib_getsockopt to sockopt_t
https://git.kernel.org/netdev/net-next/c/f99d7065a4d4
- [net-next,v2,3/4] ipv4: raw: convert do_raw_getsockopt to sockopt_t
https://git.kernel.org/netdev/net-next/c/9588d5da17ce
- [net-next,v2,4/4] selftests: net: getsockopt_iter: add raw ICMP_FILTER coverage
https://git.kernel.org/netdev/net-next/c/f4d5e3a5c7bc
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next v3 01/15] net: macb: drop "consistent" from alloc/free function names
From: Nicolai Buchwitz @ 2026-07-02 10:41 UTC (permalink / raw)
To: Théo Lebrun
Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
Maxime Chevallier
In-Reply-To: <20260701-macb-context-v3-1-00268d5b1502@bootlin.com>
On 1.7.2026 17:59, Théo Lebrun wrote:
> Since commit 4df95131ea80 ("net/macb: change RX path for GEM") those
> functions have not been only allocating or freeing consistent memory
> mappings.
>
> Rename from macb_alloc_consistent() to macb_alloc() and
> from macb_free_consistent() to macb_free().
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> drivers/net/ethernet/cadence/macb_main.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb_main.c
> b/drivers/net/ethernet/cadence/macb_main.c
> index fd282a1700fb..d677a93b9d72 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -2646,7 +2646,7 @@ static unsigned int
> macb_rx_ring_size_per_queue(struct macb *bp)
> return macb_dma_desc_get_size(bp) * bp->rx_ring_size +
> bp->rx_bd_rd_prefetch;
> }
>
> -static void macb_free_consistent(struct macb *bp)
> +static void macb_free(struct macb *bp)
> {
> struct device *dev = &bp->pdev->dev;
> struct macb_queue *queue;
> @@ -2711,7 +2711,7 @@ static int macb_alloc_rx_buffers(struct macb *bp)
> return 0;
> }
>
> -static int macb_alloc_consistent(struct macb *bp)
> +static int macb_alloc(struct macb *bp)
> {
> struct device *dev = &bp->pdev->dev;
> dma_addr_t tx_dma, rx_dma;
> @@ -2769,7 +2769,7 @@ static int macb_alloc_consistent(struct macb *bp)
> return 0;
>
> out_err:
> - macb_free_consistent(bp);
> + macb_free(bp);
> return -ENOMEM;
> }
>
> @@ -3157,7 +3157,7 @@ static int macb_open(struct net_device *dev)
> /* RX buffers initialization */
> macb_init_rx_buffer_size(bp, bufsz);
>
> - err = macb_alloc_consistent(bp);
> + err = macb_alloc(bp);
> if (err) {
> netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
> err);
> @@ -3202,7 +3202,7 @@ static int macb_open(struct net_device *dev)
> napi_disable(&queue->napi_rx);
> napi_disable(&queue->napi_tx);
> }
> - macb_free_consistent(bp);
> + macb_free(bp);
> pm_exit:
> pm_runtime_put_sync(&bp->pdev->dev);
> return err;
> @@ -3235,7 +3235,7 @@ static int macb_close(struct net_device *dev)
> netif_carrier_off(dev);
> spin_unlock_irqrestore(&bp->lock, flags);
>
> - macb_free_consistent(bp);
> + macb_free(bp);
>
> if (bp->ptp_info)
> bp->ptp_info->ptp_remove(dev);
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks
Nicolai
^ permalink raw reply
* Re: [PATCH net-next v3 03/15] net: macb: unify variable naming convention in at91ether functions
From: Nicolai Buchwitz @ 2026-07-02 10:42 UTC (permalink / raw)
To: Théo Lebrun
Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
Maxime Chevallier
In-Reply-To: <20260701-macb-context-v3-3-00268d5b1502@bootlin.com>
On 1.7.2026 17:59, Théo Lebrun wrote:
> Follow MACB naming convention throughout on two aspects:
> - Always name `struct macb *bp` rather than `lp`.
> - Always name `struct macb_queue *queue` rather than `q`.
>
> The latter is to reserve `q` for queue indexes.
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> [...]
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks
Nicolai
^ permalink raw reply
* Re: [PATCH 03/10] net: emac: use DMA-specific and SMP memory barriers
From: Paolo Abeni @ 2026-07-02 10:42 UTC (permalink / raw)
To: Rosen Penev, netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
open list
In-Reply-To: <20260630041634.284127-4-rosenp@gmail.com>
On 6/30/26 6:16 AM, Rosen Penev wrote:
> @@ -1845,7 +1845,7 @@ static int emac_poll_rx(void *param, int budget)
> }
>
> if (unlikely(budget && test_bit(MAL_COMMAC_RX_STOPPED, &dev->commac.flags))) {
> - mb();
> + dma_rmb();
> if (!(dev->rx_desc[slot].ctrl & MAL_RX_CTRL_EMPTY)) {
> DBG2(dev, "rx restart" NL);
> received = 0;
Sashiko geimini thinks the above is not enough for PowerPC:
https://sashiko.dev/#/patchset/20260630041634.284127-1-rosenp%40gmail.com
> diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
> index a3839cf02ec4..5144ee94a7d2 100644
> --- a/drivers/net/ethernet/ibm/emac/zmii.c
> +++ b/drivers/net/ethernet/ibm/emac/zmii.c
> @@ -258,8 +258,8 @@ static int zmii_probe(struct platform_device *ofdev)
> /* Disable all inputs by default */
> out_be32(&dev->base->fer, 0);
>
> - printk(KERN_INFO "ZMII %pOF initialized\n", ofdev->dev.of_node);
> - wmb();
> + dev_info(&ofdev->dev, "ZMII initialized\n");
The printk change is unrelated and should go in a different patch.
/P
^ permalink raw reply
* Re: [PATCH net-next v3 04/15] net: macb: unify queue index variable naming convention and types
From: Nicolai Buchwitz @ 2026-07-02 10:43 UTC (permalink / raw)
To: Théo Lebrun
Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
Maxime Chevallier
In-Reply-To: <20260701-macb-context-v3-4-00268d5b1502@bootlin.com>
On 1.7.2026 17:59, Théo Lebrun wrote:
> Variables are named q or queue_index. Types are int, unsigned int, u32
> and u16. Use `unsigned int q` everywhere.
>
> Skip over taprio functions. They use `u8 queue_id` which fits with the
> `struct macb_queue_enst_config` field. Using `queue_id` everywhere
> would be too verbose.
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> drivers/net/ethernet/cadence/macb_main.c | 32
> ++++++++++++++++----------------
> 1 file changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb_main.c
> b/drivers/net/ethernet/cadence/macb_main.c
> index 86c0e9ccbfce..3b75797381b6 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -877,7 +877,7 @@ static void gem_shuffle_tx_one_ring(struct
> macb_queue *queue)
> static void gem_shuffle_tx_rings(struct macb *bp)
> {
> struct macb_queue *queue;
> - int q;
> + unsigned int q;
>
> for (q = 0, queue = bp->queues; q < bp->num_queues; q++, queue++)
> gem_shuffle_tx_one_ring(queue);
> @@ -1258,7 +1258,7 @@ static void macb_tx_error_task(struct work_struct
> *work)
> tx_error_task);
> bool halt_timeout = false;
> struct macb *bp = queue->bp;
> - u32 queue_index;
> + unsigned int q;
> u32 packets = 0;
> u32 bytes = 0;
> struct macb_tx_skb *tx_skb;
> @@ -1267,9 +1267,9 @@ static void macb_tx_error_task(struct work_struct
> *work)
> unsigned int tail;
> unsigned long flags;
>
> - queue_index = queue - bp->queues;
> + q = queue - bp->queues;
> netdev_vdbg(bp->netdev, "macb_tx_error_task: q = %u, t = %u, h =
> %u\n",
> - queue_index, queue->tx_tail, queue->tx_head);
> + q, queue->tx_tail, queue->tx_head);
>
> /* Prevent the queue NAPI TX poll from running, as it calls
> * macb_tx_complete(), which in turn may call netif_wake_subqueue().
> @@ -1342,7 +1342,7 @@ static void macb_tx_error_task(struct work_struct
> *work)
> macb_tx_unmap(bp, tx_skb, 0);
> }
>
> - netdev_tx_completed_queue(netdev_get_tx_queue(bp->netdev,
> queue_index),
> + netdev_tx_completed_queue(netdev_get_tx_queue(bp->netdev, q),
> packets, bytes);
>
> /* Set end of TX queue */
> @@ -1407,7 +1407,7 @@ static bool ptp_one_step_sync(struct sk_buff
> *skb)
> static int macb_tx_complete(struct macb_queue *queue, int budget)
> {
> struct macb *bp = queue->bp;
> - u16 queue_index = queue - bp->queues;
> + unsigned int q = queue - bp->queues;
> unsigned long flags;
> unsigned int tail;
> unsigned int head;
> @@ -1469,14 +1469,14 @@ static int macb_tx_complete(struct macb_queue
> *queue, int budget)
> }
> }
>
> - netdev_tx_completed_queue(netdev_get_tx_queue(bp->netdev,
> queue_index),
> + netdev_tx_completed_queue(netdev_get_tx_queue(bp->netdev, q),
> packets, bytes);
>
> queue->tx_tail = tail;
> - if (__netif_subqueue_stopped(bp->netdev, queue_index) &&
> + if (__netif_subqueue_stopped(bp->netdev, q) &&
> CIRC_CNT(queue->tx_head, queue->tx_tail,
> bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
> - netif_wake_subqueue(bp->netdev, queue_index);
> + netif_wake_subqueue(bp->netdev, q);
> spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
>
> if (packets)
> @@ -2470,10 +2470,10 @@ static int macb_pad_and_fcs(struct sk_buff
> **skb, struct net_device *netdev)
> static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
> struct net_device *netdev)
> {
> - u16 queue_index = skb_get_queue_mapping(skb);
> struct macb *bp = netdev_priv(netdev);
> - struct macb_queue *queue = &bp->queues[queue_index];
> + unsigned int q = skb_get_queue_mapping(skb);
> unsigned int desc_cnt, nr_frags, frag_size, f;
> + struct macb_queue *queue = &bp->queues[q];
> unsigned int hdrlen;
> unsigned long flags;
> bool is_lso;
> @@ -2512,8 +2512,8 @@ static netdev_tx_t macb_start_xmit(struct sk_buff
> *skb,
>
> #if defined(DEBUG) && defined(VERBOSE_DEBUG)
> netdev_vdbg(bp->netdev,
> - "start_xmit: queue %hu len %u head %p data %p tail %p end %p\n",
> - queue_index, skb->len, skb->head, skb->data,
> + "start_xmit: queue %u len %u head %p data %p tail %p end %p\n",
> + q, skb->len, skb->head, skb->data,
> skb_tail_pointer(skb), skb_end_pointer(skb));
> print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1,
> skb->data, 16, true);
> @@ -2539,7 +2539,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff
> *skb,
> /* This is a hard error, log it. */
> if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
> bp->tx_ring_size) < desc_cnt) {
> - netif_stop_subqueue(netdev, queue_index);
> + netif_stop_subqueue(netdev, q);
> netdev_dbg(netdev, "tx_head = %u, tx_tail = %u\n",
> queue->tx_head, queue->tx_tail);
> ret = NETDEV_TX_BUSY;
> @@ -2555,7 +2555,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff
> *skb,
> /* Make newly initialized descriptor visible to hardware */
> wmb();
> skb_tx_timestamp(skb);
> - netdev_tx_sent_queue(netdev_get_tx_queue(bp->netdev, queue_index),
> + netdev_tx_sent_queue(netdev_get_tx_queue(bp->netdev, q),
> skb->len);
>
> spin_lock(&bp->lock);
> @@ -2564,7 +2564,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff
> *skb,
> spin_unlock(&bp->lock);
>
> if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
> - netif_stop_subqueue(netdev, queue_index);
> + netif_stop_subqueue(netdev, q);
>
> unlock:
> spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks
Nicolai
^ permalink raw reply
* Re: [PATCH net v2] net: airoha: Add retry mechanism to airoha_qdma_set_trtcm_param()
From: Leto Liu (刘涛) @ 2026-07-02 10:44 UTC (permalink / raw)
To: Lorenzo Bianconi, Simon Horman
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, netdev@vger.kernel.org,
Brown Huang (黃柏翰)
In-Reply-To: <ajrtd5WA2GFzQyV9@lore-desk>
First, let me descript the detailed mechanism of hardware QDMA register read/write is as follows:
CPU register reads do not have a “write-fail” issue; a CPU read operation does not fail to execute.
A CPU register write may not take effect as expected, i.e., the value written by the CPU may not be preserved. This is because QDMA performs non-atomic read-modify-write (RMW) operations, and a hardware write can overwrite a CPU write, causing the CPU write to be lost.
rw_done is cleared to 0 when the CPU issues a write request, and is set to 1 after completion. The interval is only a few hardware clock cycles (less than 10 ns).
Regarding write contention:
CPU side (driver/software) HW side (rate-limiter engine)
| |
| write cfg_param register | token-bucket refill tick / packet ingress/egress
| (indirectly writes SRAM) | (updates SRAM)
| |
v v
+-----------------------------------------------------------------------------------------------------------------------------------------+
| HW SRAM |
| |
| HW performs Read-Modify-Write (non-atomic) |
| | |
| | 1. HW reads the old value |
| | 2. CPU write happens first ---> contention point |
| | 3. HW write overwrites with old/mod value ---> CPU value overwritten |
| v |
+-----------------------------------------------------------------------------------------------------------------------------------------+
Best Regards, Leto
> > This is an AI-generated review of your patch. The human sending this
> > email has considered the AI review valid, or at least plausible.
> > Full review at: https://sashiko.dev
> >
> > Simon says: I'd appreciate it if you could look over the first two issues
> > flagged below in the context of this patch. While the third
> > and final issue looks like it is in possible separate follow-up
> > territory.
> >
> > ---
> > net: airoha: Add retry mechanism to airoha_qdma_set_trtcm_param()
> >
> > This patch introduces a retry loop to airoha_qdma_set_trtcm_param() to
> > mitigate bus timeouts when configuring QDMA parameters. It attempts to
> > verify that the configuration is correctly applied to the hardware.
> >
> > > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c
> > > b/drivers/net/ethernet/airoha/airoha_eth.c
> > > index 3370c3df7c107..bb5c0599a4eed 100644
> > > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> > > @@ -2673,14 +2673,30 @@ static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel,
> > > FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
> > > FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
> > > FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
> > > + int i;
> > >
> > > - airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
> > > - airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
> > > + for (i = 0; i < 100; i++) {
> > > + u32 data;
> > >
> > > - return read_poll_timeout(airoha_qdma_rr, val,
> > > - val & TRTCM_PARAM_RW_DONE_MASK,
> > > - USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
> > > - qdma, REG_TRTCM_CFG_PARAM(addr));
> > > + airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
> > > + wmb();
> > > + airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
> > > +
> > > + if (read_poll_timeout(airoha_qdma_rr, data,
> > > + data & TRTCM_PARAM_RW_DONE_MASK,
> > > + USEC_PER_MSEC, 10 * USEC_PER_MSEC,
> > > + true, qdma, REG_TRTCM_CFG_PARAM(addr)))
> > > + return -ETIMEDOUT;
> >
> > [Severity: High]
> > If a bus timeout causes the write phase's read_poll_timeout() in
> > airoha_qdma_set_trtcm_param() to fail, this immediately returns
> > -ETIMEDOUT, aborting the 100-iteration retry loop.
> >
> > Doesn't this defeat the mitigation?
Here we are polling the hardware done bit. Based on the hardware behavior described above, a read operation will not fail. In addition, the hardware register write completes within at most 10 ns, while the poll timeout here is configured more than 1 ms. From these two points, we can conclude that this read_poll_timeout will always succeed (i.e., it will return 0). Therefore, adding a return -ETIMEDOUT path here will not cause any issues.
Best Regards, Leto
>
> I agree we just run 'continue' here instead of returing -ETIMEDOUT
No change is needed here, and even if we modify it, it will not cause any issues.
Best Regards, Leto
> >
> > > +
> > > + if (airoha_qdma_get_trtcm_param(qdma, channel, addr, param,
> > > + mode, &data, NULL))
> > > + continue;
> >
> > [Severity: High]
> > If airoha_qdma_get_trtcm_param() times out during the verification
> > phase, it indicates the hardware hasn't finished the read command (DONE bit is still 0).
> >
> > The continue statement then immediately starts the next iteration,
> > writing new commands to DATA_LOW and CFG_PARAM.
> >
> > Can writing to command registers while the hardware state machine is
> > actively busy violate hardware protocols and lead to unrecoverable lockups?
>
> @Brown and @Leto: can you please comment on this case?
>
the hardware register write completes within at most 10 ns, while the poll timeout here is configured more than 1 ms. When airoha_qdma_get_trtcm_param() is called here, the hardware has already completed the previous register write operation. Therefore, the concern mentioned here will definitely not occur, and there will be no issue at this point.
Best Regards, Leto
> >
> > > +
> > > + if (data == val)
> > > + return 0;
> >
> > [Severity: High]
> > This isn't a bug introduced by this patch, but if the bus drops the
> > command write to REG_TRTCM_CFG_PARAM, the hardware never executes the
> > command and the TRTCM_PARAM_RW_DONE_MASK bit remains set from the previous operation.
> >
> > Consequently, read_poll_timeout() returns an immediate false success.
> >
> > If both the set and get command writes are dropped by the bus, the get
> > operation will read back the newly written DATA_LOW register value.
> >
> > Will the data == val check evaluate to true and falsely report success
> > without the hardware ever processing the configuration?
>
> This seems quite a 'pathological' scenario, is it really an issue?
>
> Regards,
> Lorenzo
>
As explained above, the concern here does not apply and there will be no issue.
Best Regards, Leto
> >
> > > + }
> > > +
> > > + return -EBUSY;
> > > }
> > >
> >
> > [ ... ]
> >
> > > static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel,
> > > u32 addr, enum trtcm_mode_type mode,
> > > bool enable, u32 enable_mask)
> > > {
> > > u32 val;
> > >
> > > if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
> > > mode, &val, NULL))
> > > return -EINVAL;
> >
> > [Severity: High]
> > Standalone calls to airoha_qdma_get_trtcm_param(), like this one in
> > airoha_qdma_set_trtcm_config(), lack a retry loop entirely.
> >
> > Does this leave read-modify-write cycles fully vulnerable to the same
> > bus timeouts the patch attempts to mitigate?
> >
No change is needed here. Even if the write succeeds but the read-back during verification returns an incorrect value, the verification will fail and the code will proceed to the next retry. A failure would only occur if this happened for 100 consecutive attempts, which has an almost zero probability. Therefore, this code does not affect the final outcome.
That said, your suggestion is a good one, and it is still worthwhile to improve/optimize the read function.
Best Regards, Leto
> > [Severity: High]
> > This isn't a bug introduced by this patch, but the patch mitigates bus
> > timeouts in airoha_qdma_set_trtcm_param() while entirely missing
> > airoha_qdma_set_rl_param().
> >
> > The latter performs the exact same write-and-poll sequence on
> > identical QDMA configuration registers:
> >
> > drivers/net/ethernet/airoha/airoha_eth.c:airoha_qdma_set_rl_param() {
> > ...
> > return read_poll_timeout(..., val & RATE_LIMIT_PARAM_RW_DONE_MASK,
> > ...); }
> >
> > If bus timeouts affect QDMA access broadly as stated in the commit
> > message, are the rate-limiting configuration paths randomly vulnerable to the same failures?
> >
Yes, you are right. Function airoha_qdma_set_rl_param need readback protecting.
Best Regards, Leto
> > [Severity: High]
> > This isn't a bug introduced by this patch, but in
> > airoha_tc_remove_htb_queue(), hardware teardown incorrectly uses queue + 1 instead of queue:
> >
> > drivers/net/ethernet/airoha/airoha_eth.c:airoha_tc_remove_htb_queue() {
> > ...
> > airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0);
> > ...
> > }
> >
> > Does this leave the removed queue's hardware limits permanently active
> > (resource leak) and inadvertently disable the rate limits for queue +
> > 1, corrupting the QoS state of another active channel?
It has already been fixed, refer to https://github.com/LorenzoBianconi/net-next/commit/d775d542504cbfea2b214149405d97eb00a88dc4
Best Regards, Leto
^ permalink raw reply
* Re: [PATCH 05/10] net: emac: mal: replace busy-wait in mal_poll_disable with wait_event
From: Paolo Abeni @ 2026-07-02 10:46 UTC (permalink / raw)
To: Rosen Penev, netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
open list
In-Reply-To: <20260630041634.284127-6-rosenp@gmail.com>
On 6/30/26 6:16 AM, Rosen Penev wrote:
> @@ -371,8 +373,8 @@ static irqreturn_t mal_int(int irq, void *dev_instance)
> void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
> {
> /* Spinlock-type semantics: only one caller disable poll at a time */
> - while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags))
> - msleep(1);
> + wait_event(commac->poll_wait,
> + !test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags));
The above looks dangerous to me. IDK which is the expected latency here,
but unconditionally spinning without any obvious upper bound and no
reschedule does not look good.
/P
^ permalink raw reply
* Re: [PATCH net-next v3 05/15] net: macb: enforce reverse christmas tree (RCT) convention
From: Nicolai Buchwitz @ 2026-07-02 10:48 UTC (permalink / raw)
To: Théo Lebrun
Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
Maxime Chevallier
In-Reply-To: <20260701-macb-context-v3-5-00268d5b1502@bootlin.com>
On 1.7.2026 17:59, Théo Lebrun wrote:
> Enforce the reverse christmas tree convention in those functions:
>
> macb_tx_error_task()
> gem_rx_refill()
> gem_rx()
> macb_rx_frame()
> macb_init_rx_ring()
> macb_rx()
> macb_rx_pending()
> macb_start_xmit()
>
> The goal is to minimise unrelated diff in future patches.
>
> In macb_tx_error_task(), we fold the assignment into the declaration
> statement.
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> drivers/net/ethernet/cadence/macb_main.c | 61
> ++++++++++++++++----------------
> 1 file changed, 30 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb_main.c
> b/drivers/net/ethernet/cadence/macb_main.c
> index 3b75797381b6..8b52122bc134 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -1254,20 +1254,19 @@ static dma_addr_t macb_get_addr(struct macb
> *bp, struct macb_dma_desc *desc)
>
> static void macb_tx_error_task(struct work_struct *work)
> {
> - struct macb_queue *queue = container_of(work, struct macb_queue,
> - tx_error_task);
> - bool halt_timeout = false;
> - struct macb *bp = queue->bp;
> - unsigned int q;
> - u32 packets = 0;
> - u32 bytes = 0;
> - struct macb_tx_skb *tx_skb;
> - struct macb_dma_desc *desc;
> - struct sk_buff *skb;
> - unsigned int tail;
> - unsigned long flags;
> + struct macb_queue *queue = container_of(work, struct macb_queue,
> + tx_error_task);
> + unsigned int q = queue - queue->bp->queues;
> + struct macb *bp = queue->bp;
> + struct macb_tx_skb *tx_skb;
> + struct macb_dma_desc *desc;
> + bool halt_timeout = false;
> + struct sk_buff *skb;
> + unsigned long flags;
> + unsigned int tail;
> + u32 packets = 0;
> + u32 bytes = 0;
>
> - q = queue - bp->queues;
> netdev_vdbg(bp->netdev, "macb_tx_error_task: q = %u, t = %u, h =
> %u\n",
> q, queue->tx_tail, queue->tx_head);
>
> @@ -1487,11 +1486,11 @@ static int macb_tx_complete(struct macb_queue
> *queue, int budget)
>
> static void gem_rx_refill(struct macb_queue *queue)
> {
> - unsigned int entry;
> - struct sk_buff *skb;
> - dma_addr_t paddr;
> struct macb *bp = queue->bp;
> struct macb_dma_desc *desc;
> + struct sk_buff *skb;
> + unsigned int entry;
> + dma_addr_t paddr;
>
> while (CIRC_SPACE(queue->rx_prepared_head, queue->rx_tail,
> bp->rx_ring_size) > 0) {
> @@ -1584,11 +1583,11 @@ static int gem_rx(struct macb_queue *queue,
> struct napi_struct *napi,
> int budget)
> {
> struct macb *bp = queue->bp;
> - unsigned int len;
> - unsigned int entry;
> - struct sk_buff *skb;
> - struct macb_dma_desc *desc;
> - int count = 0;
> + struct macb_dma_desc *desc;
> + struct sk_buff *skb;
> + unsigned int entry;
> + unsigned int len;
> + int count = 0;
>
> while (count < budget) {
> u32 ctrl;
> @@ -1674,12 +1673,12 @@ static int gem_rx(struct macb_queue *queue,
> struct napi_struct *napi,
> static int macb_rx_frame(struct macb_queue *queue, struct napi_struct
> *napi,
> unsigned int first_frag, unsigned int last_frag)
> {
> - unsigned int len;
> - unsigned int frag;
> + struct macb *bp = queue->bp;
> + struct macb_dma_desc *desc;
> unsigned int offset;
> struct sk_buff *skb;
> - struct macb_dma_desc *desc;
> - struct macb *bp = queue->bp;
> + unsigned int frag;
> + unsigned int len;
>
> desc = macb_rx_desc(queue, last_frag);
> len = desc->ctrl & bp->rx_frm_len_mask;
> @@ -1755,9 +1754,9 @@ static int macb_rx_frame(struct macb_queue
> *queue, struct napi_struct *napi,
>
> static inline void macb_init_rx_ring(struct macb_queue *queue)
> {
> + struct macb_dma_desc *desc = NULL;
> struct macb *bp = queue->bp;
> dma_addr_t addr;
> - struct macb_dma_desc *desc = NULL;
> int i;
>
> addr = queue->rx_buffers_dma;
> @@ -1776,9 +1775,9 @@ static int macb_rx(struct macb_queue *queue,
> struct napi_struct *napi,
> {
> struct macb *bp = queue->bp;
> bool reset_rx_queue = false;
> - int received = 0;
> - unsigned int tail;
> int first_frag = -1;
> + unsigned int tail;
> + int received = 0;
>
> for (tail = queue->rx_tail; budget > 0; tail++) {
> struct macb_dma_desc *desc = macb_rx_desc(queue, tail);
> @@ -1853,8 +1852,8 @@ static int macb_rx(struct macb_queue *queue,
> struct napi_struct *napi,
> static bool macb_rx_pending(struct macb_queue *queue)
> {
> struct macb *bp = queue->bp;
> - unsigned int entry;
> - struct macb_dma_desc *desc;
> + struct macb_dma_desc *desc;
> + unsigned int entry;
>
> entry = macb_rx_ring_wrap(bp, queue->rx_tail);
> desc = macb_rx_desc(queue, entry);
> @@ -2474,10 +2473,10 @@ static netdev_tx_t macb_start_xmit(struct
> sk_buff *skb,
> unsigned int q = skb_get_queue_mapping(skb);
> unsigned int desc_cnt, nr_frags, frag_size, f;
> struct macb_queue *queue = &bp->queues[q];
> + netdev_tx_t ret = NETDEV_TX_OK;
> unsigned int hdrlen;
> unsigned long flags;
> bool is_lso;
> - netdev_tx_t ret = NETDEV_TX_OK;
>
> if (macb_clear_csum(skb)) {
> dev_kfree_skb_any(skb);
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks
Nicolai
^ permalink raw reply
* [PATCH net-next 00/12] netfilter: updates for net-next
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
Hi,
The following patchset contains Netfilter updates for *net-next*.
1) Update nfnetlink_hook to dump the individual NAT type chains
instead of the nat base chains to userspace. From Phil Sutter.
2) Replace strlcpy/strlcat() with snprintf() in x_tables, from Ian Bridges.
3) Start replacing u_int8_t and u_int16t with u8 and u16 in netfilter.
From Carlos Grillet.
4) Replace strcpy() with strscpy() in netfilter, from David Laight.
5) Remove redundant NULL check before kvfree().
6) Add parameter validation to xt_tcpmss. Ensure mss_min <= mss_max and
invert <= 1. From Feng Wu.
7) Add checkentry for xt_dscp 'tos' match. Implement tos_mt_check() to reject
invalid invert values. Also from Feng Wu.
8) Stop hashing nf_conntrack_helper by tuple. Switch to hashing by name and
L4 protocol.
9) Remove tuples from conntrack helper definitions and port usage from
broadcast helpers. Add netlink policy validation to prevent protocol
number truncation.
10) Remove obsolete netfilter conntrack module parameters.
11) Bound num_counters in ebtables: do_replace() by MAX_EBT_ENTRIES to prevent
oversized vmalloc_array() allocations. From Jiayuan Chen.
12) Make expectations created via nft_ct rules work with NAT.
Please, pull these changes from:
The following changes since commit b8ea7da314c2efcb9c2f559ed65b7a36c869d68e:
net: dsa: qca8k: fall back to ethernet-ports node name for LEDs (2026-07-02 11:48:25 +0200)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next.git tags/nf-next-26-07-02
for you to fetch changes up to d4beefc90a66672e43fdf82b43e4b3c0b1b18c5e:
netfilter: nft_ct: support expectation creation for natted flows (2026-07-02 12:17:14 +0200)
----------------------------------------------------------------
netfilter pull request nf-next-26-07-02
----------------------------------------------------------------
Carlos Grillet (1):
netfilter: replace u_int8_t and u_int16t with u8 and u16
David Laight (1):
netfilter: avoid strcpy usage
Feng Wu (2):
netfilter: xt_tcpmss: add checkentry for parameter validation
netfilter: xt_dscp: add checkentry for tos match
Florian Westphal (4):
netfilter: nf_conntrack_helper: do not hash by tuple
netfilter: conntrack: get rid of tuple in helper definitions
netfilter: conntrack: remove obsolete module parameters
netfilter: nft_ct: support expectation creation for natted flows
Ian Bridges (1):
netfilter: x_tables: replace strlcat() with snprintf()
Jiayuan Chen (1):
netfilter: ebtables: bound num_counters like nentries in do_replace()
Phil Sutter (1):
netfilter: nfnetlink_hook: Dump nat type chains
Subasri S (1):
netfilter: remove redundant null check before kvfree()
include/linux/netfilter.h | 7 ++
include/linux/netfilter/nf_conntrack_h323.h | 2 -
include/linux/netfilter/nf_conntrack_pptp.h | 2 -
include/linux/netfilter/nf_conntrack_sane.h | 2 -
include/linux/netfilter/nf_conntrack_tftp.h | 2 -
include/net/ip_vs.h | 2 +-
include/net/netfilter/nf_conntrack_helper.h | 10 ++-
net/bridge/netfilter/ebtables.c | 12 ++--
net/ipv4/netfilter/nf_nat_snmp_basic_main.c | 2 +-
net/netfilter/ipvs/ip_vs_nfct.c | 2 +-
net/netfilter/nf_conntrack_amanda.c | 6 +-
net/netfilter/nf_conntrack_broadcast.c | 2 -
net/netfilter/nf_conntrack_ftp.c | 32 +++------
net/netfilter/nf_conntrack_h323_main.c | 12 ++--
net/netfilter/nf_conntrack_helper.c | 77 +++++++++------------
net/netfilter/nf_conntrack_irc.c | 27 +++-----
net/netfilter/nf_conntrack_netbios_ns.c | 2 -
net/netfilter/nf_conntrack_ovs.c | 6 +-
net/netfilter/nf_conntrack_pptp.c | 2 +-
net/netfilter/nf_conntrack_sane.c | 34 +++------
net/netfilter/nf_conntrack_sip.c | 45 ++++--------
net/netfilter/nf_conntrack_snmp.c | 4 +-
net/netfilter/nf_conntrack_tftp.c | 33 +++------
net/netfilter/nf_nat_core.c | 6 --
net/netfilter/nf_nat_proto.c | 8 +++
net/netfilter/nfnetlink_cthelper.c | 21 +++---
net/netfilter/nfnetlink_cttimeout.c | 2 +-
net/netfilter/nfnetlink_hook.c | 37 ++++++++--
net/netfilter/nft_ct.c | 35 ++++++++++
net/netfilter/nft_set_rbtree.c | 3 +-
net/netfilter/x_tables.c | 30 +++-----
net/netfilter/xt_TCPOPTSTRIP.c | 8 +--
net/netfilter/xt_dscp.c | 12 ++++
net/netfilter/xt_recent.c | 2 +-
net/netfilter/xt_tcpmss.c | 13 ++++
net/sched/act_ct.c | 4 +-
36 files changed, 246 insertions(+), 260 deletions(-)
--
2.54.0
^ permalink raw reply
* [PATCH net-next 01/12] netfilter: nfnetlink_hook: Dump nat type chains
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Phil Sutter <phil@nwl.cc>
These chains are indirectly attached to the hook since they are
not called for packets belonging to an established connection.
Introduce NF_HOOK_OP_NAT to identify the container and dump attached
entries instead of the container itself.
Dump these entries with the dispatcher's priority value since their own
priority merely defines ordering within the dispatcher's list.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/netfilter.h | 7 +++++++
net/netfilter/nf_nat_core.c | 6 ------
net/netfilter/nf_nat_proto.c | 8 ++++++++
net/netfilter/nfnetlink_hook.c | 37 ++++++++++++++++++++++++++++++----
4 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index efbbfa770d66..e99afc1414cd 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -93,6 +93,7 @@ enum nf_hook_ops_type {
NF_HOOK_OP_NF_TABLES,
NF_HOOK_OP_BPF,
NF_HOOK_OP_NFT_FT,
+ NF_HOOK_OP_NAT,
};
struct nf_hook_ops {
@@ -140,6 +141,12 @@ struct nf_hook_entries {
*/
};
+struct nf_nat_lookup_hook_priv {
+ struct nf_hook_entries __rcu *entries;
+
+ struct rcu_head rcu_head;
+};
+
#ifdef CONFIG_NETFILTER
static inline struct nf_hook_ops **nf_hook_entries_get_hook_ops(const struct nf_hook_entries *e)
{
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 63ff6b4d5d21..8ac326e1eb5b 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -39,12 +39,6 @@ static struct hlist_head *nf_nat_bysource __read_mostly;
static unsigned int nf_nat_htable_size __read_mostly;
static siphash_aligned_key_t nf_nat_hash_rnd;
-struct nf_nat_lookup_hook_priv {
- struct nf_hook_entries __rcu *entries;
-
- struct rcu_head rcu_head;
-};
-
struct nf_nat_hooks_net {
struct nf_hook_ops *nat_hook_ops;
unsigned int users;
diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c
index 07f51fe75fbe..64b9bac228ea 100644
--- a/net/netfilter/nf_nat_proto.c
+++ b/net/netfilter/nf_nat_proto.c
@@ -770,6 +770,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
/* After packet filtering, change source */
{
@@ -777,6 +778,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
/* Before packet filtering, change destination */
{
@@ -784,6 +786,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
/* After packet filtering, change source */
{
@@ -791,6 +794,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
};
@@ -1031,6 +1035,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP6_PRI_NAT_DST,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
/* After packet filtering, change source */
{
@@ -1038,6 +1043,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP6_PRI_NAT_SRC,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
/* Before packet filtering, change destination */
{
@@ -1045,6 +1051,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP6_PRI_NAT_DST,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
/* After packet filtering, change source */
{
@@ -1052,6 +1059,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP6_PRI_NAT_SRC,
+ .hook_ops_type = NF_HOOK_OP_NAT,
},
};
diff --git a/net/netfilter/nfnetlink_hook.c b/net/netfilter/nfnetlink_hook.c
index 5623c18fcd12..95005e9a6066 100644
--- a/net/netfilter/nfnetlink_hook.c
+++ b/net/netfilter/nfnetlink_hook.c
@@ -190,7 +190,7 @@ static int nfnl_hook_put_nft_ft_info(struct sk_buff *nlskb,
static int nfnl_hook_dump_one(struct sk_buff *nlskb,
const struct nfnl_dump_hook_data *ctx,
- const struct nf_hook_ops *ops,
+ const struct nf_hook_ops *ops, int priority,
int family, unsigned int seq)
{
u16 event = nfnl_msg_type(NFNL_SUBSYS_HOOK, NFNL_MSG_HOOK_GET);
@@ -244,7 +244,7 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb,
if (ret)
goto nla_put_failure;
- ret = nla_put_be32(nlskb, NFNLA_HOOK_PRIORITY, htonl(ops->priority));
+ ret = nla_put_be32(nlskb, NFNLA_HOOK_PRIORITY, htonl(priority));
if (ret)
goto nla_put_failure;
@@ -337,6 +337,30 @@ nfnl_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *de
return hook_head;
}
+static int nfnl_hook_dump_nat(struct sk_buff *nlskb,
+ const struct nfnl_dump_hook_data *ctx,
+ const struct nf_hook_ops *ops,
+ int family, unsigned int seq)
+{
+ struct nf_nat_lookup_hook_priv *priv = ops->priv;
+ struct nf_hook_entries *e = rcu_dereference(priv->entries);
+ struct nf_hook_ops **nat_ops;
+ int i, err;
+
+ if (!e)
+ return 0;
+
+ nat_ops = nf_hook_entries_get_hook_ops(e);
+
+ for (i = 0; i < e->num_hook_entries; i++) {
+ err = nfnl_hook_dump_one(nlskb, ctx, nat_ops[i],
+ ops->priority, family, seq);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
static int nfnl_hook_dump(struct sk_buff *nlskb,
struct netlink_callback *cb)
{
@@ -365,8 +389,13 @@ static int nfnl_hook_dump(struct sk_buff *nlskb,
ops = nf_hook_entries_get_hook_ops(e);
for (; i < e->num_hook_entries; i++) {
- err = nfnl_hook_dump_one(nlskb, ctx, ops[i], family,
- cb->nlh->nlmsg_seq);
+ if (ops[i]->hook_ops_type == NF_HOOK_OP_NAT)
+ err = nfnl_hook_dump_nat(nlskb, ctx, ops[i], family,
+ cb->nlh->nlmsg_seq);
+ else
+ err = nfnl_hook_dump_one(nlskb, ctx, ops[i],
+ ops[i]->priority, family,
+ cb->nlh->nlmsg_seq);
if (err)
break;
}
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 02/12] netfilter: x_tables: replace strlcat() with snprintf()
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Ian Bridges <icb@fastmail.org>
In preparation for removing the deprecated strlcat() API[1], replace the
strscpy()/strlcat() pairs in xt_proto_init() and xt_proto_fini() with
snprintf(), which builds each /proc file name in a single call.
Each name is "<prefix><suffix>", where <prefix> is the address-family
string xt_prefix[af] and <suffix> is one of the FORMAT_TABLES,
FORMAT_MATCHES or FORMAT_TARGETS literals. Prepend %s to the FORMAT
macros and switch to snprintf().
Link: https://github.com/KSPP/linux/issues/370 [1]
Signed-off-by: Ian Bridges <icb@fastmail.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/x_tables.c | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 4e6708c23922..e64116bf2637 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1920,9 +1920,9 @@ static const struct seq_operations xt_target_seq_ops = {
.show = xt_target_seq_show,
};
-#define FORMAT_TABLES "_tables_names"
-#define FORMAT_MATCHES "_tables_matches"
-#define FORMAT_TARGETS "_tables_targets"
+#define FORMAT_TABLES "%s_tables_names"
+#define FORMAT_MATCHES "%s_tables_matches"
+#define FORMAT_TARGETS "%s_tables_targets"
#endif /* CONFIG_PROC_FS */
@@ -2033,8 +2033,7 @@ int xt_proto_init(struct net *net, u_int8_t af)
root_uid = make_kuid(net->user_ns, 0);
root_gid = make_kgid(net->user_ns, 0);
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_TABLES, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_TABLES, xt_prefix[af]);
proc = proc_create_net_data(buf, 0440, net->proc_net, &xt_table_seq_ops,
sizeof(struct seq_net_private),
(void *)(unsigned long)af);
@@ -2043,8 +2042,7 @@ int xt_proto_init(struct net *net, u_int8_t af)
if (uid_valid(root_uid) && gid_valid(root_gid))
proc_set_user(proc, root_uid, root_gid);
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_MATCHES, xt_prefix[af]);
proc = proc_create_seq_private(buf, 0440, net->proc_net,
&xt_match_seq_ops, sizeof(struct nf_mttg_trav),
(void *)(unsigned long)af);
@@ -2053,8 +2051,7 @@ int xt_proto_init(struct net *net, u_int8_t af)
if (uid_valid(root_uid) && gid_valid(root_gid))
proc_set_user(proc, root_uid, root_gid);
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_TARGETS, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_TARGETS, xt_prefix[af]);
proc = proc_create_seq_private(buf, 0440, net->proc_net,
&xt_target_seq_ops, sizeof(struct nf_mttg_trav),
(void *)(unsigned long)af);
@@ -2068,13 +2065,11 @@ int xt_proto_init(struct net *net, u_int8_t af)
#ifdef CONFIG_PROC_FS
out_remove_matches:
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_MATCHES, xt_prefix[af]);
remove_proc_entry(buf, net->proc_net);
out_remove_tables:
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_TABLES, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_TABLES, xt_prefix[af]);
remove_proc_entry(buf, net->proc_net);
out:
return -1;
@@ -2087,16 +2082,13 @@ void xt_proto_fini(struct net *net, u_int8_t af)
#ifdef CONFIG_PROC_FS
char buf[XT_FUNCTION_MAXNAMELEN];
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_TABLES, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_TABLES, xt_prefix[af]);
remove_proc_entry(buf, net->proc_net);
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_TARGETS, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_TARGETS, xt_prefix[af]);
remove_proc_entry(buf, net->proc_net);
- strscpy(buf, xt_prefix[af], sizeof(buf));
- strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+ snprintf(buf, sizeof(buf), FORMAT_MATCHES, xt_prefix[af]);
remove_proc_entry(buf, net->proc_net);
#endif /*CONFIG_PROC_FS*/
}
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 03/12] netfilter: replace u_int8_t and u_int16t with u8 and u16
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Carlos Grillet <carlos@carlosgrillet.me>
Use preferred kernel integer type u8 instead of the POSIX u_int8_t
variant.
No functional change.
Signed-off-by: Carlos Grillet <carlos@carlosgrillet.me>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/ip_vs.h | 2 +-
net/netfilter/ipvs/ip_vs_nfct.c | 2 +-
net/netfilter/nf_conntrack_amanda.c | 2 +-
net/netfilter/nf_conntrack_h323_main.c | 2 +-
net/netfilter/xt_TCPOPTSTRIP.c | 8 ++++----
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 49297fec448a..ed2e9bc1bb4e 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -2123,7 +2123,7 @@ void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
int outin);
int ip_vs_confirm_conntrack(struct sk_buff *skb);
void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
- struct ip_vs_conn *cp, u_int8_t proto,
+ struct ip_vs_conn *cp, u8 proto,
const __be16 port, int from_rs);
void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp);
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
index 81974f69e5bb..347185fd0c8c 100644
--- a/net/netfilter/ipvs/ip_vs_nfct.c
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -208,7 +208,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
* Use port 0 to expect connection from any port.
*/
void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
- struct ip_vs_conn *cp, u_int8_t proto,
+ struct ip_vs_conn *cp, u8 proto,
const __be16 port, int from_rs)
{
struct nf_conntrack_expect *exp;
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index ddafbdfc96dc..f10ac2c49f4b 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -89,7 +89,7 @@ static int amanda_help(struct sk_buff *skb,
struct nf_conntrack_tuple *tuple;
unsigned int dataoff, start, stop, off, i;
char pbuf[sizeof("65535")], *tmp;
- u_int16_t len;
+ u16 len;
__be16 port;
int ret = NF_ACCEPT;
nf_nat_amanda_hook_fn *nf_nat_amanda;
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 24931e379985..37b6314ca772 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -671,7 +671,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
static int callforward_do_filter(struct net *net,
const union nf_inet_addr *src,
const union nf_inet_addr *dst,
- u_int8_t family)
+ u8 family)
{
int ret = 0;
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
index 93f064306901..265d21697847 100644
--- a/net/netfilter/xt_TCPOPTSTRIP.c
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -16,7 +16,7 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_TCPOPTSTRIP.h>
-static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
+static inline unsigned int optlen(const u8 *opt, unsigned int offset)
{
/* Beware zero-length options: make finite progress */
if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
@@ -33,8 +33,8 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
const struct xt_tcpoptstrip_target_info *info = par->targinfo;
struct tcphdr *tcph, _th;
unsigned int optl, i, j;
- u_int16_t n, o;
- u_int8_t *opt;
+ u16 n, o;
+ u8 *opt;
int tcp_hdrlen;
/* This is a fragment, no TCP header is available */
@@ -97,7 +97,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
int tcphoff;
- u_int8_t nexthdr;
+ u8 nexthdr;
__be16 frag_off;
nexthdr = ipv6h->nexthdr;
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 04/12] netfilter: avoid strcpy usage
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: David Laight <david.laight.linux@gmail.com>
Replacing strcpy() with strscpy() ensures that overflow of the target
buffer cannot happen.
[ fw@strlen.de: cleanup. netlink policy rejects too large inputs,
xt_recent validates content and length before the copy ]
Signed-off-by: David Laight <david.laight.linux@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nfnetlink_cttimeout.c | 2 +-
net/netfilter/xt_recent.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 170d3db860c5..66c2016f6049 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -168,7 +168,7 @@ static int cttimeout_new_timeout(struct sk_buff *skb,
if (ret < 0)
goto err_free_timeout_policy;
- strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
+ nla_strscpy(timeout->name, cda[CTA_TIMEOUT_NAME], sizeof(timeout->name));
timeout->timeout->l3num = l3num;
timeout->timeout->l4proto = l4proto;
refcount_set(&timeout->timeout->refcnt, 1);
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index f72752fa4374..d34831ce3adf 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -400,7 +400,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
t->nstamps_max_mask = nstamp_mask;
memcpy(&t->mask, &info->mask, sizeof(t->mask));
- strcpy(t->name, info->name);
+ strscpy(t->name, info->name);
INIT_LIST_HEAD(&t->lru_list);
for (i = 0; i < ip_list_hash_size; i++)
INIT_LIST_HEAD(&t->iphash[i]);
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 05/12] netfilter: remove redundant null check before kvfree()
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Subasri S <subasris1210@gmail.com>
kvfree() internally performs NULL check on the pointer
handed to it and takes no action if it indeed is NULL.
Hence there is no need for a pre-check of the memory
pointer before handing it to kvfree().
Issue reported by ifnullfree.cocci Coccinelle semantic
patch script.
Signed-off-by: Subasri S <subasris1210@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nft_set_rbtree.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 018bbb6df4ce..efc25e788a1c 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -544,8 +544,7 @@ static int nft_array_intervals_alloc(struct nft_array *array, u32 max_intervals)
if (!intervals)
return -ENOMEM;
- if (array->intervals)
- kvfree(array->intervals);
+ kvfree(array->intervals);
array->intervals = intervals;
array->max_intervals = max_intervals;
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 06/12] netfilter: xt_tcpmss: add checkentry for parameter validation
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Feng Wu <wufengwufengwufeng@gmail.com>
Add tcpmss_mt_check() that validates mss_min <= mss_max and
invert <= 1.
Signed-off-by: Feng Wu <wufengwufengwufeng@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/xt_tcpmss.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index b9da8269161d..b08b077d7f0a 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -78,10 +78,23 @@ tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par)
return false;
}
+static int tcpmss_mt_check(const struct xt_mtchk_param *par)
+{
+ const struct xt_tcpmss_match_info *info = par->matchinfo;
+
+ if (info->mss_min > info->mss_max)
+ return -EINVAL;
+ if (info->invert > 1)
+ return -EINVAL;
+
+ return 0;
+}
+
static struct xt_match tcpmss_mt_reg[] __read_mostly = {
{
.name = "tcpmss",
.family = NFPROTO_IPV4,
+ .checkentry = tcpmss_mt_check,
.match = tcpmss_mt,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 07/12] netfilter: xt_dscp: add checkentry for tos match
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Feng Wu <wufengwufengwufeng@gmail.com>
The 'tos' match registered in xt_dscp.c has no .checkentry callback,
allowing userspace to insert rules with a non-boolean invert field
without any validation.
Add tos_mt_check() that rejects invert > 1 and attach it to both the
IPv4 and IPv6 'tos' match registrations.
Signed-off-by: Feng Wu <wufengwufengwufeng@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/xt_dscp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index fb0169a8f9bb..878f27016e99 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -49,6 +49,16 @@ static int dscp_mt_check(const struct xt_mtchk_param *par)
return 0;
}
+static int tos_mt_check(const struct xt_mtchk_param *par)
+{
+ const struct xt_tos_match_info *info = par->matchinfo;
+
+ if (info->invert > 1)
+ return -EINVAL;
+
+ return 0;
+}
+
static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_tos_match_info *info = par->matchinfo;
@@ -82,6 +92,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = {
.name = "tos",
.revision = 1,
.family = NFPROTO_IPV4,
+ .checkentry = tos_mt_check,
.match = tos_mt,
.matchsize = sizeof(struct xt_tos_match_info),
.me = THIS_MODULE,
@@ -90,6 +101,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = {
.name = "tos",
.revision = 1,
.family = NFPROTO_IPV6,
+ .checkentry = tos_mt_check,
.match = tos_mt,
.matchsize = sizeof(struct xt_tos_match_info),
.me = THIS_MODULE,
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 08/12] netfilter: nf_conntrack_helper: do not hash by tuple
From: Florian Westphal @ 2026-07-02 10:49 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
Long time ago helpers were auto-assigned to connections based on
port/protocol match. For this reason, nf_conntrack_helper still contains
a full tuple.
Nowadays the only relevant entries in the tuple are the l3 and l4 protocol
numbers.
Prepare for tuple removal and switch to hashing name and l4 protocol.
l3num cannot be used because helpers can also register for "unspec"
protocol.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nf_conntrack_helper.c | 67 +++++++++++++----------------
1 file changed, 31 insertions(+), 36 deletions(-)
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 500509b17663..5ad5429352a7 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -40,12 +40,16 @@ static unsigned int nf_ct_helper_count __read_mostly;
static DEFINE_MUTEX(nf_ct_nat_helpers_mutex);
static struct list_head nf_ct_nat_helpers __read_mostly;
-/* Stupid hash, but collision free for the default registrations of the
- * helpers currently in the kernel. */
-static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
+static unsigned int helper_hash(const char *name, u8 protonum)
{
- return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^
- (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize;
+ static u32 seed;
+ u32 initval;
+
+ get_random_once(&seed, sizeof(seed));
+
+ initval = seed ^ protonum;
+
+ return jhash(name, strlen(name), initval) % nf_ct_helper_hsize;
}
struct nf_conntrack_helper *
@@ -54,18 +58,21 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
struct nf_conntrack_helper *h;
unsigned int i;
- for (i = 0; i < nf_ct_helper_hsize; i++) {
- hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) {
- if (strcmp(h->name, name))
- continue;
+ if (!nf_ct_helper_hash)
+ return NULL;
- if (h->tuple.src.l3num != NFPROTO_UNSPEC &&
- h->tuple.src.l3num != l3num)
- continue;
+ i = helper_hash(name, protonum);
- if (h->tuple.dst.protonum == protonum)
- return h;
- }
+ hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) {
+ if (strcmp(h->name, name))
+ continue;
+
+ if (h->tuple.src.l3num != NFPROTO_UNSPEC &&
+ h->tuple.src.l3num != l3num)
+ continue;
+
+ if (h->tuple.dst.protonum == protonum)
+ return h;
}
return NULL;
}
@@ -363,9 +370,8 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_log);
int __nf_conntrack_helper_register(struct nf_conntrack_helper *me)
{
- struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
- unsigned int h = helper_hash(&me->tuple);
struct nf_conntrack_helper *cur;
+ unsigned int h;
int ret = 0, i;
BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
@@ -382,29 +388,18 @@ int __nf_conntrack_helper_register(struct nf_conntrack_helper *me)
return -EINVAL;
}
+ h = helper_hash(me->name, me->tuple.dst.protonum);
mutex_lock(&nf_ct_helper_mutex);
- for (i = 0; i < nf_ct_helper_hsize; i++) {
- hlist_for_each_entry(cur, &nf_ct_helper_hash[i], hnode) {
- if (!strcmp(cur->name, me->name) &&
- (cur->tuple.src.l3num == NFPROTO_UNSPEC ||
- cur->tuple.src.l3num == me->tuple.src.l3num) &&
- cur->tuple.dst.protonum == me->tuple.dst.protonum) {
- ret = -EBUSY;
- goto out;
- }
+ hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
+ if (!strcmp(cur->name, me->name) &&
+ (cur->tuple.src.l3num == NFPROTO_UNSPEC ||
+ cur->tuple.src.l3num == me->tuple.src.l3num) &&
+ cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+ ret = -EBUSY;
+ goto out;
}
}
- /* avoid unpredictable behaviour for auto_assign_helper */
- if (!(me->flags & NF_CT_HELPER_F_USERSPACE)) {
- hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
- if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple,
- &mask)) {
- ret = -EBUSY;
- goto out;
- }
- }
- }
refcount_set(&me->ct_refcnt, 1);
hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
nf_ct_helper_count++;
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 09/12] netfilter: conntrack: get rid of tuple in helper definitions
From: Florian Westphal @ 2026-07-02 10:50 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
Leftover from the days when the kernel did automatic assignment of helpers
based on a pre-registered / well-known-port.
This helper autoassign was removed from the kernel, so all we really
need are the l3 and l4 protocol numbers.
In the broadcast helper, the only remaining consumer of the port number is
removed. AFAICS its not needed: The expectation is populated from the
control connection reply tuple, so the src port is the original directions
destination (snmp/161 for example).
LLM complained about silent l3num (u16) -> nfproto (u8) truncation, so
add a netlink policy validation to reject large NFPROTO values upfront.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/netfilter/nf_conntrack_helper.h | 9 ++++-----
net/netfilter/nf_conntrack_broadcast.c | 2 --
net/netfilter/nf_conntrack_helper.c | 22 +++++++++------------
net/netfilter/nf_conntrack_ovs.c | 6 +++---
net/netfilter/nfnetlink_cthelper.c | 21 ++++++++++----------
net/sched/act_ct.c | 4 ++--
6 files changed, 29 insertions(+), 35 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index c761cd8158b2..f3f0c1392e88 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -43,11 +43,10 @@ struct nf_conntrack_helper {
refcount_t ct_refcnt;
- /* Tuple of things we will help (compared against server response) */
- struct nf_conntrack_tuple tuple;
+ u8 nfproto; /* NFPROTO_*, can be NFPROTO_UNSPEC */
+ u8 l4proto; /* IPPROTO_UDP/TCP */
- /* Function to call when data passes; return verdict, or -1 to
- invalidate. */
+ /* Function to call when data passes; return verdict */
int __rcu (*help)(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info conntrackinfo);
@@ -94,7 +93,7 @@ struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
void nf_conntrack_helper_put(struct nf_conntrack_helper *helper);
void nf_ct_helper_init(struct nf_conntrack_helper *helper,
- u16 l3num, u16 protonum, const char *name,
+ u8 l3num, u16 protonum, const char *name,
u16 default_port, u16 spec_port, u32 id,
const struct nf_conntrack_expect_policy *exp_pol,
u32 expect_class_max,
diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c
index bf78828c7549..6ff954f1bfb8 100644
--- a/net/netfilter/nf_conntrack_broadcast.c
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -66,8 +66,6 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
helper = rcu_dereference(help->helper);
- if (helper)
- exp->tuple.src.u.udp.port = helper->tuple.src.u.udp.port;
exp->mask.src.u3.ip = mask;
exp->mask.src.u.udp.port = htons(0xFFFF);
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 5ad5429352a7..b28986100db0 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -66,12 +66,9 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) {
if (strcmp(h->name, name))
continue;
-
- if (h->tuple.src.l3num != NFPROTO_UNSPEC &&
- h->tuple.src.l3num != l3num)
+ if (h->nfproto != NFPROTO_UNSPEC && h->nfproto != l3num)
continue;
-
- if (h->tuple.dst.protonum == protonum)
+ if (h->l4proto == protonum)
return h;
}
return NULL;
@@ -388,13 +385,13 @@ int __nf_conntrack_helper_register(struct nf_conntrack_helper *me)
return -EINVAL;
}
- h = helper_hash(me->name, me->tuple.dst.protonum);
+ h = helper_hash(me->name, me->l4proto);
mutex_lock(&nf_ct_helper_mutex);
hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
if (!strcmp(cur->name, me->name) &&
- (cur->tuple.src.l3num == NFPROTO_UNSPEC ||
- cur->tuple.src.l3num == me->tuple.src.l3num) &&
- cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+ (cur->nfproto == NFPROTO_UNSPEC ||
+ cur->nfproto == me->nfproto) &&
+ cur->l4proto == me->l4proto) {
ret = -EBUSY;
goto out;
}
@@ -474,7 +471,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
void nf_ct_helper_init(struct nf_conntrack_helper *helper,
- u16 l3num, u16 protonum, const char *name,
+ u8 l3num, u16 protonum, const char *name,
u16 default_port, u16 spec_port, u32 id,
const struct nf_conntrack_expect_policy *exp_pol,
u32 expect_class_max,
@@ -487,9 +484,8 @@ void nf_ct_helper_init(struct nf_conntrack_helper *helper,
{
memset(helper, 0, sizeof(*helper));
- helper->tuple.src.l3num = l3num;
- helper->tuple.dst.protonum = protonum;
- helper->tuple.src.u.all = htons(spec_port);
+ helper->nfproto = l3num;
+ helper->l4proto = protonum;
rcu_assign_pointer(helper->help, help);
helper->from_nlattr = from_nlattr;
diff --git a/net/netfilter/nf_conntrack_ovs.c b/net/netfilter/nf_conntrack_ovs.c
index 49d1511e9921..b4085af3ad1c 100644
--- a/net/netfilter/nf_conntrack_ovs.c
+++ b/net/netfilter/nf_conntrack_ovs.c
@@ -31,8 +31,8 @@ int nf_ct_helper(struct sk_buff *skb, struct nf_conn *ct,
if (!helper)
return NF_ACCEPT;
- if (helper->tuple.src.l3num != NFPROTO_UNSPEC &&
- helper->tuple.src.l3num != proto)
+ if (helper->nfproto != NFPROTO_UNSPEC &&
+ helper->nfproto != proto)
return NF_ACCEPT;
switch (proto) {
@@ -60,7 +60,7 @@ int nf_ct_helper(struct sk_buff *skb, struct nf_conn *ct,
return NF_DROP;
}
- if (helper->tuple.dst.protonum != proto)
+ if (helper->l4proto != proto)
return NF_ACCEPT;
helper_cb = rcu_dereference(helper->help);
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index f1460b683d7a..56655cb7fe2a 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -67,7 +67,7 @@ nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff,
}
static const struct nla_policy nfnl_cthelper_tuple_pol[NFCTH_TUPLE_MAX+1] = {
- [NFCTH_TUPLE_L3PROTONUM] = { .type = NLA_U16, },
+ [NFCTH_TUPLE_L3PROTONUM] = NLA_POLICY_MAX(NLA_BE16, NFPROTO_IPV6),
[NFCTH_TUPLE_L4PROTONUM] = { .type = NLA_U8, },
};
@@ -254,7 +254,8 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
helper->data_len = size;
helper->flags |= NF_CT_HELPER_F_USERSPACE;
- memcpy(&helper->tuple, tuple, sizeof(struct nf_conntrack_tuple));
+ helper->nfproto = tuple->src.l3num;
+ helper->l4proto = tuple->dst.protonum;
helper->me = THIS_MODULE;
helper->help = nfnl_userspace_cthelper;
@@ -449,8 +450,8 @@ static int nfnl_cthelper_new(struct sk_buff *skb, const struct nfnl_info *info,
if (strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN))
continue;
- if ((tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
+ if ((tuple.src.l3num != cur->nfproto ||
+ tuple.dst.protonum != cur->l4proto))
continue;
if (info->nlh->nlmsg_flags & NLM_F_EXCL)
@@ -479,10 +480,10 @@ nfnl_cthelper_dump_tuple(struct sk_buff *skb,
goto nla_put_failure;
if (nla_put_be16(skb, NFCTH_TUPLE_L3PROTONUM,
- htons(helper->tuple.src.l3num)))
+ htons(helper->nfproto)))
goto nla_put_failure;
- if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->tuple.dst.protonum))
+ if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->l4proto))
goto nla_put_failure;
nla_nest_end(skb, nest_parms);
@@ -661,8 +662,8 @@ static int nfnl_cthelper_get(struct sk_buff *skb, const struct nfnl_info *info,
continue;
if (tuple_set &&
- (tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
+ (tuple.src.l3num != cur->nfproto ||
+ tuple.dst.protonum != cur->l4proto))
continue;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -721,8 +722,8 @@ static int nfnl_cthelper_del(struct sk_buff *skb, const struct nfnl_info *info,
continue;
if (tuple_set &&
- (tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
+ (tuple.src.l3num != cur->nfproto ||
+ tuple.dst.protonum != cur->l4proto))
continue;
found = true;
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index be535a261fa0..4ca7964e83c8 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -1527,8 +1527,8 @@ static int tcf_ct_dump_helper(struct sk_buff *skb,
return 0;
if (nla_put_string(skb, TCA_CT_HELPER_NAME, helper->name) ||
- nla_put_u8(skb, TCA_CT_HELPER_FAMILY, helper->tuple.src.l3num) ||
- nla_put_u8(skb, TCA_CT_HELPER_PROTO, helper->tuple.dst.protonum))
+ nla_put_u8(skb, TCA_CT_HELPER_FAMILY, helper->nfproto) ||
+ nla_put_u8(skb, TCA_CT_HELPER_PROTO, helper->l4proto))
return -1;
return 0;
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 10/12] netfilter: conntrack: remove obsolete module parameters
From: Florian Westphal @ 2026-07-02 10:50 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
helper autoassign was removed years ago, all the port numbers are
no longer functional.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/netfilter/nf_conntrack_h323.h | 2 -
include/linux/netfilter/nf_conntrack_pptp.h | 2 -
include/linux/netfilter/nf_conntrack_sane.h | 2 -
include/linux/netfilter/nf_conntrack_tftp.h | 2 -
include/net/netfilter/nf_conntrack_helper.h | 1 -
net/ipv4/netfilter/nf_nat_snmp_basic_main.c | 2 +-
net/netfilter/nf_conntrack_amanda.c | 4 +-
net/netfilter/nf_conntrack_ftp.c | 32 +++++----------
net/netfilter/nf_conntrack_h323_main.c | 10 ++---
net/netfilter/nf_conntrack_helper.c | 6 +--
net/netfilter/nf_conntrack_irc.c | 27 ++++---------
net/netfilter/nf_conntrack_netbios_ns.c | 2 -
net/netfilter/nf_conntrack_pptp.c | 2 +-
net/netfilter/nf_conntrack_sane.c | 34 +++++-----------
net/netfilter/nf_conntrack_sip.c | 45 ++++++---------------
net/netfilter/nf_conntrack_snmp.c | 4 +-
net/netfilter/nf_conntrack_tftp.c | 33 +++++----------
17 files changed, 59 insertions(+), 151 deletions(-)
diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h
index 81286c499325..b15f37604cde 100644
--- a/include/linux/netfilter/nf_conntrack_h323.h
+++ b/include/linux/netfilter/nf_conntrack_h323.h
@@ -9,8 +9,6 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <uapi/linux/netfilter/nf_conntrack_tuple_common.h>
-#define RAS_PORT 1719
-#define Q931_PORT 1720
#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
/* This structure exists only once per master */
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h
index c3bdb4370938..c0b305ce7c3c 100644
--- a/include/linux/netfilter/nf_conntrack_pptp.h
+++ b/include/linux/netfilter/nf_conntrack_pptp.h
@@ -50,8 +50,6 @@ struct nf_nat_pptp {
__be16 pac_call_id; /* NAT'ed PAC call id */
};
-#define PPTP_CONTROL_PORT 1723
-
#define PPTP_PACKET_CONTROL 1
#define PPTP_PACKET_MGMT 2
diff --git a/include/linux/netfilter/nf_conntrack_sane.h b/include/linux/netfilter/nf_conntrack_sane.h
index 46c7acd1b4a7..8501035d7335 100644
--- a/include/linux/netfilter/nf_conntrack_sane.h
+++ b/include/linux/netfilter/nf_conntrack_sane.h
@@ -3,8 +3,6 @@
#define _NF_CONNTRACK_SANE_H
/* SANE tracking. */
-#define SANE_PORT 6566
-
enum sane_state {
SANE_STATE_NORMAL,
SANE_STATE_START_REQUESTED,
diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h
index 90b334bbce3c..e3d1739c557d 100644
--- a/include/linux/netfilter/nf_conntrack_tftp.h
+++ b/include/linux/netfilter/nf_conntrack_tftp.h
@@ -2,8 +2,6 @@
#ifndef _NF_CONNTRACK_TFTP_H
#define _NF_CONNTRACK_TFTP_H
-#define TFTP_PORT 69
-
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/types.h>
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index f3f0c1392e88..bc5427d239f4 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -94,7 +94,6 @@ void nf_conntrack_helper_put(struct nf_conntrack_helper *helper);
void nf_ct_helper_init(struct nf_conntrack_helper *helper,
u8 l3num, u16 protonum, const char *name,
- u16 default_port, u16 spec_port, u32 id,
const struct nf_conntrack_expect_policy *exp_pol,
u32 expect_class_max,
int (*help)(struct sk_buff *skb, unsigned int protoff,
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
index 0ede138dfd29..e540b86bd15b 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
@@ -213,7 +213,7 @@ static int __init nf_nat_snmp_basic_init(void)
RCU_INIT_POINTER(nf_nat_snmp_hook, help);
nf_ct_helper_init(&snmp_trap_helper, AF_INET, IPPROTO_UDP,
- "snmp_trap", SNMP_TRAP_PORT, SNMP_TRAP_PORT, SNMP_TRAP_PORT,
+ "snmp_trap",
&snmp_exp_policy, 0, help, NULL, THIS_MODULE);
err = nf_conntrack_helper_register(&snmp_trap_helper, &snmp_trap_helper_ptr);
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index f10ac2c49f4b..06d6ec12c86d 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -199,10 +199,10 @@ static int __init nf_conntrack_amanda_init(void)
}
nf_ct_helper_init(&amanda_helper[0], AF_INET, IPPROTO_UDP,
- HELPER_NAME, 10080, 10080, 10080,
+ HELPER_NAME,
&amanda_exp_policy, 0, amanda_help, NULL, THIS_MODULE);
nf_ct_helper_init(&amanda_helper[1], AF_INET6, IPPROTO_UDP,
- HELPER_NAME, 10080, 10080, 10080,
+ HELPER_NAME,
&amanda_exp_policy, 0, amanda_help, NULL, THIS_MODULE);
ret = nf_conntrack_helpers_register(amanda_helper,
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 0847f845613d..f3944598c172 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -35,11 +35,6 @@ MODULE_ALIAS("ip_conntrack_ftp");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
static DEFINE_SPINLOCK(nf_ftp_lock);
-#define MAX_PORTS 8
-static u_int16_t ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-
static bool loose;
module_param(loose, bool, 0600);
@@ -560,8 +555,8 @@ static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
return 0;
}
-static struct nf_conntrack_helper ftp[MAX_PORTS * 2] __read_mostly;
-static struct nf_conntrack_helper *ftp_ptr[MAX_PORTS * 2] __read_mostly;
+static struct nf_conntrack_helper ftp __read_mostly;
+static struct nf_conntrack_helper *ftp_ptr __read_mostly;
static const struct nf_conntrack_expect_policy ftp_exp_policy = {
.max_expected = 1,
@@ -570,32 +565,23 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = {
static void __exit nf_conntrack_ftp_fini(void)
{
- nf_conntrack_helpers_unregister(ftp_ptr, ports_c * 2);
+ nf_conntrack_helper_unregister(ftp_ptr);
}
static int __init nf_conntrack_ftp_init(void)
{
- int i, ret = 0;
+ int ret = 0;
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_ftp_master));
- if (ports_c == 0)
- ports[ports_c++] = FTP_PORT;
-
/* FIXME should be configurable whether IPv4 and IPv6 FTP connections
are tracked or not - YK */
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&ftp[2 * i], AF_INET, IPPROTO_TCP,
- HELPER_NAME, FTP_PORT, ports[i], ports[i],
- &ftp_exp_policy, 0, help,
- nf_ct_ftp_from_nlattr, THIS_MODULE);
- nf_ct_helper_init(&ftp[2 * i + 1], AF_INET6, IPPROTO_TCP,
- HELPER_NAME, FTP_PORT, ports[i], ports[i],
- &ftp_exp_policy, 0, help,
- nf_ct_ftp_from_nlattr, THIS_MODULE);
- }
+ nf_ct_helper_init(&ftp, NFPROTO_UNSPEC, IPPROTO_TCP,
+ HELPER_NAME,
+ &ftp_exp_policy, 0, help,
+ nf_ct_ftp_from_nlattr, THIS_MODULE);
- ret = nf_conntrack_helpers_register(ftp, ports_c * 2, ftp_ptr);
+ ret = nf_conntrack_helper_register(&ftp, &ftp_ptr);
if (ret < 0) {
pr_err("failed to register helpers\n");
return ret;
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 37b6314ca772..4cb1665bba02 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -1713,19 +1713,19 @@ static int __init h323_helper_init(void)
int ret;
nf_ct_helper_init(&nf_conntrack_helper_ras[0], AF_INET, IPPROTO_UDP,
- "RAS", RAS_PORT, RAS_PORT, RAS_PORT,
+ "RAS",
&ras_exp_policy, 0, ras_help, NULL, THIS_MODULE);
nf_ct_helper_init(&nf_conntrack_helper_ras[1], AF_INET6, IPPROTO_UDP,
- "RAS", RAS_PORT, RAS_PORT, RAS_PORT,
+ "RAS",
&ras_exp_policy, 0, ras_help, NULL, THIS_MODULE);
nf_ct_helper_init(&nf_conntrack_helper_h245, AF_UNSPEC, IPPROTO_UDP,
- "H.245", 0, 0, 0,
+ "H.245",
&h245_exp_policy, 0, h245_help, NULL, THIS_MODULE);
nf_ct_helper_init(&nf_conntrack_helper_q931[0], AF_INET, IPPROTO_TCP,
- "Q.931", Q931_PORT, Q931_PORT, Q931_PORT,
+ "Q.931",
&q931_exp_policy, 0, q931_help, NULL, THIS_MODULE);
nf_ct_helper_init(&nf_conntrack_helper_q931[1], AF_INET6, IPPROTO_TCP,
- "Q.931", Q931_PORT, Q931_PORT, Q931_PORT,
+ "Q.931",
&q931_exp_policy, 0, q931_help, NULL, THIS_MODULE);
ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245,
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index b28986100db0..506c58034761 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -472,7 +472,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
void nf_ct_helper_init(struct nf_conntrack_helper *helper,
u8 l3num, u16 protonum, const char *name,
- u16 default_port, u16 spec_port, u32 id,
const struct nf_conntrack_expect_policy *exp_pol,
u32 expect_class_max,
int (*help)(struct sk_buff *skb, unsigned int protoff,
@@ -493,10 +492,7 @@ void nf_ct_helper_init(struct nf_conntrack_helper *helper,
snprintf(helper->nat_mod_name, sizeof(helper->nat_mod_name),
NF_NAT_HELPER_PREFIX "%s", name);
- if (spec_port == default_port)
- snprintf(helper->name, sizeof(helper->name), "%s", name);
- else
- snprintf(helper->name, sizeof(helper->name), "%s-%u", name, id);
+ snprintf(helper->name, sizeof(helper->name), "%s", name);
if (WARN_ON_ONCE(expect_class_max >= NF_CT_MAX_EXPECT_CLASSES))
return;
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 193ab34db795..4e6bafe41437 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -21,9 +21,6 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <linux/netfilter/nf_conntrack_irc.h>
-#define MAX_PORTS 8
-static unsigned short ports[MAX_PORTS];
-static unsigned int ports_c;
static unsigned int max_dcc_channels = 8;
static unsigned int dcc_timeout __read_mostly = 300;
/* This is slow, but it's simple. --RR */
@@ -42,8 +39,6 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_conntrack_irc");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-module_param_array(ports, ushort, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "port numbers of IRC servers");
module_param(max_dcc_channels, uint, 0400);
MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
"IRC session");
@@ -254,13 +249,13 @@ static int help(struct sk_buff *skb, unsigned int protoff,
return ret;
}
-static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
-static struct nf_conntrack_helper *irc_ptr[MAX_PORTS] __read_mostly;
+static struct nf_conntrack_helper irc __read_mostly;
+static struct nf_conntrack_helper *irc_ptr __read_mostly;
static struct nf_conntrack_expect_policy irc_exp_policy;
static int __init nf_conntrack_irc_init(void)
{
- int i, ret;
+ int ret;
nf_conntrack_helper_deprecated(HELPER_NAME);
@@ -282,17 +277,11 @@ static int __init nf_conntrack_irc_init(void)
if (!irc_buffer)
return -ENOMEM;
- /* If no port given, default to standard irc port */
- if (ports_c == 0)
- ports[ports_c++] = IRC_PORT;
+ nf_ct_helper_init(&irc, AF_INET, IPPROTO_TCP, HELPER_NAME,
+ &irc_exp_policy,
+ 0, help, NULL, THIS_MODULE);
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&irc[i], AF_INET, IPPROTO_TCP, HELPER_NAME,
- IRC_PORT, ports[i], i, &irc_exp_policy,
- 0, help, NULL, THIS_MODULE);
- }
-
- ret = nf_conntrack_helpers_register(&irc[0], ports_c, irc_ptr);
+ ret = nf_conntrack_helper_register(&irc, &irc_ptr);
if (ret) {
pr_err("failed to register helpers\n");
kfree(irc_buffer);
@@ -304,7 +293,7 @@ static int __init nf_conntrack_irc_init(void)
static void __exit nf_conntrack_irc_fini(void)
{
- nf_conntrack_helpers_unregister(irc_ptr, ports_c);
+ nf_conntrack_helper_unregister(irc_ptr);
kfree(irc_buffer);
}
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 89d1cf7d6512..caa2b101fa9e 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -21,7 +21,6 @@
#include <net/netfilter/nf_conntrack_expect.h>
#define HELPER_NAME "netbios-ns"
-#define NMBD_PORT 137
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
@@ -54,7 +53,6 @@ static int __init nf_conntrack_netbios_ns_init(void)
exp_policy.timeout = timeout;
nf_ct_helper_init(&helper, AF_INET, IPPROTO_UDP, HELPER_NAME,
- NMBD_PORT, NMBD_PORT, NMBD_PORT,
&exp_policy, 0, netbios_ns_help, NULL, THIS_MODULE);
return nf_conntrack_helper_register(&helper, &helper_ptr);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 80fc14c87ddc..cbf32a3cb1f6 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -540,7 +540,7 @@ static int __init nf_conntrack_pptp_init(void)
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_pptp_master));
nf_ct_helper_init(&pptp, AF_INET, IPPROTO_TCP,
- "pptp", PPTP_CONTROL_PORT, PPTP_CONTROL_PORT, PPTP_CONTROL_PORT,
+ "pptp",
&pptp_exp_policy, 0, conntrack_pptp_help, NULL, THIS_MODULE);
pptp.destroy = gre_pptp_destroy_siblings;
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index 39085acf7a71..a0658f69d78f 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -34,11 +34,6 @@ MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>");
MODULE_DESCRIPTION("SANE connection tracking helper");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-#define MAX_PORTS 8
-static u_int16_t ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-
struct sane_request {
__be32 RPC_code;
#define SANE_NET_START 7 /* RPC code */
@@ -169,8 +164,8 @@ static int help(struct sk_buff *skb,
return ret;
}
-static struct nf_conntrack_helper sane[MAX_PORTS * 2] __read_mostly;
-static struct nf_conntrack_helper *sane_ptr[MAX_PORTS * 2] __read_mostly;
+static struct nf_conntrack_helper sane __read_mostly;
+static struct nf_conntrack_helper *sane_ptr __read_mostly;
static const struct nf_conntrack_expect_policy sane_exp_policy = {
.max_expected = 1,
@@ -179,32 +174,21 @@ static const struct nf_conntrack_expect_policy sane_exp_policy = {
static void __exit nf_conntrack_sane_fini(void)
{
- nf_conntrack_helpers_unregister(sane_ptr, ports_c * 2);
+ nf_conntrack_helper_unregister(sane_ptr);
}
static int __init nf_conntrack_sane_init(void)
{
- int i, ret = 0;
+ int ret = 0;
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sane_master));
- if (ports_c == 0)
- ports[ports_c++] = SANE_PORT;
-
- /* FIXME should be configurable whether IPv4 and IPv6 connections
- are tracked or not - YK */
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&sane[2 * i], AF_INET, IPPROTO_TCP,
- HELPER_NAME, SANE_PORT, ports[i], ports[i],
- &sane_exp_policy, 0, help, NULL,
- THIS_MODULE);
- nf_ct_helper_init(&sane[2 * i + 1], AF_INET6, IPPROTO_TCP,
- HELPER_NAME, SANE_PORT, ports[i], ports[i],
- &sane_exp_policy, 0, help, NULL,
- THIS_MODULE);
- }
+ nf_ct_helper_init(&sane, NFPROTO_UNSPEC, IPPROTO_TCP,
+ HELPER_NAME,
+ &sane_exp_policy, 0, help, NULL,
+ THIS_MODULE);
- ret = nf_conntrack_helpers_register(sane, ports_c * 2, sane_ptr);
+ ret = nf_conntrack_helper_register(&sane, &sane_ptr);
if (ret < 0) {
pr_err("failed to register helpers\n");
return ret;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 5ec3a4a4bbd7..d0b85b8ad1e6 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -35,12 +35,6 @@ MODULE_DESCRIPTION("SIP connection tracking helper");
MODULE_ALIAS("ip_conntrack_sip");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-#define MAX_PORTS 8
-static unsigned short ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "port numbers of SIP servers");
-
static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
module_param(sip_timeout, uint, 0600);
MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
@@ -1764,8 +1758,8 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff,
return process_sip_msg(skb, ct, protoff, dataoff, &dptr, &datalen);
}
-static struct nf_conntrack_helper sip[MAX_PORTS * 4] __read_mostly;
-static struct nf_conntrack_helper *sip_ptr[MAX_PORTS * 4] __read_mostly;
+static struct nf_conntrack_helper sip[2] __read_mostly;
+static struct nf_conntrack_helper *sip_ptr[2] __read_mostly;
static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
[SIP_EXPECT_SIGNALLING] = {
@@ -1792,38 +1786,25 @@ static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1
static void __exit nf_conntrack_sip_fini(void)
{
- nf_conntrack_helpers_unregister(sip_ptr, ports_c * 4);
+ nf_conntrack_helpers_unregister(sip_ptr, 2);
}
static int __init nf_conntrack_sip_init(void)
{
- int i, ret;
+ int ret;
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sip_master));
- if (ports_c == 0)
- ports[ports_c++] = SIP_PORT;
-
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp,
- NULL, THIS_MODULE);
- nf_ct_helper_init(&sip[4 * i + 1], AF_INET, IPPROTO_TCP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp,
- NULL, THIS_MODULE);
- nf_ct_helper_init(&sip[4 * i + 2], AF_INET6, IPPROTO_UDP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp,
- NULL, THIS_MODULE);
- nf_ct_helper_init(&sip[4 * i + 3], AF_INET6, IPPROTO_TCP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp,
- NULL, THIS_MODULE);
- }
+ nf_ct_helper_init(&sip[0], NFPROTO_UNSPEC, IPPROTO_UDP,
+ HELPER_NAME,
+ sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp,
+ NULL, THIS_MODULE);
+ nf_ct_helper_init(&sip[1], NFPROTO_UNSPEC, IPPROTO_TCP,
+ HELPER_NAME,
+ sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp,
+ NULL, THIS_MODULE);
- ret = nf_conntrack_helpers_register(sip, ports_c * 4, sip_ptr);
+ ret = nf_conntrack_helpers_register(sip, 2, sip_ptr);
if (ret < 0) {
pr_err("failed to register helpers\n");
return ret;
diff --git a/net/netfilter/nf_conntrack_snmp.c b/net/netfilter/nf_conntrack_snmp.c
index b6fce5703fce..109986d5d55e 100644
--- a/net/netfilter/nf_conntrack_snmp.c
+++ b/net/netfilter/nf_conntrack_snmp.c
@@ -14,8 +14,6 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <linux/netfilter/nf_conntrack_snmp.h>
-#define SNMP_PORT 161
-
MODULE_AUTHOR("Jiri Olsa <jolsa@redhat.com>");
MODULE_DESCRIPTION("SNMP service broadcast connection tracking helper");
MODULE_LICENSE("GPL");
@@ -55,7 +53,7 @@ static int __init nf_conntrack_snmp_init(void)
exp_policy.timeout = timeout;
nf_ct_helper_init(&helper, AF_INET, IPPROTO_UDP,
- "snmp", SNMP_PORT, SNMP_PORT, SNMP_PORT,
+ "snmp",
&exp_policy, 0, snmp_conntrack_help, NULL,
THIS_MODULE);
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index 4393c435aa35..a69559edf9b3 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -26,12 +26,6 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_conntrack_tftp");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-#define MAX_PORTS 8
-static unsigned short ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
-
nf_nat_tftp_hook_fn __rcu *nf_nat_tftp_hook __read_mostly;
EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
@@ -95,8 +89,8 @@ static int tftp_help(struct sk_buff *skb,
return ret;
}
-static struct nf_conntrack_helper tftp[MAX_PORTS * 2] __read_mostly;
-static struct nf_conntrack_helper *tftp_ptr[MAX_PORTS * 2] __read_mostly;
+static struct nf_conntrack_helper tftp __read_mostly;
+static struct nf_conntrack_helper *tftp_ptr __read_mostly;
static const struct nf_conntrack_expect_policy tftp_exp_policy = {
.max_expected = 1,
@@ -105,30 +99,21 @@ static const struct nf_conntrack_expect_policy tftp_exp_policy = {
static void __exit nf_conntrack_tftp_fini(void)
{
- nf_conntrack_helpers_unregister(tftp_ptr, ports_c * 2);
+ nf_conntrack_helper_unregister(tftp_ptr);
}
static int __init nf_conntrack_tftp_init(void)
{
- int i, ret;
+ int ret;
NF_CT_HELPER_BUILD_BUG_ON(0);
- if (ports_c == 0)
- ports[ports_c++] = TFTP_PORT;
-
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&tftp[2 * i], AF_INET, IPPROTO_UDP,
- HELPER_NAME, TFTP_PORT, ports[i], i,
- &tftp_exp_policy, 0, tftp_help, NULL,
- THIS_MODULE);
- nf_ct_helper_init(&tftp[2 * i + 1], AF_INET6, IPPROTO_UDP,
- HELPER_NAME, TFTP_PORT, ports[i], i,
- &tftp_exp_policy, 0, tftp_help, NULL,
- THIS_MODULE);
- }
+ nf_ct_helper_init(&tftp, NFPROTO_UNSPEC, IPPROTO_UDP,
+ HELPER_NAME,
+ &tftp_exp_policy, 0, tftp_help, NULL,
+ THIS_MODULE);
- ret = nf_conntrack_helpers_register(tftp, ports_c * 2, tftp_ptr);
+ ret = nf_conntrack_helper_register(&tftp, &tftp_ptr);
if (ret < 0) {
pr_err("failed to register helpers\n");
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 11/12] netfilter: ebtables: bound num_counters like nentries in do_replace()
From: Florian Westphal @ 2026-07-02 10:50 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
From: Jiayuan Chen <jiayuan.chen@linux.dev>
do_replace_finish() allocates the counter buffer before it is validated:
counterstmp = vmalloc_array(repl->num_counters, sizeof(*counterstmp));
do_replace() only checks num_counters against INT_MAX / sizeof(struct
ebt_counter), so vmalloc_array() can be asked for up to 134217726 * 16 =
2147483616 bytes (~2 GiB).
num_counters must in fact equal nentries: do_replace_finish() later
rejects the request when repl->num_counters != t->private->nentries.
get_counters() folds the per-CPU counters back into one entry per rule,
so what userspace gets is bounded by nentries, never by nentries *
nr_cpus. Apply the same upper bound used for nentries (MAX_EBT_ENTRIES)
to the incoming num_counters so the over-sized allocation can no longer
be requested.
The allocation is still kept outside the ebt_mutex, since vmalloc() may
sleep and trigger reclaim; only the bound is tightened.
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/bridge/netfilter/ebtables.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index f20c039e44c8..042d31278713 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -39,6 +39,8 @@
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
COUNTER_OFFSET(n) * cpu))
+#define MAX_EBT_ENTRIES (((INT_MAX - sizeof(struct ebt_table_info)) / \
+ NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
struct ebt_pernet {
struct list_head tables;
@@ -1124,10 +1126,9 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
return -EINVAL;
/* overflow check */
- if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
- NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
+ if (tmp.nentries >= MAX_EBT_ENTRIES)
return -ENOMEM;
- if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
+ if (tmp.num_counters >= MAX_EBT_ENTRIES)
return -ENOMEM;
tmp.name[sizeof(tmp.name) - 1] = 0;
@@ -2265,10 +2266,9 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
if (tmp.entries_size == 0)
return -EINVAL;
- if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
- NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
+ if (tmp.nentries >= MAX_EBT_ENTRIES)
return -ENOMEM;
- if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
+ if (tmp.num_counters >= MAX_EBT_ENTRIES)
return -ENOMEM;
memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 12/12] netfilter: nft_ct: support expectation creation for natted flows
From: Florian Westphal @ 2026-07-02 10:50 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
In-Reply-To: <20260702105003.13550-1-fw@strlen.de>
This feature only works for connections originating from the host
and only if there no source address rewrite.
Add the needed nat glue to have the expectation follow the original
nat binding.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nft_ct.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 03a88c77e0f0..358b9287e12e 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -1297,6 +1297,17 @@ static int nft_ct_expect_obj_dump(struct sk_buff *skb,
return 0;
}
+#if IS_ENABLED(CONFIG_NF_NAT)
+static void nft_ct_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this)
+{
+ const struct nf_ct_helper_expectfn *expfn;
+
+ expfn = nf_ct_helper_expectfn_find_by_name("nat-follow-master");
+ if (expfn)
+ expfn->expectfn(ct, this);
+}
+#endif
+
static void nft_ct_expect_obj_eval(struct nft_object *obj,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
@@ -1342,6 +1353,13 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
priv->l4proto, NULL, &priv->dport);
exp->timeout += priv->timeout;
+#if IS_ENABLED(CONFIG_NF_NAT)
+ if (ct->status & IPS_NAT_MASK) {
+ exp->saved_proto.tcp.port = priv->dport;
+ exp->dir = !dir;
+ exp->expectfn = nft_ct_nat_follow_master;
+ }
+#endif
if (nf_ct_expect_related(exp, 0) != 0)
regs->verdict.code = NF_DROP;
@@ -1375,6 +1393,13 @@ static struct nft_object_type nft_ct_expect_obj_type __read_mostly = {
.owner = THIS_MODULE,
};
+#if IS_ENABLED(CONFIG_NF_NAT)
+static struct nf_ct_helper_expectfn nft_ct_nat __read_mostly = {
+ .name = "nft_ct-follow-master",
+ .expectfn = nft_ct_nat_follow_master,
+};
+#endif
+
static int __init nft_ct_module_init(void)
{
int err;
@@ -1400,6 +1425,9 @@ static int __init nft_ct_module_init(void)
err = nft_register_obj(&nft_ct_timeout_obj_type);
if (err < 0)
goto err4;
+#endif
+#if IS_ENABLED(CONFIG_NF_NAT)
+ nf_ct_helper_expectfn_register(&nft_ct_nat);
#endif
return 0;
@@ -1425,6 +1453,13 @@ static void __exit nft_ct_module_exit(void)
nft_unregister_obj(&nft_ct_helper_obj_type);
nft_unregister_expr(&nft_notrack_type);
nft_unregister_expr(&nft_ct_type);
+
+#if IS_ENABLED(CONFIG_NF_NAT)
+ nf_ct_helper_expectfn_unregister(&nft_ct_nat);
+ synchronize_rcu();
+ nf_ct_helper_expectfn_destroy(&nft_ct_nat);
+ synchronize_rcu();
+#endif
}
module_init(nft_ct_module_init);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH bpf v3 3/4] selftests/bpf: Adapt sockmap update error handling
From: Jakub Sitnicki @ 2026-07-02 10:52 UTC (permalink / raw)
To: Michal Luczaj
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan,
John Fastabend, Jiayuan Chen, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, David S. Miller, Jakub Kicinski,
Simon Horman, Cong Wang, bpf, linux-kselftest, linux-kernel,
netdev
In-Reply-To: <20260702-sockmap-lookup-udp-leak-v3-3-ff8de8782468@rbox.co>
On Thu, Jul 02, 2026 at 01:28 AM +02, Michal Luczaj wrote:
> Update sockmap_listen to accommodate the recent change in sockmap that
> rejects unbound UDP sockets.
>
> TCP: Reject unbound and bound (unless established or listening).
> UDP: Accept only bound sockets.
>
> While at it, migrate to ASSERT_* and enforce reverse xmas tree.
>
> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
> Signed-off-by: Michal Luczaj <mhal@rbox.co>
> ---
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
^ permalink raw reply
* RE: [PATCH net v4] rtase: Workaround for TX hang caused by short UDP packets entering hardware PTP parsing
From: Justin Lai @ 2026-07-02 10:52 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem@davemloft.net, edumazet@google.com, pabeni@redhat.com,
andrew+netdev@lunn.ch, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, stable@vger.kernel.org, horms@kernel.org,
richardcochran@gmail.com, david.laight.linux@gmail.com,
aleksander.lobakin@intel.com, Ping-Ke Shih, Larry Chiu
In-Reply-To: <20260630020126.2366786-1-kuba@kernel.org>
Jakub Kicinski <kuba@kernel.org> wrote:
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> rtase: Workaround for TX hang caused by short UDP packets entering
> hardware PTP parsing
>
> This commit attempts to work around a hardware TX hang caused by
> out-of-bounds
> reads during PTP parsing. It introduces logic to pad short UDP packets to a
> minimum transport data length before transmission.
>
> > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > index 255667775f0e8..944ffe71b2d07 100644
> > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> [ ... ]
> > +static bool rtase_get_udp_offset(struct sk_buff *skb, u32 *udp_offset)
> > +{
> > + struct ipv6hdr *i6h, _i6h;
> > + struct iphdr *ih, _ih;
> > + __be16 proto;
> > + u32 no;
> > +
> > + if (!rtase_get_l3_proto(skb, &proto, &no))
> > + return false;
> > +
> > + switch (proto) {
> > + case htons(ETH_P_IP):
> > + ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
> > + if (!ih)
> > + return false;
>
> [Severity: High]
> Does this skip the padding workaround if the IP header itself is truncated?
>
> If the packet is shorter than the IP header (e.g., less than 34 bytes),
> skb_header_pointer() will return false. This causes rtase_skb_pad() to
> return true, allowing the packet to skip padding. Could this small unpadded
> packet still trigger the hardware parser and cause the TX hang?
>
Thanks for pointing this out.
A truncated IPv4 header can also trigger the same hardware TX hang
issue.
We'll update the workaround to handle this case as well.
We'll also update the commit message to document this hardware
limitation.
> [ ... ]
> > +static bool rtase_skb_pad(struct sk_buff *skb)
> > +{
> > + __be16 *dest, _dest;
> > + u32 trans_data_len;
> > + u32 udp_offset;
> > + u16 dest_port;
> > + u32 pad_len;
> > +
> > + if (!rtase_get_udp_offset(skb, &udp_offset))
> > + return true;
> > +
> > + if (udp_offset > skb->len)
> > + return false;
> > +
> > + trans_data_len = skb->len - udp_offset;
> > + if (trans_data_len < offsetof(struct udphdr, len) ||
> > + trans_data_len >= RTASE_MIN_PAD_LEN)
> > + return true;
>
> [Severity: High]
> Can an attacker bypass the workaround if the transport payload is very small?
>
> By returning true when trans_data_len is less than
> offsetof(struct udphdr, len) (which is 4 bytes), the packet is passed to
> the hardware unpadded.
>
> If an attacker sends an IPv4 non-initial fragment with a very small payload,
> the hardware parser might identify the fragment as UDP and attempt to read
> the
> destination port at offset 2 from the payload. If this out-of-bounds read
> hits residual uninitialized memory in the TX FIFO containing PTP port values
> (319 or 320), the hardware could incorrectly classify it as a PTP packet,
> continue parsing out of bounds, and trigger the TX hang.
>
Thanks for the review.
The hardware fetches packet data according to the packet length
specified in the TX descriptor, so it does not fetch residual data
beyond the end of the packet during DMA.
The affected out-of-bounds access occurs after the packet has already
matched the PTP classification criteria (UDP destination port 319/320)
and entered the hardware PTP parsing path.
If the transport data is shorter than the destination port field
itself, the packet cannot match the affected PTP classification path,
so padding is not required for this case.
> > +
> > + dest = skb_header_pointer(skb,
> --
> pw-bot: cr
^ permalink raw reply
* Re: [PATCH net-next v3 06/15] net: macb: allocate tieoff descriptor once across device lifetime
From: Nicolai Buchwitz @ 2026-07-02 10:54 UTC (permalink / raw)
To: Théo Lebrun
Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
Maxime Chevallier
In-Reply-To: <20260701-macb-context-v3-6-00268d5b1502@bootlin.com>
Hi Théo
On 1.7.2026 17:59, Théo Lebrun wrote:
> The tieoff descriptor is a RX DMA descriptor ring of size one. It gets
> configured onto queues for Wake-on-LAN during system-wide suspend when
> hardware does not support disabling individual queues
> (MACB_CAPS_QUEUE_DISABLE).
>
> MACB/GEM driver allocates it alongside the main RX ring
> inside macb_alloc() at open. Free is done by macb_free() at close.
>
> Change to allocate once at probe and free on probe failure or device
> removal. This makes the tieoff descriptor lifetime much longer,
> avoiding repeating coherent buffer allocation on each open/close cycle.
>
> Main benefit: we dissociate its lifetime from the main ring's lifetime.
> That way there is less work to be doing on resources (re)alloc. This
> currently happens on close/open, but will soon also happen on context
> swap operations (set_ringparam, change_mtu, set_channels, etc).
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> drivers/net/ethernet/cadence/macb_main.c | 75
> +++++++++++++++++---------------
> 1 file changed, 41 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb_main.c
> b/drivers/net/ethernet/cadence/macb_main.c
> index 8b52122bc134..951a7f080225 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> [...]
> static void macb_init_rings(struct macb *bp)
> @@ -2832,8 +2801,6 @@ static void macb_init_rings(struct macb *bp)
> bp->queues[0].tx_head = 0;
> bp->queues[0].tx_tail = 0;
> desc->ctrl |= MACB_BIT(TX_WRAP);
> -
> - macb_init_tieoff(bp);
> }
>
> static void macb_reset_hw(struct macb *bp)
> @@ -5518,6 +5485,38 @@ static int eyeq5_init(struct platform_device
> *pdev)
> return ret;
> }
>
> +static int macb_alloc_tieoff(struct macb *bp)
> +{
> + /* Tieoff is a workaround in case HW cannot disable queues, for PM.
> */
> + if (bp->caps & MACB_CAPS_QUEUE_DISABLE)
> + return 0;
Before, the tieoff was allocated in macb_alloc(), which the at91ether
path
never called. Now it's allocated from macb_probe() for all variants,
gated only
on MACB_CAPS_QUEUE_DISABLE, so EMAC gets a coherent descriptor it never
uses.
Add MACB_CAPS_MACB_IS_EMAC to the if statement?
> [...]
Thanks
Nicolai
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox