Skip to content

Commit b13db0d

Browse files
ummakynesgregkh
authored andcommitted
netfilter: br_netfilter: skip conntrack input hook for promisc packets
[ Upstream commit 751de20 ] For historical reasons, when bridge device is in promisc mode, packets that are directed to the taps follow bridge input hook path. This patch adds a workaround to reset conntrack for these packets. Jianbo Liu reports warning splats in their test infrastructure where cloned packets reach the br_netfilter input hook to confirm the conntrack object. Scratch one bit from BR_INPUT_SKB_CB to annotate that this packet has reached the input hook because it is passed up to the bridge device to reach the taps. [ 57.571874] WARNING: CPU: 1 PID: 0 at net/bridge/br_netfilter_hooks.c:616 br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.572749] Modules linked in: xt_MASQUERADE nf_conntrack_netlink nfnetlink iptable_nat xt_addrtype xt_conntrack nf_nat br_netfilter rpcsec_gss_krb5 auth_rpcgss oid_registry overlay rpcrdma rdma_ucm ib_iser libiscsi scsi_transport_isc si ib_umad rdma_cm ib_ipoib iw_cm ib_cm mlx5_ib ib_uverbs ib_core mlx5ctl mlx5_core [ 57.575158] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.8.0+ starfive-tech#19 [ 57.575700] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [ 57.576662] RIP: 0010:br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.577195] Code: fe ff ff 41 bd 04 00 00 00 be 04 00 00 00 e9 4a ff ff ff be 04 00 00 00 48 89 ef e8 f3 a9 3c e1 66 83 ad b4 00 00 00 04 eb 91 <0f> 0b e9 f1 fe ff ff 0f 0b e9 df fe ff ff 48 89 df e8 b3 53 47 e1 [ 57.578722] RSP: 0018:ffff88885f845a08 EFLAGS: 00010202 [ 57.579207] RAX: 0000000000000002 RBX: ffff88812dfe8000 RCX: 0000000000000000 [ 57.579830] RDX: ffff88885f845a60 RSI: ffff8881022dc300 RDI: 0000000000000000 [ 57.580454] RBP: ffff88885f845a60 R08: 0000000000000001 R09: 0000000000000003 [ 57.581076] R10: 00000000ffff1300 R11: 0000000000000002 R12: 0000000000000000 [ 57.581695] R13: ffff8881047ffe00 R14: ffff888108dbee00 R15: ffff88814519b800 [ 57.582313] FS: 0000000000000000(0000) GS:ffff88885f840000(0000) knlGS:0000000000000000 [ 57.583040] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 57.583564] CR2: 000000c4206aa000 CR3: 0000000103847001 CR4: 0000000000370eb0 [ 57.584194] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 57.584820] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 57.585440] Call Trace: [ 57.585721] <IRQ> [ 57.585976] ? __warn+0x7d/0x130 [ 57.586323] ? br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.586811] ? report_bug+0xf1/0x1c0 [ 57.587177] ? handle_bug+0x3f/0x70 [ 57.587539] ? exc_invalid_op+0x13/0x60 [ 57.587929] ? asm_exc_invalid_op+0x16/0x20 [ 57.588336] ? br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.588825] nf_hook_slow+0x3d/0xd0 [ 57.589188] ? br_handle_vlan+0x4b/0x110 [ 57.589579] br_pass_frame_up+0xfc/0x150 [ 57.589970] ? br_port_flags_change+0x40/0x40 [ 57.590396] br_handle_frame_finish+0x346/0x5e0 [ 57.590837] ? ipt_do_table+0x32e/0x430 [ 57.591221] ? br_handle_local_finish+0x20/0x20 [ 57.591656] br_nf_hook_thresh+0x4b/0xf0 [br_netfilter] [ 57.592286] ? br_handle_local_finish+0x20/0x20 [ 57.592802] br_nf_pre_routing_finish+0x178/0x480 [br_netfilter] [ 57.593348] ? br_handle_local_finish+0x20/0x20 [ 57.593782] ? nf_nat_ipv4_pre_routing+0x25/0x60 [nf_nat] [ 57.594279] br_nf_pre_routing+0x24c/0x550 [br_netfilter] [ 57.594780] ? br_nf_hook_thresh+0xf0/0xf0 [br_netfilter] [ 57.595280] br_handle_frame+0x1f3/0x3d0 [ 57.595676] ? br_handle_local_finish+0x20/0x20 [ 57.596118] ? br_handle_frame_finish+0x5e0/0x5e0 [ 57.596566] __netif_receive_skb_core+0x25b/0xfc0 [ 57.597017] ? __napi_build_skb+0x37/0x40 [ 57.597418] __netif_receive_skb_list_core+0xfb/0x220 Fixes: 62e7151 ("netfilter: bridge: confirm multicast packets before passing them up the stack") Reported-by: Jianbo Liu <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent df7c0fb commit b13db0d

