[Devel] [PATCH rh7 v3 1/1] net/netfilter: handle case when nft_do_chain() is called for wrong netns

Konstantin Khorenko khorenko at virtuozzo.com
Wed May 6 15:31:34 MSK 2020


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 <khorenko at virtuozzo.com>
---
 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



More information about the Devel mailing list