When nf_nat_ipv4.ko is not loaded, l3proto is NULL pointer. If the csum_recalc function of l3proto is called, it will cause NULL pointer access issue.
--- v3: add space after return type for Patch 3/3 v2: modify commit message for Patch 3/3 ---
Florian Westphal (2): netfilter: nat: remove csum_recalc hook netfilter: nat: fix udp checksum corruption
Zhengchao Shao (1): netfilter: nat: fix kabi change
include/net/netfilter/nf_nat_l3proto.h | 4 ++ net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 19 ------ net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 19 ------ net/netfilter/Makefile | 2 +- net/netfilter/nf_nat_helper.c | 12 ++-- net/netfilter/nf_nat_proto.c | 74 ++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 47 deletions(-) create mode 100644 net/netfilter/nf_nat_proto.c
From: Florian Westphal fw@strlen.de
mainline inclusion from mainline-v5.1-rc1 commit dac3fe72596f91011afc649a9d181b18466dd895 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7O0PV CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
We can now use direct calls.
Signed-off-by: Florian Westphal fw@strlen.de Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org
Conflicts: include/net/netfilter/nf_nat_l3proto.h net/ipv4/netfilter/nf_nat_l3proto_ipv4.c net/ipv6/netfilter/nf_nat_l3proto_ipv6.c net/netfilter/Makefile net/netfilter/nf_nat_helper.c net/netfilter/nf_nat_proto.c
Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com --- include/net/netfilter/nf_nat_l3proto.h | 8 +-- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 19 ------ net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 19 ------ net/netfilter/Makefile | 2 +- net/netfilter/nf_nat_helper.c | 12 ++-- net/netfilter/nf_nat_proto.c | 74 ++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 51 deletions(-) create mode 100644 net/netfilter/nf_nat_proto.c
diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index d300b8f03972..6e649db8bbec 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -22,10 +22,6 @@ struct nf_nat_l3proto { const struct nf_conntrack_tuple *t, enum nf_nat_manip_type maniptype);
- void (*csum_recalc)(struct sk_buff *skb, u8 proto, - void *data, __sum16 *check, - int datalen, int oldlen); - void (*decode_session)(struct sk_buff *skb, const struct nf_conn *ct, enum ip_conntrack_dir dir, @@ -54,4 +50,8 @@ void nf_nat_l3proto_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops int nf_nat_l3proto_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops); void nf_nat_l3proto_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops);
+void nf_nat_csum_recalc(struct sk_buff *skb, + u8 nfproto, u8 proto, void *data, __sum16 *check, + int datalen, int oldlen); + #endif /* _NF_NAT_L3PROTO_H */ diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index 290a04820701..7beb622bd2af 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -123,24 +123,6 @@ static void nf_nat_ipv4_csum_update(struct sk_buff *skb, inet_proto_csum_replace4(check, skb, oldip, newip, true); }
-static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, - u8 proto, void *data, __sum16 *check, - int datalen, int oldlen) -{ - if (skb->ip_summed != CHECKSUM_PARTIAL) { - const struct iphdr *iph = ip_hdr(skb); - - skb->ip_summed = CHECKSUM_PARTIAL; - skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + - ip_hdrlen(skb); - skb->csum_offset = (void *)check - data; - *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, - proto, 0); - } else - inet_proto_csum_replace2(check, skb, - htons(oldlen), htons(datalen), true); -} - #if IS_ENABLED(CONFIG_NF_CT_NETLINK) static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], struct nf_nat_range2 *range) @@ -165,7 +147,6 @@ static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { .secure_port = nf_nat_ipv4_secure_port, .manip_pkt = nf_nat_ipv4_manip_pkt, .csum_update = nf_nat_ipv4_csum_update, - .csum_recalc = nf_nat_ipv4_csum_recalc, #if IS_ENABLED(CONFIG_NF_CT_NETLINK) .nlattr_to_range = nf_nat_ipv4_nlattr_to_range, #endif diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index 2160936e5b91..747018f2613c 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -131,24 +131,6 @@ static void nf_nat_ipv6_csum_update(struct sk_buff *skb, newip->s6_addr32, true); }
-static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, - u8 proto, void *data, __sum16 *check, - int datalen, int oldlen) -{ - if (skb->ip_summed != CHECKSUM_PARTIAL) { - const struct ipv6hdr *ipv6h = ipv6_hdr(skb); - - skb->ip_summed = CHECKSUM_PARTIAL; - skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + - (data - (void *)skb->data); - skb->csum_offset = (void *)check - data; - *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, - datalen, proto, 0); - } else - inet_proto_csum_replace2(check, skb, - htons(oldlen), htons(datalen), true); -} - #if IS_ENABLED(CONFIG_NF_CT_NETLINK) static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], struct nf_nat_range2 *range) @@ -175,7 +157,6 @@ static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { .in_range = nf_nat_ipv6_in_range, .manip_pkt = nf_nat_ipv6_manip_pkt, .csum_update = nf_nat_ipv6_csum_update, - .csum_recalc = nf_nat_ipv6_csum_recalc, #if IS_ENABLED(CONFIG_NF_CT_NETLINK) .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, #endif diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 16895e045b66..802352d12766 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -48,7 +48,7 @@ obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ - nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o + nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o nf_nat_proto.o
# NAT protocols (nf_nat) nf_nat-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o diff --git a/net/netfilter/nf_nat_helper.c b/net/netfilter/nf_nat_helper.c index 99606baedda4..b96d4eb8d002 100644 --- a/net/netfilter/nf_nat_helper.c +++ b/net/netfilter/nf_nat_helper.c @@ -98,7 +98,6 @@ bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb, const char *rep_buffer, unsigned int rep_len, bool adjust) { - const struct nf_nat_l3proto *l3proto; struct tcphdr *tcph; int oldlen, datalen;
@@ -120,9 +119,8 @@ bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
datalen = skb->len - protoff;
- l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); - l3proto->csum_recalc(skb, IPPROTO_TCP, tcph, &tcph->check, - datalen, oldlen); + nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP, + tcph, &tcph->check, datalen, oldlen);
if (adjust && rep_len != match_len) nf_ct_seqadj_set(ct, ctinfo, tcph->seq, @@ -152,7 +150,6 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, const char *rep_buffer, unsigned int rep_len) { - const struct nf_nat_l3proto *l3proto; struct udphdr *udph; int datalen, oldlen;
@@ -178,9 +175,8 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) return true;
- l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); - l3proto->csum_recalc(skb, IPPROTO_UDP, udph, &udph->check, - datalen, oldlen); + nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP, + udph, &udph->check, datalen, oldlen);
return true; } diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c new file mode 100644 index 000000000000..a4b68557b0f9 --- /dev/null +++ b/net/netfilter/nf_nat_proto.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team coreteam@netfilter.org + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/ipv6.h> +#include <linux/netfilter_ipv6.h> +#include <net/checksum.h> +#include <net/ip6_checksum.h> +#include <net/ip6_route.h> +#include <net/xfrm.h> +#include <net/ipv6.h> + +static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, + u8 proto, void *data, __sum16 *check, + int datalen, int oldlen) +{ + if (skb->ip_summed != CHECKSUM_PARTIAL) { + const struct iphdr *iph = ip_hdr(skb); + + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + + ip_hdrlen(skb); + skb->csum_offset = (void *)check - data; + *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, + proto, 0); + } else { + inet_proto_csum_replace2(check, skb, + htons(oldlen), htons(datalen), true); + } +} + +#if IS_ENABLED(CONFIG_IPV6) +static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, + u8 proto, void *data, __sum16 *check, + int datalen, int oldlen) +{ + if (skb->ip_summed != CHECKSUM_PARTIAL) { + const struct ipv6hdr *ipv6h = ipv6_hdr(skb); + + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + + (data - (void *)skb->data); + skb->csum_offset = (void *)check - data; + *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, + datalen, proto, 0); + } else { + inet_proto_csum_replace2(check, skb, + htons(oldlen), htons(datalen), true); + } +} +#endif + +void nf_nat_csum_recalc(struct sk_buff *skb, + u8 nfproto, u8 proto, void *data, __sum16 *check, + int datalen, int oldlen) +{ + switch (nfproto) { + case NFPROTO_IPV4: + nf_nat_ipv4_csum_recalc(skb, proto, data, check, + datalen, oldlen); + return; +#if IS_ENABLED(CONFIG_IPV6) + case NFPROTO_IPV6: + nf_nat_ipv6_csum_recalc(skb, proto, data, check, + datalen, oldlen); + return; +#endif + } + + WARN_ON_ONCE(1); +}
From: Florian Westphal fw@strlen.de
mainline inclusion from mainline-v5.2-rc3 commit 6bac76db1da3cb162c425d58ae421486f8e43955 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7O0PV CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Due to copy&paste error nf_nat_mangle_udp_packet passes IPPROTO_TCP, resulting in incorrect udp checksum when payload had to be mangled.
Fixes: dac3fe72596f9 ("netfilter: nat: remove csum_recalc hook") Reported-by: Marc Haber mh+netdev@zugschlus.de Tested-by: Marc Haber mh+netdev@zugschlus.de Signed-off-by: Florian Westphal fw@strlen.de Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com --- net/netfilter/nf_nat_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nf_nat_helper.c b/net/netfilter/nf_nat_helper.c index b96d4eb8d002..73cdb887a428 100644 --- a/net/netfilter/nf_nat_helper.c +++ b/net/netfilter/nf_nat_helper.c @@ -175,7 +175,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) return true;
- nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP, + nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_UDP, udph, &udph->check, datalen, oldlen);
return true;
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7O0PV CVE: NA
--------------------------------
fix kabi change
Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com --- include/net/netfilter/nf_nat_l3proto.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index 6e649db8bbec..cece34d0ec1c 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -22,6 +22,10 @@ struct nf_nat_l3proto { const struct nf_conntrack_tuple *t, enum nf_nat_manip_type maniptype);
+ void (*csum_recalc)(struct sk_buff *skb, u8 proto, + void *data, __sum16 *check, + int datalen, int oldlen); + void (*decode_session)(struct sk_buff *skb, const struct nf_conn *ct, enum ip_conntrack_dir dir,
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/1831 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/S...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/1831 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/S...