summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLudovic Cintrat <ludovic.cintrat@gatewatcher.com>2022-09-07 12:08:13 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-28 11:11:47 +0200
commit4d2f1bc9067af43ca59c7c34b6be0a847638513a (patch)
treefd392a01dcfc69447421b26683ce0bbae6eacf46 /net
parent8d06006c7eb75587d986da46c48ba9274f94e8e7 (diff)
downloadlinux-stable-4d2f1bc9067af43ca59c7c34b6be0a847638513a.tar.gz
linux-stable-4d2f1bc9067af43ca59c7c34b6be0a847638513a.tar.bz2
linux-stable-4d2f1bc9067af43ca59c7c34b6be0a847638513a.zip
net: core: fix flow symmetric hash
[ Upstream commit 64ae13ed478428135cddc2f1113dff162d8112d4 ] __flow_hash_consistentify() wrongly swaps ipv4 addresses in few cases. This function is indirectly used by __skb_get_hash_symmetric(), which is used to fanout packets in AF_PACKET. Intrusion detection systems may be impacted by this issue. __flow_hash_consistentify() computes the addresses difference then swaps them if the difference is negative. In few cases src - dst and dst - src are both negative. The following snippet mimics __flow_hash_consistentify(): ``` #include <stdio.h> #include <stdint.h> int main(int argc, char** argv) { int diffs_d, diffd_s; uint32_t dst = 0xb225a8c0; /* 178.37.168.192 --> 192.168.37.178 */ uint32_t src = 0x3225a8c0; /* 50.37.168.192 --> 192.168.37.50 */ uint32_t dst2 = 0x3325a8c0; /* 51.37.168.192 --> 192.168.37.51 */ diffs_d = src - dst; diffd_s = dst - src; printf("src:%08x dst:%08x, diff(s-d)=%d(0x%x) diff(d-s)=%d(0x%x)\n", src, dst, diffs_d, diffs_d, diffd_s, diffd_s); diffs_d = src - dst2; diffd_s = dst2 - src; printf("src:%08x dst:%08x, diff(s-d)=%d(0x%x) diff(d-s)=%d(0x%x)\n", src, dst2, diffs_d, diffs_d, diffd_s, diffd_s); return 0; } ``` Results: src:3225a8c0 dst:b225a8c0, \ diff(s-d)=-2147483648(0x80000000) \ diff(d-s)=-2147483648(0x80000000) src:3225a8c0 dst:3325a8c0, \ diff(s-d)=-16777216(0xff000000) \ diff(d-s)=16777216(0x1000000) In the first case the addresses differences are always < 0, therefore __flow_hash_consistentify() always swaps, thus dst->src and src->dst packets have differents hashes. Fixes: c3f8324188fa8 ("net: Add full IPv6 addresses to flow_keys") Signed-off-by: Ludovic Cintrat <ludovic.cintrat@gatewatcher.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/flow_dissector.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index bc50bd331d5b..1c34e2266578 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -1519,9 +1519,8 @@ static inline void __flow_hash_consistentify(struct flow_keys *keys)
switch (keys->control.addr_type) {
case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
- addr_diff = (__force u32)keys->addrs.v4addrs.dst -
- (__force u32)keys->addrs.v4addrs.src;
- if (addr_diff < 0)
+ if ((__force u32)keys->addrs.v4addrs.dst <
+ (__force u32)keys->addrs.v4addrs.src)
swap(keys->addrs.v4addrs.src, keys->addrs.v4addrs.dst);
if ((__force u16)keys->ports.dst <