[nf,v2] netfilter: nf_flow_table: do not remove offload when other netns's interface is down

Message ID 20181011184629.28016-1-ap420073@gmail.com
State Accepted
Delegated to: Pablo Neira
Headers show
Series
  • [nf,v2] netfilter: nf_flow_table: do not remove offload when other netns's interface is down
Related show

Commit Message

Taehee Yoo Oct. 11, 2018, 6:46 p.m.
When interface is down, offload cleanup function(nf_flow_table_do_cleanup)
is called and that checks whether interface index of offload and
index of link down interface is same. but only interface index checking
is not enough because flowtable is not pernet list.
So that, if other netns's interface that has index is same with offload
is down, that offload will be removed.
This patch adds netns checking code to the offload cleanup routine.

Fixes: 59c466dd68e7 ("netfilter: nf_flow_table: add a new flow state for tearing down offloading")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2: do not modify unnecessary code (Pablo Neira Ayuso)
v1: Initial patch

 net/netfilter/nf_flow_table_core.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

Comments

Pablo Neira Ayuso Oct. 19, 2018, 11:31 a.m. | #1
On Fri, Oct 12, 2018 at 03:46:29AM +0900, Taehee Yoo wrote:
> When interface is down, offload cleanup function(nf_flow_table_do_cleanup)
> is called and that checks whether interface index of offload and
> index of link down interface is same. but only interface index checking
> is not enough because flowtable is not pernet list.
> So that, if other netns's interface that has index is same with offload
> is down, that offload will be removed.
> This patch adds netns checking code to the offload cleanup routine.

Applied, thanks!

Patch

diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index d8125616edc7..c188e27972c7 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -478,14 +478,17 @@  EXPORT_SYMBOL_GPL(nf_flow_table_init);
 static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data)
 {
 	struct net_device *dev = data;
+	struct flow_offload_entry *e;
+
+	e = container_of(flow, struct flow_offload_entry, flow);
 
 	if (!dev) {
 		flow_offload_teardown(flow);
 		return;
 	}
-
-	if (flow->tuplehash[0].tuple.iifidx == dev->ifindex ||
-	    flow->tuplehash[1].tuple.iifidx == dev->ifindex)
+	if (net_eq(nf_ct_net(e->ct), dev_net(dev)) &&
+	    (flow->tuplehash[0].tuple.iifidx == dev->ifindex ||
+	     flow->tuplehash[1].tuple.iifidx == dev->ifindex))
 		flow_offload_dead(flow);
 }