[Devel] [PATCH RHEL7 COMMIT] net/netfilter: do not pretend nf_hook_ops->priv is always valid
Konstantin Khorenko
khorenko at virtuozzo.com
Sun May 3 10:56:53 MSK 2020
The commit is pushed to "branch-rh7-3.10.0-1127.vz7.150.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1127.vz7.150.6
------>
commit 078421bbd20ada20c1f140f8ab0592cd6faa3f9e
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date: Sun May 3 10:50:25 2020 +0300
net/netfilter: do not pretend nf_hook_ops->priv is always valid
1) it's unsafe to consider nf_hook_ops->priv always filled in
nf_nat_ipv{4,6}_fn() until we do all checks
2) we better don't add extra checks for net correctness in every
call of nf_nat_ipv{4,6}_fn() - we need them only on conntrack
configuration stage.
=> move check for proper netns under IP_CT_NEW case.
Fixes: 5ff26bf49074a net/netfilter: make nft NAT working in different
netns simultaneously
https://jira.sw.ru/browse/PSBM-103718
https://jira.sw.ru/browse/PSBM-102728
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 21 +++++++++++----------
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 21 +++++++++++----------
2 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
index fa880d189bed3..de977be995f5e 100644
--- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
@@ -252,11 +252,6 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
/* maniptype == SRC for postrouting. */
enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
- const struct nft_chain *chain = ops->priv;
- const struct net *chain_net =
- read_pnet(&nft_base_chain(chain)->pnet);
- const struct net *net;
-
/* We never see fragments: conntrack defrags on pre-routing
* and local-out, and nf_nat_out protects post-routing.
*/
@@ -271,11 +266,6 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (!ct)
return NF_ACCEPT;
- /* Ignore chains that are not for the current network namespace */
- net = nf_ct_net(ct);
- if (!net_eq(net, chain_net))
- return NF_ACCEPT;
-
/* Don't try to NAT if this packet is not conntracked */
if (nf_ct_is_untracked(ct))
return NF_ACCEPT;
@@ -300,8 +290,19 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
* or local packets.
*/
if (!nf_nat_initialized(ct, maniptype)) {
+ const struct nft_chain *chain = ops->priv;
+ const struct net *chain_net =
+ read_pnet(&nft_base_chain(chain)->pnet);
+ const struct net *net;
unsigned int ret;
+ /* Ignore chains that are not for the current network
+ * namespace
+ */
+ net = nf_ct_net(ct);
+ if (!net_eq(net, chain_net))
+ return NF_ACCEPT;
+
ret = do_chain(ops, skb, state, ct);
if (ret != NF_ACCEPT)
return ret;
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
index f369123f89246..a0804157e12b2 100644
--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
@@ -265,11 +265,6 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
int hdrlen;
u8 nexthdr;
- const struct nft_chain *chain = ops->priv;
- const struct net *chain_net =
- read_pnet(&nft_base_chain(chain)->pnet);
- const struct net *net;
-
ct = nf_ct_get(skb, &ctinfo);
/* Can't track? It's not due to stress, or conntrack would
* have dropped it. Hence it's the user's responsibilty to
@@ -279,11 +274,6 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (!ct)
return NF_ACCEPT;
- /* Ignore chains that are not for the current network namespace */
- net = nf_ct_net(ct);
- if (!net_eq(net, chain_net))
- return NF_ACCEPT;
-
/* Don't try to NAT if this packet is not conntracked */
if (nf_ct_is_untracked(ct))
return NF_ACCEPT;
@@ -313,8 +303,19 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
* or local packets.
*/
if (!nf_nat_initialized(ct, maniptype)) {
+ const struct nft_chain *chain = ops->priv;
+ const struct net *chain_net =
+ read_pnet(&nft_base_chain(chain)->pnet);
+ const struct net *net;
unsigned int ret;
+ /* Ignore chains that are not for the current network
+ * namespace
+ */
+ net = nf_ct_net(ct);
+ if (!net_eq(net, chain_net))
+ return NF_ACCEPT;
+
ret = do_chain(ops, skb, state, ct);
if (ret != NF_ACCEPT)
return ret;
More information about the Devel
mailing list