File tree

4 files changed

+28
-8
lines changed

4 files changed

+28
-8
lines changed

net/bridge/br_input.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
3030
return netif_receive_skb(skb);
3131
}
3232

33-
static int br_pass_frame_up(struct sk_buff *skb)
33+
static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
3434
{
3535
struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
3636
struct net_bridge *br = netdev_priv(brdev);
@@ -65,6 +65,8 @@ static int br_pass_frame_up(struct sk_buff *skb)
6565
br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb),
6666
BR_MCAST_DIR_TX);
6767

68+
BR_INPUT_SKB_CB(skb)->promisc = promisc;
69+
6870
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
6971
dev_net(indev), NULL, skb, indev, NULL,
7072
br_netif_receive_skb);
@@ -82,6 +84,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
8284
struct net_bridge_mcast *brmctx;
8385
struct net_bridge_vlan *vlan;
8486
struct net_bridge *br;
87+
bool promisc;
8588
u16 vid = 0;
8689
u8 state;
8790

@@ -120,7 +123,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
120123
if (p->flags & BR_LEARNING)
121124
br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0);
122125

123-
local_rcv = !!(br->dev->flags & IFF_PROMISC);
126+
promisc = !!(br->dev->flags & IFF_PROMISC);
127+
local_rcv = promisc;
128+
124129
if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
125130
/* by definition the broadcast is also a multicast address */
126131
if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {
@@ -183,7 +188,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
183188
unsigned long now = jiffies;
184189

185190
if (test_bit(BR_FDB_LOCAL, &dst->flags))
186-
return br_pass_frame_up(skb);
191+
return br_pass_frame_up(skb, false);
187192

188193
if (now != dst->used)
189194
dst->used = now;
@@ -196,7 +201,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
196201
}
197202

198203
if (local_rcv)
199-
return br_pass_frame_up(skb);
204+
return br_pass_frame_up(skb, promisc);
200205

201206
out:
202207
return 0;
@@ -368,6 +373,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
368373
goto forward;
369374
}
370375

376+
BR_INPUT_SKB_CB(skb)->promisc = false;
377+
371378
/* The else clause should be hit when nf_hook():
372379
* - returns < 0 (drop/error)
373380
* - returns = 0 (stolen/nf_queue)

net/bridge/br_netfilter_hooks.c

+6
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,17 @@ static unsigned int br_nf_local_in(void *priv,
600600
struct sk_buff *skb,
601601
const struct nf_hook_state *state)
602602
{
603+
bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
603604
struct nf_conntrack *nfct = skb_nfct(skb);
604605
const struct nf_ct_hook *ct_hook;
605606
struct nf_conn *ct;
606607
int ret;
607608

609+
if (promisc) {
610+
nf_reset_ct(skb);
611+
return NF_ACCEPT;
612+
}
613+
608614
if (!nfct || skb->pkt_type == PACKET_HOST)
609615
return NF_ACCEPT;
610616

net/bridge/br_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ struct br_input_skb_cb {
559559
#endif
560560
u8 proxyarp_replied:1;
561561
u8 src_port_isolated:1;
562+
u8 promisc:1;
562563
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
563564
u8 vlan_filtered:1;
564565
#endif

net/bridge/netfilter/nf_conntrack_bridge.c

+10-4
Original file line numberDiff line numberDiff line change
@@ -294,18 +294,24 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
294294
static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb,
295295
const struct nf_hook_state *state)
296296
{
297-
enum ip_conntrack_info ctinfo;
297+
bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
298+
struct nf_conntrack *nfct = skb_nfct(skb);
298299
struct nf_conn *ct;
299300

300-
if (skb->pkt_type == PACKET_HOST)
301+
if (promisc) {
302+
nf_reset_ct(skb);
303+
return NF_ACCEPT;
304+
}
305+
306+
if (!nfct || skb->pkt_type == PACKET_HOST)
301307
return NF_ACCEPT;
302308

303309
/* nf_conntrack_confirm() cannot handle concurrent clones,
304310
* this happens for broad/multicast frames with e.g. macvlan on top
305311
* of the bridge device.
306312
*/
307-
ct = nf_ct_get(skb, &ctinfo);
308-
if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
313+
ct = container_of(nfct, struct nf_conn, ct_general);
314+
if (nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
309315
return NF_ACCEPT;
310316

311317
/* let inet prerouting call conntrack again */

0 commit comments

Comments
 (0)