mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-20 22:23:27 +00:00
kernel: check dst of flow offloading table
Flow offload dst can become invalid after the route cache is created. dst_check() in packet path is necessary to prevent packet drop. Signed-off-by: Ritaro Takenaka <ritarot634@gmail.com>
This commit is contained in:
parent
78b7515c2e
commit
6d891adf39
@ -0,0 +1,97 @@
|
||||
From 94936600fce68845edea66ae6d06ad12d6469e0b Mon Sep 17 00:00:00 2001
|
||||
From: Ritaro Takenaka <ritarot634@gmail.com>
|
||||
Date: Tue, 31 May 2022 00:25:08 +0900
|
||||
Subject: [PATCH] netfilter: flowtable: add check_dst in packet path
|
||||
|
||||
Flow offload dst can become invalid after the route cache is created.
|
||||
dst_check() in packet path is necessary to prevent packet drop.
|
||||
|
||||
[ Upstream commit 2738d9d963bd1f06d5114c2b4fa5771a95703991
|
||||
8b9229d15877ec77775633f058d14145f6eb98fa
|
||||
e5075c0badaaac245a6fa0b4625b5cd714d8ade3 ]
|
||||
|
||||
Signed-off-by: Ritaro Takenaka <ritarot634@gmail.com>
|
||||
---
|
||||
include/net/netfilter/nf_flow_table.h | 5 ++++-
|
||||
net/netfilter/nf_flow_table_core.c | 13 +++++++++++++
|
||||
net/netfilter/nf_flow_table_ip.c | 12 ++----------
|
||||
3 files changed, 19 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -56,7 +56,10 @@ struct flow_offload_tuple {
|
||||
|
||||
u16 mtu;
|
||||
|
||||
- struct dst_entry *dst_cache;
|
||||
+ struct {
|
||||
+ struct dst_entry *dst_cache;
|
||||
+ u32 dst_cookie;
|
||||
+ };
|
||||
};
|
||||
|
||||
struct flow_offload_tuple_rhash {
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -23,6 +23,18 @@ struct flow_offload_entry {
|
||||
static DEFINE_MUTEX(flowtable_lock);
|
||||
static LIST_HEAD(flowtables);
|
||||
|
||||
+static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)
|
||||
+{
|
||||
+ const struct rt6_info *rt;
|
||||
+
|
||||
+ if (flow_tuple->l3proto == NFPROTO_IPV6) {
|
||||
+ rt = (const struct rt6_info *)flow_tuple->dst_cache;
|
||||
+ return rt6_get_cookie(rt);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
|
||||
struct nf_flow_route *route,
|
||||
@@ -55,6 +67,7 @@ flow_offload_fill_dir(struct flow_offloa
|
||||
|
||||
ft->iifidx = other_dst->dev->ifindex;
|
||||
ft->dst_cache = dst;
|
||||
+ ft->dst_cookie = flow_offload_dst_cookie(ft);
|
||||
}
|
||||
|
||||
struct flow_offload *
|
||||
--- a/net/netfilter/nf_flow_table_ip.c
|
||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||
@@ -215,14 +215,6 @@ static bool nf_flow_exceeds_mtu(const st
|
||||
return true;
|
||||
}
|
||||
|
||||
-static int nf_flow_offload_dst_check(struct dst_entry *dst)
|
||||
-{
|
||||
- if (unlikely(dst_xfrm(dst)))
|
||||
- return dst_check(dst, 0) ? 0 : -1;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
|
||||
const struct nf_hook_state *state,
|
||||
struct dst_entry *dst)
|
||||
@@ -273,7 +265,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
|
||||
return NF_ACCEPT;
|
||||
|
||||
- if (nf_flow_offload_dst_check(&rt->dst)) {
|
||||
+ if (!dst_check(&rt->dst, 0)) {
|
||||
flow_offload_teardown(flow);
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
@@ -500,7 +492,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
sizeof(*ip6h)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
- if (nf_flow_offload_dst_check(&rt->dst)) {
|
||||
+ if (!dst_check(&rt->dst, tuplehash->tuple.dst_cookie)) {
|
||||
flow_offload_teardown(flow);
|
||||
return NF_ACCEPT;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -160,6 +160,8 @@ struct nf_flow_table_hw {
|
||||
@@ -163,6 +163,8 @@ struct nf_flow_table_hw {
|
||||
int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload);
|
||||
void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload);
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
struct flow_offload_entry {
|
||||
struct flow_offload flow;
|
||||
@@ -164,6 +165,22 @@ void flow_offload_free(struct flow_offlo
|
||||
@@ -177,6 +178,22 @@ void flow_offload_free(struct flow_offlo
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(flow_offload_free);
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
/* For layer 4 checksum field offset. */
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
@@ -296,6 +297,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
@@ -288,6 +289,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
skb->dev = outdev;
|
||||
nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
|
||||
skb_dst_set_noref(skb, &rt->dst);
|
||||
@ -60,7 +60,7 @@
|
||||
neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb);
|
||||
|
||||
return NF_STOLEN;
|
||||
@@ -526,6 +528,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
@@ -518,6 +520,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
skb->dev = outdev;
|
||||
nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
|
||||
skb_dst_set_noref(skb, &rt->dst);
|
||||
|
@ -536,7 +536,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
#include <net/netfilter/nf_flow_table.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
@@ -338,8 +337,7 @@ flow_offload_lookup(struct nf_flowtable
|
||||
@@ -351,8 +350,7 @@ flow_offload_lookup(struct nf_flowtable
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(flow_offload_lookup);
|
||||
|
||||
@ -546,7 +546,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
void (*iter)(struct flow_offload *flow, void *data),
|
||||
void *data)
|
||||
{
|
||||
@@ -372,6 +370,7 @@ nf_flow_table_iterate(struct nf_flowtabl
|
||||
@@ -385,6 +383,7 @@ nf_flow_table_iterate(struct nf_flowtabl
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -576,7 +576,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+#endif /* _XT_FLOWOFFLOAD_H */
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -130,6 +130,10 @@ static inline void flow_offload_dead(str
|
||||
@@ -133,6 +133,10 @@ static inline void flow_offload_dead(str
|
||||
flow->flags |= FLOW_OFFLOAD_DYING;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
};
|
||||
|
||||
enum flow_offload_tuple_dir {
|
||||
@@ -68,6 +74,7 @@ struct flow_offload_tuple_rhash {
|
||||
@@ -71,6 +77,7 @@ struct flow_offload_tuple_rhash {
|
||||
#define FLOW_OFFLOAD_DNAT 0x2
|
||||
#define FLOW_OFFLOAD_DYING 0x4
|
||||
#define FLOW_OFFLOAD_TEARDOWN 0x8
|
||||
@ -85,7 +85,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
struct flow_offload {
|
||||
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
|
||||
@@ -120,6 +127,22 @@ unsigned int nf_flow_offload_ip_hook(voi
|
||||
@@ -123,6 +130,22 @@ unsigned int nf_flow_offload_ip_hook(voi
|
||||
unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state);
|
||||
|
||||
@ -156,7 +156,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -248,10 +248,16 @@ static inline bool nf_flow_has_expired(c
|
||||
@@ -261,10 +261,16 @@ static inline bool nf_flow_has_expired(c
|
||||
return nf_flow_timeout_delta(flow->timeout) <= 0;
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
rhashtable_remove_fast(&flow_table->rhashtable,
|
||||
&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node,
|
||||
@@ -271,6 +277,9 @@ static void flow_offload_del(struct nf_f
|
||||
@@ -284,6 +290,9 @@ static void flow_offload_del(struct nf_f
|
||||
if (!(flow->flags & FLOW_OFFLOAD_TEARDOWN))
|
||||
flow_offload_fixup_ct_state(e->ct);
|
||||
|
||||
@ -183,7 +183,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
flow_offload_free(flow);
|
||||
}
|
||||
|
||||
@@ -361,6 +370,9 @@ static void nf_flow_offload_gc_step(stru
|
||||
@@ -374,6 +383,9 @@ static void nf_flow_offload_gc_step(stru
|
||||
if (!teardown)
|
||||
nf_ct_offload_timeout(flow);
|
||||
|
||||
@ -193,7 +193,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (nf_flow_has_expired(flow) || teardown)
|
||||
flow_offload_del(flow_table, flow);
|
||||
}
|
||||
@@ -490,10 +502,43 @@ int nf_flow_dnat_port(const struct flow_
|
||||
@@ -503,10 +515,43 @@ int nf_flow_dnat_port(const struct flow_
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_flow_dnat_port);
|
||||
|
||||
@ -237,7 +237,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc);
|
||||
|
||||
err = rhashtable_init(&flowtable->rhashtable,
|
||||
@@ -534,6 +579,8 @@ static void nf_flow_table_iterate_cleanu
|
||||
@@ -547,6 +592,8 @@ static void nf_flow_table_iterate_cleanu
|
||||
{
|
||||
nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev);
|
||||
flush_delayed_work(&flowtable->gc_work);
|
||||
@ -246,7 +246,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
|
||||
void nf_flow_table_cleanup(struct net_device *dev)
|
||||
@@ -547,6 +594,26 @@ void nf_flow_table_cleanup(struct net_de
|
||||
@@ -560,6 +607,26 @@ void nf_flow_table_cleanup(struct net_de
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_flow_table_cleanup);
|
||||
|
||||
@ -273,7 +273,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
void nf_flow_table_free(struct nf_flowtable *flow_table)
|
||||
{
|
||||
mutex_lock(&flowtable_lock);
|
||||
@@ -556,9 +623,58 @@ void nf_flow_table_free(struct nf_flowta
|
||||
@@ -569,9 +636,58 @@ void nf_flow_table_free(struct nf_flowta
|
||||
nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
|
||||
nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, flow_table);
|
||||
rhashtable_destroy(&flow_table->rhashtable);
|
||||
|
@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
int (*ndo_get_phys_port_id)(struct net_device *dev,
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -85,6 +85,21 @@ struct flow_offload {
|
||||
@@ -88,6 +88,21 @@ struct flow_offload {
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -75,6 +75,7 @@ struct flow_offload_tuple_rhash {
|
||||
@@ -78,6 +78,7 @@ struct flow_offload_tuple_rhash {
|
||||
#define FLOW_OFFLOAD_DYING 0x4
|
||||
#define FLOW_OFFLOAD_TEARDOWN 0x8
|
||||
#define FLOW_OFFLOAD_HW 0x10
|
||||
@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -370,7 +370,7 @@ static void nf_flow_offload_gc_step(stru
|
||||
@@ -383,7 +383,7 @@ static void nf_flow_offload_gc_step(stru
|
||||
if (!teardown)
|
||||
nf_ct_offload_timeout(flow);
|
||||
|
||||
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -80,9 +80,10 @@ struct flow_offload_tuple_rhash {
|
||||
@@ -83,9 +83,10 @@ struct flow_offload_tuple_rhash {
|
||||
struct flow_offload {
|
||||
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
|
||||
u32 flags;
|
||||
|
@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -90,6 +90,7 @@ struct flow_offload {
|
||||
@@ -93,6 +93,7 @@ struct flow_offload {
|
||||
#define FLOW_OFFLOAD_PATH_ETHERNET BIT(0)
|
||||
#define FLOW_OFFLOAD_PATH_VLAN BIT(1)
|
||||
#define FLOW_OFFLOAD_PATH_PPPOE BIT(2)
|
||||
@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
struct flow_offload_hw_path {
|
||||
struct net_device *dev;
|
||||
@@ -100,6 +101,7 @@ struct flow_offload_hw_path {
|
||||
@@ -103,6 +104,7 @@ struct flow_offload_hw_path {
|
||||
u16 vlan_proto;
|
||||
u16 vlan_id;
|
||||
u16 pppoe_sid;
|
||||
|
Loading…
Reference in New Issue
Block a user