From 028b3d8d549e276ffa34835aeb2c2a18c98e7ca3 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Tue, 30 Apr 2019 01:55:29 +0900 Subject: netfilter: nf_flow_table: fix netdev refcnt leak [ Upstream commit 26a302afbe328ecb7507cae2035d938e6635131b ] flow_offload_alloc() calls nf_route() to get a dst_entry. Internally, nf_route() calls ip_route_output_key() that allocates a dst_entry and holds it. So, a dst_entry should be released by dst_release() if nf_route() is successful. Otherwise, netns exit routine cannot be finished and the following message is printed: [ 257.490952] unregister_netdevice: waiting for lo to become free. Usage count = 1 Fixes: ac2a66665e23 ("netfilter: add generic flow table infrastructure") Signed-off-by: Taehee Yoo Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nft_flow_offload.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/netfilter/nft_flow_offload.c') diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index 436cc14cfc59..7f85af4c40ff 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c @@ -113,6 +113,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, if (ret < 0) goto err_flow_add; + dst_release(route.tuple[!dir].dst); return; err_flow_add: -- cgit v1.2.3 From 48f611ecea0e67ba2065074e2c0f20bfcb860f85 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 21 May 2019 13:24:31 +0200 Subject: netfilter: nft_flow_offload: set liberal tracking mode for tcp commit 8437a6209f76f85a2db1abb12a9bde2170801617 upstream. Without it, whenever a packet has to be pushed up the stack (e.g. because of mtu mismatch), then conntrack will flag packets as invalid, which in turn breaks NAT. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nft_flow_offload.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net/netfilter/nft_flow_offload.c') diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index 7f85af4c40ff..b63729350d97 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c @@ -72,6 +72,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, struct nf_flow_route route; struct flow_offload *flow; enum ip_conntrack_dir dir; + bool is_tcp = false; struct nf_conn *ct; int ret; @@ -84,6 +85,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { case IPPROTO_TCP: + is_tcp = true; + break; case IPPROTO_UDP: break; default: @@ -109,6 +112,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, if (!flow) goto err_flow_alloc; + if (is_tcp) { + ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; + ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; + } + ret = flow_offload_add(flowtable, flow); if (ret < 0) goto err_flow_add; -- cgit v1.2.3 From 041c181e6ba0f6d30c29ac5c6a4ec5ad52cc2fca Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 21 May 2019 13:24:32 +0200 Subject: netfilter: nft_flow_offload: don't offload when sequence numbers need adjustment commit 91a9048f238063dde7feea752b9dd386f7e3808b upstream. We can't deal with tcp sequence number rewrite in flow_offload. While at it, simplify helper check, we only need to know if the extension is present, we don't need the helper data. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nft_flow_offload.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net/netfilter/nft_flow_offload.c') diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index b63729350d97..256cccd093e1 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c @@ -12,7 +12,6 @@ #include #include #include -#include struct nft_flow_offload { struct nft_flowtable *flowtable; @@ -67,7 +66,6 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, { struct nft_flow_offload *priv = nft_expr_priv(expr); struct nf_flowtable *flowtable = &priv->flowtable->data; - const struct nf_conn_help *help; enum ip_conntrack_info ctinfo; struct nf_flow_route route; struct flow_offload *flow; @@ -93,8 +91,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, goto out; } - help = nfct_help(ct); - if (help) + if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || + ct->status & IPS_SEQ_ADJUST) goto out; if (ctinfo == IP_CT_NEW || -- cgit v1.2.3 From c549680ed59b4f829c1c84a56fcca8a2f7e460d2 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 21 May 2019 13:24:33 +0200 Subject: netfilter: nft_flow_offload: IPCB is only valid for ipv4 family commit 69aeb538587e087bfc81dd1f465eab3558ff3158 upstream. Guard this with a check vs. ipv4, IPCB isn't valid in ipv6 case. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nft_flow_offload.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'net/netfilter/nft_flow_offload.c') diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index 256cccd093e1..6e0c26025ab1 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c @@ -48,15 +48,20 @@ static int nft_flow_route(const struct nft_pktinfo *pkt, return 0; } -static bool nft_flow_offload_skip(struct sk_buff *skb) +static bool nft_flow_offload_skip(struct sk_buff *skb, int family) { - struct ip_options *opt = &(IPCB(skb)->opt); - - if (unlikely(opt->optlen)) - return true; if (skb_sec_path(skb)) return true; + if (family == NFPROTO_IPV4) { + const struct ip_options *opt; + + opt = &(IPCB(skb)->opt); + + if (unlikely(opt->optlen)) + return true; + } + return false; } @@ -74,7 +79,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, struct nf_conn *ct; int ret; - if (nft_flow_offload_skip(pkt->skb)) + if (nft_flow_offload_skip(pkt->skb, nft_pf(pkt))) goto out; ct = nf_ct_get(pkt->skb, &ctinfo); -- cgit v1.2.3