All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nf] netfilter: bridge: ebt_redirect: don't assume bridge port exists
@ 2026-06-01  9:50 Florian Westphal
  2026-06-01 10:29 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 3+ messages in thread
From: Florian Westphal @ 2026-06-01  9:50 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal, Hacking

ebt_redirect_tg() dereferences br_port_get_rcu() return without a
NULL check, causing a kernel panic when the bridge port has been
removed between the original hook invocation and an NFQUEUE
reinject.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Hacking <eilaimemedsnaimel@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/bridge/netfilter/ebt_redirect.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 307790562b49..379662961aeb 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -20,16 +20,25 @@ static unsigned int
 ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct ebt_redirect_info *info = par->targinfo;
+	const unsigned char *dev_addr;
 
 	if (skb_ensure_writable(skb, 0))
 		return EBT_DROP;
 
-	if (xt_hooknum(par) != NF_BR_BROUTING)
-		/* rcu_read_lock()ed by nf_hook_thresh */
-		ether_addr_copy(eth_hdr(skb)->h_dest,
-				br_port_get_rcu(xt_in(par))->br->dev->dev_addr);
-	else
-		ether_addr_copy(eth_hdr(skb)->h_dest, xt_in(par)->dev_addr);
+	if (xt_hooknum(par) != NF_BR_BROUTING) {
+		const struct net_bridge_port *port;
+
+		port = br_port_get_rcu(xt_in(par));
+		if (!port)
+			return EBT_DROP;
+
+		dev_addr = port->br->dev->dev_addr;
+	} else {
+		dev_addr = xt_in(par)->dev_addr;
+	}
+
+	ether_addr_copy(eth_hdr(skb)->h_dest, dev_addr);
+
 	skb->pkt_type = PACKET_HOST;
 	return info->target;
 }
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH nf] netfilter: bridge: ebt_redirect: don't assume bridge port exists
  2026-06-01  9:50 [PATCH nf] netfilter: bridge: ebt_redirect: don't assume bridge port exists Florian Westphal
@ 2026-06-01 10:29 ` Pablo Neira Ayuso
  2026-06-01 10:31   ` Florian Westphal
  0 siblings, 1 reply; 3+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-01 10:29 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel, Hacking

Hi Florian,

On Mon, Jun 01, 2026 at 11:50:00AM +0200, Florian Westphal wrote:
> ebt_redirect_tg() dereferences br_port_get_rcu() return without a
> NULL check, causing a kernel panic when the bridge port has been
> removed between the original hook invocation and an NFQUEUE
> reinject.

Maybe more candidates for the same pattern?

net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
net/netfilter/nfnetlink_log.c:                                   htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
net/netfilter/nfnetlink_log.c:                                   htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
net/netfilter/nfnetlink_queue.c:                                         htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
net/netfilter/nfnetlink_queue.c:                                         htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))

So this can be fix in one patch?

Thanks

> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Reported-by: Hacking <eilaimemedsnaimel@gmail.com>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  net/bridge/netfilter/ebt_redirect.c | 21 +++++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
> index 307790562b49..379662961aeb 100644
> --- a/net/bridge/netfilter/ebt_redirect.c
> +++ b/net/bridge/netfilter/ebt_redirect.c
> @@ -20,16 +20,25 @@ static unsigned int
>  ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
>  {
>  	const struct ebt_redirect_info *info = par->targinfo;
> +	const unsigned char *dev_addr;
>  
>  	if (skb_ensure_writable(skb, 0))
>  		return EBT_DROP;
>  
> -	if (xt_hooknum(par) != NF_BR_BROUTING)
> -		/* rcu_read_lock()ed by nf_hook_thresh */
> -		ether_addr_copy(eth_hdr(skb)->h_dest,
> -				br_port_get_rcu(xt_in(par))->br->dev->dev_addr);
> -	else
> -		ether_addr_copy(eth_hdr(skb)->h_dest, xt_in(par)->dev_addr);
> +	if (xt_hooknum(par) != NF_BR_BROUTING) {
> +		const struct net_bridge_port *port;
> +
> +		port = br_port_get_rcu(xt_in(par));
> +		if (!port)
> +			return EBT_DROP;
> +
> +		dev_addr = port->br->dev->dev_addr;
> +	} else {
> +		dev_addr = xt_in(par)->dev_addr;
> +	}
> +
> +	ether_addr_copy(eth_hdr(skb)->h_dest, dev_addr);
> +
>  	skb->pkt_type = PACKET_HOST;
>  	return info->target;
>  }
> -- 
> 2.54.0
> 
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH nf] netfilter: bridge: ebt_redirect: don't assume bridge port exists
  2026-06-01 10:29 ` Pablo Neira Ayuso
@ 2026-06-01 10:31   ` Florian Westphal
  0 siblings, 0 replies; 3+ messages in thread
From: Florian Westphal @ 2026-06-01 10:31 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel, Hacking

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> Hi Florian,
> 
> On Mon, Jun 01, 2026 at 11:50:00AM +0200, Florian Westphal wrote:
> > ebt_redirect_tg() dereferences br_port_get_rcu() return without a
> > NULL check, causing a kernel panic when the bridge port has been
> > removed between the original hook invocation and an NFQUEUE
> > reinject.
> 
> Maybe more candidates for the same pattern?

Did not find any, but I only searched in net/bridge/netfilter.

Will send a v2.

> net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
> net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
> net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);
> net/bridge/netfilter/nft_reject_bridge.c:       br_forward(br_port_get_rcu(dev), nskb, false, true);

br_forward(NULL, .. is safe.

> net/netfilter/nfnetlink_log.c:                                   htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
> net/netfilter/nfnetlink_log.c:                                   htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
> net/netfilter/nfnetlink_queue.c:                                         htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
> net/netfilter/nfnetlink_queue.c:                                         htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))

Those aren't.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-06-01 10:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-01  9:50 [PATCH nf] netfilter: bridge: ebt_redirect: don't assume bridge port exists Florian Westphal
2026-06-01 10:29 ` Pablo Neira Ayuso
2026-06-01 10:31   ` Florian Westphal

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.