mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
ipvs: return the csum validation for forward hook
Sashiko notes that playing games with the skb dst and rt
flags instead of providing hooknum is not a good idea
when validating the checksums.
Also, skipping checksum validation for FORWARD packets
risk silent data corruption, even if the only user is
the FTP-CMD packets coming from the real server.
Sashiko also noticed that by using common checksum
helper in the previous commit we actually fixed old bug
where the TCP/UDP checksum for IPv6 on CHECKSUM_COMPLETE
was not validated correctly.
Fixes: e876b75b90 ("ipvs: fix the checksum validations")
Link: https://sashiko.dev/#/patchset/20260722211420.153933-1-pablo%40netfilter.org
Link: https://sashiko.dev/#/patchset/20260727185024.67534-1-ja%40ssi.bg
Link: https://sashiko.dev/#/patchset/20260728202520.59179-1-ja%40ssi.bg
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
646922a037
commit
99609cb0aa
|
|
@ -25,9 +25,7 @@
|
|||
#include <linux/netfilter.h> /* for union nf_inet_addr */
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h> /* for struct ipv6hdr */
|
||||
#include <net/route.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/ip6_fib.h>
|
||||
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#endif
|
||||
|
|
@ -2095,30 +2093,23 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
|
|||
return csum_partial(diff, sizeof(diff), oldsum);
|
||||
}
|
||||
|
||||
static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
|
||||
static inline bool ip_vs_checksum_needed(struct sk_buff *skb)
|
||||
{
|
||||
/* Checksum unnecessary or already validated? */
|
||||
if (skb_csum_unnecessary(skb))
|
||||
return false;
|
||||
/* LOCAL_OUT ? */
|
||||
if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
|
||||
/* Locally generated ? */
|
||||
if (!skb->dev)
|
||||
return false;
|
||||
/* !LOCAL_IN (FORWARD) ? */
|
||||
if (af == AF_INET6) {
|
||||
if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
|
||||
return false;
|
||||
} else {
|
||||
if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
|
||||
int offset, int proto, int af)
|
||||
{
|
||||
if (!ip_vs_checksum_needed(skb, af))
|
||||
if (!ip_vs_checksum_needed(skb))
|
||||
return true;
|
||||
/* Validate csum even for FORWARD */
|
||||
return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
struct sctphdr *sh;
|
||||
__le32 cmp, val;
|
||||
|
||||
if (!ip_vs_checksum_needed(skb, af))
|
||||
if (!ip_vs_checksum_needed(skb))
|
||||
return 1;
|
||||
sh = (struct sctphdr *)(skb->data + sctphoff);
|
||||
cmp = sh->checksum;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user