nf_nat_ipv{4,6}_fn() functions must notice when do_chain()
(== nft_do_chain()) is called for a skb with netns which does not suit
the chain netns and do not call nf_nat_alloc_null_binding() in that
case.

So introduce a new error code for nft_do_chain() to return
and check it in nf_nat_ipv{4,6}_fn().

https://jira.sw.ru/browse/PSBM-102728
https://jira.sw.ru/browse/PSBM-103746

Signed-off-by: Konstantin Khorenko <[email protected]>
---
 include/uapi/linux/netfilter.h           | 4 ++++
 net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 2 ++
 net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 2 ++
 net/netfilter/nf_tables_core.c           | 2 +-
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
index 750c04e41b6d2..4ab88a112d381 100644
--- a/include/uapi/linux/netfilter.h
+++ b/include/uapi/linux/netfilter.h
@@ -14,11 +14,15 @@
 #define NF_QUEUE 3
 #define NF_REPEAT 4
 #define NF_STOP 5
+/* NF_WRONG_NETNS is to be used only in nft_do_chain() only */
+#define NF_WRONG_NETNS (NF_VERDICT_MASK - 1)
+/* NF_MAX_VERDICT value is left untouched on purpose */
 #define NF_MAX_VERDICT NF_STOP
 
 /* we overload the higher bits for encoding auxiliary data such as the queue
  * number or errno values. Not nice, but better than additional function
  * arguments. */
+/* If NF_VERDICT_MASK gets changed, check NF_WRONG_NETNS value */
 #define NF_VERDICT_MASK 0x000000ff
 
 /* extra verdict flags have mask 0x0000ff00 */
diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c 
b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
index 3b8b048ffc6cb..4522a01271868 100644
--- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
@@ -292,6 +292,8 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct 
sk_buff *skb,
                        unsigned int ret;
 
                        ret = do_chain(ops, skb, state, ct);
+                       if (ret == NF_WRONG_NETNS)
+                               return NF_ACCEPT;
                        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 540dc0fdaf102..ebca2c4e3e57a 100644
--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
@@ -305,6 +305,8 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct 
sk_buff *skb,
                        unsigned int ret;
 
                        ret = do_chain(ops, skb, state, ct);
+                       if (ret == NF_WRONG_NETNS)
+                               return NF_ACCEPT;
                        if (ret != NF_ACCEPT)
                                return ret;
 
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 81ccbca32fa8a..d2c96afb1ace1 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -134,7 +134,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct 
nf_hook_ops *ops)
 
        /* Ignore chains that are not for the current network namespace */
        if (!net_eq(net, chain_net))
-               return NF_ACCEPT;
+               return NF_WRONG_NETNS;
 
        info.trace = false;
        if (static_key_false(&nft_trace_enabled))
-- 
2.15.1

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to