]>
Commit | Line | Data |
---|---|---|
91861a69 SL |
1 | From 5ec68ba789d9d8803c8a394c1eac68027009262d Mon Sep 17 00:00:00 2001 |
2 | From: Florian Westphal <fw@strlen.de> | |
3 | Date: Fri, 11 Jan 2019 14:46:15 +0100 | |
4 | Subject: netfilter: physdev: relax br_netfilter dependency | |
5 | ||
6 | [ Upstream commit 8e2f311a68494a6677c1724bdcb10bada21af37c ] | |
7 | ||
8 | Following command: | |
9 | iptables -D FORWARD -m physdev ... | |
10 | causes connectivity loss in some setups. | |
11 | ||
12 | Reason is that iptables userspace will probe kernel for the module revision | |
13 | of the physdev patch, and physdev has an artificial dependency on | |
14 | br_netfilter (xt_physdev use makes no sense unless a br_netfilter module | |
15 | is loaded). | |
16 | ||
17 | This causes the "phydev" module to be loaded, which in turn enables the | |
18 | "call-iptables" infrastructure. | |
19 | ||
20 | bridged packets might then get dropped by the iptables ruleset. | |
21 | ||
22 | The better fix would be to change the "call-iptables" defaults to 0 and | |
23 | enforce explicit setting to 1, but that breaks backwards compatibility. | |
24 | ||
25 | This does the next best thing: add a request_module call to checkentry. | |
26 | This was a stray '-D ... -m physdev' won't activate br_netfilter | |
27 | anymore. | |
28 | ||
29 | Signed-off-by: Florian Westphal <fw@strlen.de> | |
30 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> | |
31 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
32 | --- | |
33 | include/net/netfilter/br_netfilter.h | 1 - | |
34 | net/bridge/br_netfilter_hooks.c | 5 ----- | |
35 | net/netfilter/xt_physdev.c | 9 +++++++-- | |
36 | 3 files changed, 7 insertions(+), 8 deletions(-) | |
37 | ||
38 | diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h | |
39 | index e8d1448425a7..b1d0d46344e2 100644 | |
40 | --- a/include/net/netfilter/br_netfilter.h | |
41 | +++ b/include/net/netfilter/br_netfilter.h | |
42 | @@ -42,7 +42,6 @@ static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) | |
43 | } | |
44 | ||
45 | struct net_device *setup_pre_routing(struct sk_buff *skb); | |
46 | -void br_netfilter_enable(void); | |
47 | ||
48 | #if IS_ENABLED(CONFIG_IPV6) | |
49 | int br_validate_ipv6(struct net *net, struct sk_buff *skb); | |
50 | diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c | |
51 | index 6def85d75b1d..93b5525bcccf 100644 | |
52 | --- a/net/bridge/br_netfilter_hooks.c | |
53 | +++ b/net/bridge/br_netfilter_hooks.c | |
54 | @@ -873,11 +873,6 @@ static const struct nf_br_ops br_ops = { | |
55 | .br_dev_xmit_hook = br_nf_dev_xmit, | |
56 | }; | |
57 | ||
58 | -void br_netfilter_enable(void) | |
59 | -{ | |
60 | -} | |
61 | -EXPORT_SYMBOL_GPL(br_netfilter_enable); | |
62 | - | |
63 | /* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because | |
64 | * br_dev_queue_push_xmit is called afterwards */ | |
65 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { | |
66 | diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c | |
67 | index 1caaccbc306c..7e4063621960 100644 | |
68 | --- a/net/netfilter/xt_physdev.c | |
69 | +++ b/net/netfilter/xt_physdev.c | |
70 | @@ -96,8 +96,7 @@ match_outdev: | |
71 | static int physdev_mt_check(const struct xt_mtchk_param *par) | |
72 | { | |
73 | const struct xt_physdev_info *info = par->matchinfo; | |
74 | - | |
75 | - br_netfilter_enable(); | |
76 | + static bool brnf_probed __read_mostly; | |
77 | ||
78 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || | |
79 | info->bitmask & ~XT_PHYSDEV_OP_MASK) | |
80 | @@ -113,6 +112,12 @@ static int physdev_mt_check(const struct xt_mtchk_param *par) | |
81 | if (par->hook_mask & (1 << NF_INET_LOCAL_OUT)) | |
82 | return -EINVAL; | |
83 | } | |
84 | + | |
85 | + if (!brnf_probed) { | |
86 | + brnf_probed = true; | |
87 | + request_module("br_netfilter"); | |
88 | + } | |
89 | + | |
90 | return 0; | |
91 | } | |
92 | ||
93 | -- | |
94 | 2.19.1 | |
95 |