From 6d891adf390dd232c63fa77a8e71750495c04159 Mon Sep 17 00:00:00 2001 From: Ritaro Takenaka Date: Wed, 25 May 2022 15:55:48 +0900 Subject: [PATCH] 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 --- ...owtable-add-check_dst-in-packet-path.patch | 97 +++++++++++++++++++ .../hack-5.4/647-netfilter-flow-acct.patch | 8 +- .../650-netfilter-add-xt_OFFLOAD-target.patch | 6 +- ...w_table-add-hardware-offload-support.patch | 18 ++-- ...w_table-support-hw-offload-through-v.patch | 2 +- ...w_table-rework-hardware-offload-time.patch | 4 +- ...low_table-rework-private-driver-data.patch | 2 +- ...-support-hardware-flow-table-offload.patch | 4 +- 8 files changed, 119 insertions(+), 22 deletions(-) create mode 100644 target/linux/generic/backport-5.4/610-v5.18-netfilter-flowtable-add-check_dst-in-packet-path.patch diff --git a/target/linux/generic/backport-5.4/610-v5.18-netfilter-flowtable-add-check_dst-in-packet-path.patch b/target/linux/generic/backport-5.4/610-v5.18-netfilter-flowtable-add-check_dst-in-packet-path.patch new file mode 100644 index 0000000000..8413f03714 --- /dev/null +++ b/target/linux/generic/backport-5.4/610-v5.18-netfilter-flowtable-add-check_dst-in-packet-path.patch @@ -0,0 +1,97 @@ +From 94936600fce68845edea66ae6d06ad12d6469e0b Mon Sep 17 00:00:00 2001 +From: Ritaro Takenaka +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 +--- + 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; + } diff --git a/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch b/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch index f9480d59d1..9f7ca61546 100644 --- a/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch +++ b/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch @@ -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 #include -@@ -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); diff --git a/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch b/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch index d584cb5c6c..0da4ad4432 100644 --- a/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch +++ b/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch @@ -536,7 +536,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -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 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 +#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; } diff --git a/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch b/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch index 1dbf49a97f..6192df9319 100644 --- a/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch +++ b/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch @@ -77,7 +77,7 @@ Signed-off-by: Pablo Neira Ayuso }; 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 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 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 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 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 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 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 } 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 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); diff --git a/target/linux/generic/pending-5.4/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch b/target/linux/generic/pending-5.4/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch index b808c0257d..ae9f7f0d83 100644 --- a/target/linux/generic/pending-5.4/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch +++ b/target/linux/generic/pending-5.4/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau 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 { }; }; diff --git a/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch b/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch index 3c44c29273..f4efbcdda8 100644 --- a/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch +++ b/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch @@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau --- 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 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); diff --git a/target/linux/generic/pending-5.4/646-netfilter-nf_flow_table-rework-private-driver-data.patch b/target/linux/generic/pending-5.4/646-netfilter-nf_flow_table-rework-private-driver-data.patch index 159ad8a0aa..235f2a3710 100644 --- a/target/linux/generic/pending-5.4/646-netfilter-nf_flow_table-rework-private-driver-data.patch +++ b/target/linux/generic/pending-5.4/646-netfilter-nf_flow_table-rework-private-driver-data.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- 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; diff --git a/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch index 91aae5b65c..369a09caac 100644 --- a/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch +++ b/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- 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 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; -- 2.30.2