|
|
098754 |
From 2258117c811aa525ec995c601c5f4649553e9490 Mon Sep 17 00:00:00 2001
|
|
|
098754 |
From: Joe Lawrence <joe.lawrence@redhat.com>
|
|
|
098754 |
Date: Mon, 6 Jun 2022 09:30:32 -0400
|
|
|
098754 |
Subject: [KPATCH CVE-2022-1012] kpatch fixes for CVE-2022-1012
|
|
|
098754 |
Content-type: text/plain
|
|
|
098754 |
|
|
|
098754 |
Changes since last build:
|
|
|
098754 |
arches: x86_64 ppc64le
|
|
|
098754 |
inet6_hashtables.o: changed function: inet6_hash_connect
|
|
|
098754 |
inet_hashtables.o: changed function: inet_hash_connect
|
|
|
098754 |
inet_hashtables.o: new function: klp__inet_hash_connect
|
|
|
098754 |
inet_hashtables.o: new function: klp_cve_2022_1012_pre_patch_callback
|
|
|
098754 |
inet_hashtables.o: new function: klp_table_perturb_ctor
|
|
|
098754 |
secure_seq.o: new function: klp_secure_ipv4_port_ephemeral
|
|
|
098754 |
secure_seq.o: new function: klp_secure_ipv6_port_ephemeral
|
|
|
098754 |
---------------------------
|
|
|
098754 |
|
|
|
098754 |
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-9/-/merge_requests/2
|
|
|
098754 |
Kernels:
|
|
|
098754 |
5.14.0-70.13.1.el9_0
|
|
|
098754 |
|
|
|
098754 |
Modifications:
|
|
|
098754 |
- Avoid header file changes, move prototypes into .c files
|
|
|
098754 |
- secure_ipv4_port_ephemeral() and secure_ipv6_port_ephemeral() are
|
|
|
098754 |
exported symbols, create "klp_" variants that change return type
|
|
|
098754 |
from u32 -> u64
|
|
|
098754 |
- inet_sk_port_offset() and inet6_sk_port_offset() have only one caller each,
|
|
|
098754 |
which we can kpatch, so it's safe to update their return values from
|
|
|
098754 |
u32 -> u64
|
|
|
098754 |
- __inet_hash_connect() is prototyped in a header file, which we don't want to
|
|
|
098754 |
touch, so create a "klp" variant updating the interface for port_offset
|
|
|
098754 |
u32 -> u64
|
|
|
098754 |
- Create larger klp_table_perturb for kpatch functions, leaving
|
|
|
098754 |
smaller table_perturb intact for unpatched code
|
|
|
098754 |
- Use a shadow variable for the larger klp_table_perturb so it may
|
|
|
098754 |
persist across kpatch upgrades
|
|
|
098754 |
- Get or allocate klp_table_perturb shadow variable in prepatch callback
|
|
|
098754 |
rather than inet_hashinfo2_init()
|
|
|
098754 |
- Use a shadow variable constructor to initialize klp_table_perturb with
|
|
|
098754 |
net_get_random_once() on its allocation
|
|
|
098754 |
- Use KLP_INET_TABLE_PERTURB_{SHIFT,SIZE} for larger size so we don't
|
|
|
098754 |
modify existing (smaller) table_perturb
|
|
|
098754 |
- Add -fno-optimize-sibling-calls attribute for inet_hash_connect()
|
|
|
098754 |
|
|
|
098754 |
commit 2f0029a0cd4a60d087882790b8f2e4b3b7a34fc9
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:26:43 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
secure_seq: use the 64 bits of the siphash for port offset calculation
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: cca87d73827e2be4da6de677da5fbbf05ee1efe7
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
|
|
|
098754 |
commit b2d057560b8107c633b39aabe517ff9d93f285e3
|
|
|
098754 |
Author: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Date: Mon May 2 10:46:08 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
secure_seq: use the 64 bits of the siphash for port offset calculation
|
|
|
098754 |
|
|
|
098754 |
SipHash replaced MD5 in secure_ipv{4,6}_port_ephemeral() via commit
|
|
|
098754 |
7cd23e5300c1 ("secure_seq: use SipHash in place of MD5"), but the output
|
|
|
098754 |
remained truncated to 32-bit only. In order to exploit more bits from the
|
|
|
098754 |
hash, let's make the functions return the full 64-bit of siphash_3u32().
|
|
|
098754 |
We also make sure the port offset calculation in __inet_hash_connect()
|
|
|
098754 |
remains done on 32-bit to avoid the need for div_u64_rem() and an extra
|
|
|
098754 |
cost on 32-bit systems.
|
|
|
098754 |
|
|
|
098754 |
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
|
098754 |
Cc: Moshe Kol <moshe.kol@mail.huji.ac.il>
|
|
|
098754 |
Cc: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
|
|
|
098754 |
Cc: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
commit 12d013e32960f7de65bf6d48b5d1b34f035db485
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:29:59 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: use different parts of the port_offset for index and offset
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: cf01c418b12c3f395134654725aee76ba8ead14f
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
|
|
|
098754 |
commit 9e9b70ae923baf2b5e8a0ea4fd0c8451801ac526
|
|
|
098754 |
Author: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Date: Mon May 2 10:46:09 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: use different parts of the port_offset for index and offset
|
|
|
098754 |
|
|
|
098754 |
Amit Klein suggests that we use different parts of port_offset for the
|
|
|
098754 |
table's index and the port offset so that there is no direct relation
|
|
|
098754 |
between them.
|
|
|
098754 |
|
|
|
098754 |
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
|
098754 |
Cc: Moshe Kol <moshe.kol@mail.huji.ac.il>
|
|
|
098754 |
Cc: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
|
|
|
098754 |
Cc: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
commit a35aa2ee80eba52053d4857f03aaec487e124938
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:30:49 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: resalt the secret every 10 seconds
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: 76a5e5ab10aa3a222b10ea44aae87b61de99de76
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
Conflicts:
|
|
|
098754 |
(context) Missing upstream commit 49ecc2e9c3ab ("net: align static
|
|
|
098754 |
siphash keys"):
|
|
|
098754 |
RHEL 9 still declares net_secret and ts_secret as siphash_key_t,
|
|
|
098754 |
while upstream uses the new siphash_aligned_key_t.
|
|
|
098754 |
|
|
|
098754 |
commit 4dfa9b438ee34caca4e6a4e5e961641807367f6f
|
|
|
098754 |
Author: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Date: Mon May 2 10:46:10 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: resalt the secret every 10 seconds
|
|
|
098754 |
|
|
|
098754 |
In order to limit the ability for an observer to recognize the source
|
|
|
098754 |
ports sequence used to contact a set of destinations, we should
|
|
|
098754 |
periodically shuffle the secret. 10 seconds looks effective enough
|
|
|
098754 |
without causing particular issues.
|
|
|
098754 |
|
|
|
098754 |
Cc: Moshe Kol <moshe.kol@mail.huji.ac.il>
|
|
|
098754 |
Cc: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
|
|
|
098754 |
Cc: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
|
098754 |
Tested-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
commit 2e7decde85e1d99aba7cfc25489136757e5e5e4d
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:37:42 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: add small random increments to the source port
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: c36cc7ecaeb895c5ec73085d925208ead5a9f285
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
|
|
|
098754 |
commit ca7af0402550f9a0b3316d5f1c30904e42ed257d
|
|
|
098754 |
Author: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Date: Mon May 2 10:46:11 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: add small random increments to the source port
|
|
|
098754 |
|
|
|
098754 |
Here we're randomly adding between 0 and 7 random increments to the
|
|
|
098754 |
selected source port in order to add some noise in the source port
|
|
|
098754 |
selection that will make the next port less predictable.
|
|
|
098754 |
|
|
|
098754 |
With the default port range of 32768-60999 this means a worst case
|
|
|
098754 |
reuse scenario of 14116/8=1764 connections between two consecutive
|
|
|
098754 |
uses of the same port, with an average of 14116/4.5=3137. This code
|
|
|
098754 |
was stressed at more than 800000 connections per second to a fixed
|
|
|
098754 |
target with all connections closed by the client using RSTs (worst
|
|
|
098754 |
condition) and only 2 connections failed among 13 billion, despite
|
|
|
098754 |
the hash being reseeded every 10 seconds, indicating a perfectly
|
|
|
098754 |
safe situation.
|
|
|
098754 |
|
|
|
098754 |
Cc: Moshe Kol <moshe.kol@mail.huji.ac.il>
|
|
|
098754 |
Cc: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
|
|
|
098754 |
Cc: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
commit 11b7585327e4558856beea1b60c2b56a89109034
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:38:33 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: dynamically allocate the perturb table used by source ports
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: 2a8821f71c0f00f5169888c9e21df0e033306ae8
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
|
|
|
098754 |
commit e9261476184be1abd486c9434164b2acbe0ed6c2
|
|
|
098754 |
Author: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Date: Mon May 2 10:46:12 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: dynamically allocate the perturb table used by source ports
|
|
|
098754 |
|
|
|
098754 |
We'll need to further increase the size of this table and it's likely
|
|
|
098754 |
that at some point its size will not be suitable anymore for a static
|
|
|
098754 |
table. Let's allocate it on boot from inet_hashinfo2_init(), which is
|
|
|
098754 |
called from tcp_init().
|
|
|
098754 |
|
|
|
098754 |
Cc: Moshe Kol <moshe.kol@mail.huji.ac.il>
|
|
|
098754 |
Cc: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
|
|
|
098754 |
Cc: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
commit ffec79df2cf078ae8efda94fa1644a2f3d249629
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:39:49 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: increase source port perturb table to 2^16
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: cb2b7f66f852709725a5fc3798b8cf60eee4cfcd
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
|
|
|
098754 |
commit 4c2c8f03a5ab7cb04ec64724d7d176d00bcc91e5
|
|
|
098754 |
Author: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Date: Mon May 2 10:46:13 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: increase source port perturb table to 2^16
|
|
|
098754 |
|
|
|
098754 |
Moshe Kol, Amit Klein, and Yossi Gilad reported being able to accurately
|
|
|
098754 |
identify a client by forcing it to emit only 40 times more connections
|
|
|
098754 |
than there are entries in the table_perturb[] table. The previous two
|
|
|
098754 |
improvements consisting in resalting the secret every 10s and adding
|
|
|
098754 |
randomness to each port selection only slightly improved the situation,
|
|
|
098754 |
and the current value of 2^8 was too small as it's not very difficult
|
|
|
098754 |
to make a client emit 10k connections in less than 10 seconds.
|
|
|
098754 |
|
|
|
098754 |
Thus we're increasing the perturb table from 2^8 to 2^16 so that the
|
|
|
098754 |
same precision now requires 2.6M connections, which is more difficult in
|
|
|
098754 |
this time frame and harder to hide as a background activity. The impact
|
|
|
098754 |
is that the table now uses 256 kB instead of 1 kB, which could mostly
|
|
|
098754 |
affect devices making frequent outgoing connections. However such
|
|
|
098754 |
components usually target a small set of destinations (load balancers,
|
|
|
098754 |
database clients, perf assessment tools), and in practice only a few
|
|
|
098754 |
entries will be visited, like before.
|
|
|
098754 |
|
|
|
098754 |
A live test at 1 million connections per second showed no performance
|
|
|
098754 |
difference from the previous value.
|
|
|
098754 |
|
|
|
098754 |
Reported-by: Moshe Kol <moshe.kol@mail.huji.ac.il>
|
|
|
098754 |
Reported-by: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
|
|
|
098754 |
Reported-by: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
commit 8b63da5c1514e473907b074eae7ce5acc0ea739e
|
|
|
098754 |
Author: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Date: Tue May 10 21:40:34 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: drop the hash_32() part from the index calculation
|
|
|
098754 |
|
|
|
098754 |
Bugzilla: https://bugzilla.redhat.com/2087128
|
|
|
098754 |
CVE: CVE-2022-1012
|
|
|
098754 |
Y-Commit: f8b7b8321dd6b55062382fc343422f3926ffa04c
|
|
|
098754 |
|
|
|
098754 |
O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2064868
|
|
|
098754 |
Upstream Status: linux.git
|
|
|
098754 |
O-CVE: CVE-2022-1012
|
|
|
098754 |
|
|
|
098754 |
commit e8161345ddbb66e449abde10d2fdce93f867eba9
|
|
|
098754 |
Author: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Date: Mon May 2 10:46:14 2022 +0200
|
|
|
098754 |
|
|
|
098754 |
tcp: drop the hash_32() part from the index calculation
|
|
|
098754 |
|
|
|
098754 |
In commit 190cc82489f4 ("tcp: change source port randomizarion at
|
|
|
098754 |
connect() time"), the table_perturb[] array was introduced and an
|
|
|
098754 |
index was taken from the port_offset via hash_32(). But it turns
|
|
|
098754 |
out that hash_32() performs a multiplication while the input here
|
|
|
098754 |
comes from the output of SipHash in secure_seq, that is well
|
|
|
098754 |
distributed enough to avoid the need for yet another hash.
|
|
|
098754 |
|
|
|
098754 |
Suggested-by: Amit Klein <aksecurity@gmail.com>
|
|
|
098754 |
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
|
098754 |
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
|
098754 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Guillaume Nault <gnault@redhat.com>
|
|
|
098754 |
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
|
|
098754 |
|
|
|
098754 |
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
|
|
|
098754 |
---
|
|
|
098754 |
net/core/secure_seq.c | 30 +++++++
|
|
|
098754 |
net/ipv4/inet_hashtables.c | 175 ++++++++++++++++++++++++++++++++++--
|
|
|
098754 |
net/ipv6/inet6_hashtables.c | 20 +++--
|
|
|
098754 |
3 files changed, 211 insertions(+), 14 deletions(-)
|
|
|
098754 |
|
|
|
098754 |
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
|
|
|
098754 |
index b5bc680d4755..f18f8176d69e 100644
|
|
|
098754 |
--- a/net/core/secure_seq.c
|
|
|
098754 |
+++ b/net/core/secure_seq.c
|
|
|
098754 |
@@ -22,6 +22,8 @@
|
|
|
098754 |
static siphash_key_t net_secret __read_mostly;
|
|
|
098754 |
static siphash_key_t ts_secret __read_mostly;
|
|
|
098754 |
|
|
|
098754 |
+#define EPHEMERAL_PORT_SHUFFLE_PERIOD (10 * HZ)
|
|
|
098754 |
+
|
|
|
098754 |
static __always_inline void net_secret_init(void)
|
|
|
098754 |
{
|
|
|
098754 |
net_get_random_once(&net_secret, sizeof(net_secret));
|
|
|
098754 |
@@ -111,6 +113,25 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
|
098754 |
&net_secret);
|
|
|
098754 |
}
|
|
|
098754 |
EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
|
|
|
098754 |
+
|
|
|
098754 |
+u64 klp_secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
|
098754 |
+ __be16 dport)
|
|
|
098754 |
+{
|
|
|
098754 |
+ const struct {
|
|
|
098754 |
+ struct in6_addr saddr;
|
|
|
098754 |
+ struct in6_addr daddr;
|
|
|
098754 |
+ unsigned int timeseed;
|
|
|
098754 |
+ __be16 dport;
|
|
|
098754 |
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
|
|
|
098754 |
+ .saddr = *(struct in6_addr *)saddr,
|
|
|
098754 |
+ .daddr = *(struct in6_addr *)daddr,
|
|
|
098754 |
+ .timeseed = jiffies / EPHEMERAL_PORT_SHUFFLE_PERIOD,
|
|
|
098754 |
+ .dport = dport,
|
|
|
098754 |
+ };
|
|
|
098754 |
+ net_secret_init();
|
|
|
098754 |
+ return siphash(&combined, offsetofend(typeof(combined), dport),
|
|
|
098754 |
+ &net_secret);
|
|
|
098754 |
+}
|
|
|
098754 |
#endif
|
|
|
098754 |
|
|
|
098754 |
#ifdef CONFIG_INET
|
|
|
098754 |
@@ -149,6 +170,15 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
|
|
|
098754 |
(__force u16)dport, &net_secret);
|
|
|
098754 |
}
|
|
|
098754 |
EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
|
|
|
098754 |
+
|
|
|
098754 |
+u64 klp_secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
|
|
|
098754 |
+{
|
|
|
098754 |
+ net_secret_init();
|
|
|
098754 |
+ return siphash_4u32((__force u32)saddr, (__force u32)daddr,
|
|
|
098754 |
+ (__force u16)dport,
|
|
|
098754 |
+ jiffies / EPHEMERAL_PORT_SHUFFLE_PERIOD,
|
|
|
098754 |
+ &net_secret);
|
|
|
098754 |
+}
|
|
|
098754 |
#endif
|
|
|
098754 |
|
|
|
098754 |
#if IS_ENABLED(CONFIG_IP_DCCP)
|
|
|
098754 |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
|
|
|
098754 |
index bfb522e51346..7f982eb04e3f 100644
|
|
|
098754 |
--- a/net/ipv4/inet_hashtables.c
|
|
|
098754 |
+++ b/net/ipv4/inet_hashtables.c
|
|
|
098754 |
@@ -504,13 +504,14 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
return -EADDRNOTAVAIL;
|
|
|
098754 |
}
|
|
|
098754 |
|
|
|
098754 |
-static u32 inet_sk_port_offset(const struct sock *sk)
|
|
|
098754 |
+u64 klp_secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
|
|
|
098754 |
+static u64 inet_sk_port_offset(const struct sock *sk)
|
|
|
098754 |
{
|
|
|
098754 |
const struct inet_sock *inet = inet_sk(sk);
|
|
|
098754 |
|
|
|
098754 |
- return secure_ipv4_port_ephemeral(inet->inet_rcv_saddr,
|
|
|
098754 |
- inet->inet_daddr,
|
|
|
098754 |
- inet->inet_dport);
|
|
|
098754 |
+ return klp_secure_ipv4_port_ephemeral(inet->inet_rcv_saddr,
|
|
|
098754 |
+ inet->inet_daddr,
|
|
|
098754 |
+ inet->inet_dport);
|
|
|
098754 |
}
|
|
|
098754 |
|
|
|
098754 |
/* Searches for an exsiting socket in the ehash bucket list.
|
|
|
098754 |
@@ -842,18 +843,178 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
return 0;
|
|
|
098754 |
}
|
|
|
098754 |
|
|
|
098754 |
+#include "kpatch-macros.h"
|
|
|
098754 |
+#define KLP_CVE_2022_1012_TABLE_PERTURB 0x2022101200000001
|
|
|
098754 |
+
|
|
|
098754 |
+#define KLP_INET_TABLE_PERTURB_SHIFT 16
|
|
|
098754 |
+#define KLP_INET_TABLE_PERTURB_SIZE (1 << KLP_INET_TABLE_PERTURB_SHIFT)
|
|
|
098754 |
+static u32 *klp_table_perturb;
|
|
|
098754 |
+
|
|
|
098754 |
+static int klp_table_perturb_ctor(void *obj, void *shadow_data, void *ctor_data)
|
|
|
098754 |
+{
|
|
|
098754 |
+ u32 *klp_tp = shadow_data;
|
|
|
098754 |
+ if (!net_get_random_once(klp_tp, KLP_INET_TABLE_PERTURB_SIZE * sizeof(*klp_tp))) {
|
|
|
098754 |
+ pr_err("kpatch assertion: net_get_random_once() on klp_table_perturb");
|
|
|
098754 |
+ return -1;
|
|
|
098754 |
+ }
|
|
|
098754 |
+
|
|
|
098754 |
+ return 0;
|
|
|
098754 |
+}
|
|
|
098754 |
+
|
|
|
098754 |
+static int klp_cve_2022_1012_pre_patch_callback(struct klp_object *obj)
|
|
|
098754 |
+{
|
|
|
098754 |
+ /* this one is used for source ports of outgoing connections */
|
|
|
098754 |
+ klp_table_perturb = klp_shadow_get_or_alloc(0, KLP_CVE_2022_1012_TABLE_PERTURB,
|
|
|
098754 |
+ KLP_INET_TABLE_PERTURB_SIZE * sizeof(*klp_table_perturb),
|
|
|
098754 |
+ GFP_KERNEL, klp_table_perturb_ctor, NULL);
|
|
|
098754 |
+ if (!klp_table_perturb) {
|
|
|
098754 |
+ pr_err("TCP: failed to alloc / find klp_table_perturb");
|
|
|
098754 |
+ return -ENOMEM;
|
|
|
098754 |
+ }
|
|
|
098754 |
+
|
|
|
098754 |
+ return 0;
|
|
|
098754 |
+}
|
|
|
098754 |
+KPATCH_PRE_PATCH_CALLBACK(klp_cve_2022_1012_pre_patch_callback);
|
|
|
098754 |
+
|
|
|
098754 |
+int klp__inet_hash_connect(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
+ struct sock *sk, u64 port_offset,
|
|
|
098754 |
+ int (*check_established)(struct inet_timewait_death_row *,
|
|
|
098754 |
+ struct sock *, __u16, struct inet_timewait_sock **))
|
|
|
098754 |
+{
|
|
|
098754 |
+ struct inet_hashinfo *hinfo = death_row->hashinfo;
|
|
|
098754 |
+ struct inet_timewait_sock *tw = NULL;
|
|
|
098754 |
+ struct inet_bind_hashbucket *head;
|
|
|
098754 |
+ int port = inet_sk(sk)->inet_num;
|
|
|
098754 |
+ struct net *net = sock_net(sk);
|
|
|
098754 |
+ struct inet_bind_bucket *tb;
|
|
|
098754 |
+ u32 remaining, offset;
|
|
|
098754 |
+ int ret, i, low, high;
|
|
|
098754 |
+ int l3mdev;
|
|
|
098754 |
+ u32 index;
|
|
|
098754 |
+
|
|
|
098754 |
+ if (port) {
|
|
|
098754 |
+ head = &hinfo->bhash[inet_bhashfn(net, port,
|
|
|
098754 |
+ hinfo->bhash_size)];
|
|
|
098754 |
+ tb = inet_csk(sk)->icsk_bind_hash;
|
|
|
098754 |
+ spin_lock_bh(&head->lock);
|
|
|
098754 |
+ if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
|
|
|
098754 |
+ inet_ehash_nolisten(sk, NULL, NULL);
|
|
|
098754 |
+ spin_unlock_bh(&head->lock);
|
|
|
098754 |
+ return 0;
|
|
|
098754 |
+ }
|
|
|
098754 |
+ spin_unlock(&head->lock);
|
|
|
098754 |
+ /* No definite answer... Walk to established hash table */
|
|
|
098754 |
+ ret = check_established(death_row, sk, port, NULL);
|
|
|
098754 |
+ local_bh_enable();
|
|
|
098754 |
+ return ret;
|
|
|
098754 |
+ }
|
|
|
098754 |
+
|
|
|
098754 |
+ l3mdev = inet_sk_bound_l3mdev(sk);
|
|
|
098754 |
+
|
|
|
098754 |
+ inet_get_local_port_range(net, &low, &high);
|
|
|
098754 |
+ high++; /* [32768, 60999] -> [32768, 61000[ */
|
|
|
098754 |
+ remaining = high - low;
|
|
|
098754 |
+ if (likely(remaining > 1))
|
|
|
098754 |
+ remaining &= ~1U;
|
|
|
098754 |
+
|
|
|
098754 |
+ /*
|
|
|
098754 |
+ * kpatch: klp_table_perturb_ctor() responsible for calling
|
|
|
098754 |
+ * net_get_random_once() for klp_table_perturb
|
|
|
098754 |
+ */
|
|
|
098754 |
+ index = port_offset & (KLP_INET_TABLE_PERTURB_SIZE - 1);
|
|
|
098754 |
+
|
|
|
098754 |
+ offset = READ_ONCE(klp_table_perturb[index]) + (port_offset >> 32);
|
|
|
098754 |
+ offset %= remaining;
|
|
|
098754 |
+
|
|
|
098754 |
+ /* In first pass we try ports of @low parity.
|
|
|
098754 |
+ * inet_csk_get_port() does the opposite choice.
|
|
|
098754 |
+ */
|
|
|
098754 |
+ offset &= ~1U;
|
|
|
098754 |
+other_parity_scan:
|
|
|
098754 |
+ port = low + offset;
|
|
|
098754 |
+ for (i = 0; i < remaining; i += 2, port += 2) {
|
|
|
098754 |
+ if (unlikely(port >= high))
|
|
|
098754 |
+ port -= remaining;
|
|
|
098754 |
+ if (inet_is_local_reserved_port(net, port))
|
|
|
098754 |
+ continue;
|
|
|
098754 |
+ head = &hinfo->bhash[inet_bhashfn(net, port,
|
|
|
098754 |
+ hinfo->bhash_size)];
|
|
|
098754 |
+ spin_lock_bh(&head->lock);
|
|
|
098754 |
+
|
|
|
098754 |
+ /* Does not bother with rcv_saddr checks, because
|
|
|
098754 |
+ * the established check is already unique enough.
|
|
|
098754 |
+ */
|
|
|
098754 |
+ inet_bind_bucket_for_each(tb, &head->chain) {
|
|
|
098754 |
+ if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
|
|
|
098754 |
+ tb->port == port) {
|
|
|
098754 |
+ if (tb->fastreuse >= 0 ||
|
|
|
098754 |
+ tb->fastreuseport >= 0)
|
|
|
098754 |
+ goto next_port;
|
|
|
098754 |
+ WARN_ON(hlist_empty(&tb->owners));
|
|
|
098754 |
+ if (!check_established(death_row, sk,
|
|
|
098754 |
+ port, &tw))
|
|
|
098754 |
+ goto ok;
|
|
|
098754 |
+ goto next_port;
|
|
|
098754 |
+ }
|
|
|
098754 |
+ }
|
|
|
098754 |
+
|
|
|
098754 |
+ tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
|
|
|
098754 |
+ net, head, port, l3mdev);
|
|
|
098754 |
+ if (!tb) {
|
|
|
098754 |
+ spin_unlock_bh(&head->lock);
|
|
|
098754 |
+ return -ENOMEM;
|
|
|
098754 |
+ }
|
|
|
098754 |
+ tb->fastreuse = -1;
|
|
|
098754 |
+ tb->fastreuseport = -1;
|
|
|
098754 |
+ goto ok;
|
|
|
098754 |
+next_port:
|
|
|
098754 |
+ spin_unlock_bh(&head->lock);
|
|
|
098754 |
+ cond_resched();
|
|
|
098754 |
+ }
|
|
|
098754 |
+
|
|
|
098754 |
+ offset++;
|
|
|
098754 |
+ if ((offset & 1) && remaining > 1)
|
|
|
098754 |
+ goto other_parity_scan;
|
|
|
098754 |
+
|
|
|
098754 |
+ return -EADDRNOTAVAIL;
|
|
|
098754 |
+
|
|
|
098754 |
+ok:
|
|
|
098754 |
+ /* Here we want to add a little bit of randomness to the next source
|
|
|
098754 |
+ * port that will be chosen. We use a max() with a random here so that
|
|
|
098754 |
+ * on low contention the randomness is maximal and on high contention
|
|
|
098754 |
+ * it may be inexistent.
|
|
|
098754 |
+ */
|
|
|
098754 |
+ i = max_t(int, i, (prandom_u32() & 7) * 2);
|
|
|
098754 |
+ WRITE_ONCE(klp_table_perturb[index], READ_ONCE(klp_table_perturb[index]) + i + 2);
|
|
|
098754 |
+
|
|
|
098754 |
+ /* Head lock still held and bh's disabled */
|
|
|
098754 |
+ inet_bind_hash(sk, tb, port);
|
|
|
098754 |
+ if (sk_unhashed(sk)) {
|
|
|
098754 |
+ inet_sk(sk)->inet_sport = htons(port);
|
|
|
098754 |
+ inet_ehash_nolisten(sk, (struct sock *)tw, NULL);
|
|
|
098754 |
+ }
|
|
|
098754 |
+ if (tw)
|
|
|
098754 |
+ inet_twsk_bind_unhash(tw, hinfo);
|
|
|
098754 |
+ spin_unlock(&head->lock);
|
|
|
098754 |
+ if (tw)
|
|
|
098754 |
+ inet_twsk_deschedule_put(tw);
|
|
|
098754 |
+ local_bh_enable();
|
|
|
098754 |
+ return 0;
|
|
|
098754 |
+}
|
|
|
098754 |
+
|
|
|
098754 |
/*
|
|
|
098754 |
* Bind a port for a connect operation and hash it.
|
|
|
098754 |
*/
|
|
|
098754 |
+__attribute__((optimize("-fno-optimize-sibling-calls")))
|
|
|
098754 |
int inet_hash_connect(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
struct sock *sk)
|
|
|
098754 |
{
|
|
|
098754 |
- u32 port_offset = 0;
|
|
|
098754 |
+ u64 port_offset = 0;
|
|
|
098754 |
|
|
|
098754 |
if (!inet_sk(sk)->inet_num)
|
|
|
098754 |
port_offset = inet_sk_port_offset(sk);
|
|
|
098754 |
- return __inet_hash_connect(death_row, sk, port_offset,
|
|
|
098754 |
- __inet_check_established);
|
|
|
098754 |
+ return klp__inet_hash_connect(death_row, sk, port_offset,
|
|
|
098754 |
+ __inet_check_established);
|
|
|
098754 |
}
|
|
|
098754 |
EXPORT_SYMBOL_GPL(inet_hash_connect);
|
|
|
098754 |
|
|
|
098754 |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
|
|
|
098754 |
index 67c9114835c8..fe0c5e5935e7 100644
|
|
|
098754 |
--- a/net/ipv6/inet6_hashtables.c
|
|
|
098754 |
+++ b/net/ipv6/inet6_hashtables.c
|
|
|
098754 |
@@ -308,24 +308,30 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
return -EADDRNOTAVAIL;
|
|
|
098754 |
}
|
|
|
098754 |
|
|
|
098754 |
-static u32 inet6_sk_port_offset(const struct sock *sk)
|
|
|
098754 |
+u64 klp_secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
|
098754 |
+ __be16 dport);
|
|
|
098754 |
+static u64 inet6_sk_port_offset(const struct sock *sk)
|
|
|
098754 |
{
|
|
|
098754 |
const struct inet_sock *inet = inet_sk(sk);
|
|
|
098754 |
|
|
|
098754 |
- return secure_ipv6_port_ephemeral(sk->sk_v6_rcv_saddr.s6_addr32,
|
|
|
098754 |
- sk->sk_v6_daddr.s6_addr32,
|
|
|
098754 |
- inet->inet_dport);
|
|
|
098754 |
+ return klp_secure_ipv6_port_ephemeral(sk->sk_v6_rcv_saddr.s6_addr32,
|
|
|
098754 |
+ sk->sk_v6_daddr.s6_addr32,
|
|
|
098754 |
+ inet->inet_dport);
|
|
|
098754 |
}
|
|
|
098754 |
|
|
|
098754 |
+int klp__inet_hash_connect(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
+ struct sock *sk, u64 port_offset,
|
|
|
098754 |
+ int (*check_established)(struct inet_timewait_death_row *,
|
|
|
098754 |
+ struct sock *, __u16, struct inet_timewait_sock **));
|
|
|
098754 |
int inet6_hash_connect(struct inet_timewait_death_row *death_row,
|
|
|
098754 |
struct sock *sk)
|
|
|
098754 |
{
|
|
|
098754 |
- u32 port_offset = 0;
|
|
|
098754 |
+ u64 port_offset = 0;
|
|
|
098754 |
|
|
|
098754 |
if (!inet_sk(sk)->inet_num)
|
|
|
098754 |
port_offset = inet6_sk_port_offset(sk);
|
|
|
098754 |
- return __inet_hash_connect(death_row, sk, port_offset,
|
|
|
098754 |
- __inet6_check_established);
|
|
|
098754 |
+ return klp__inet_hash_connect(death_row, sk, port_offset,
|
|
|
098754 |
+ __inet6_check_established);
|
|
|
098754 |
}
|
|
|
098754 |
EXPORT_SYMBOL_GPL(inet6_hash_connect);
|
|
|
098754 |
|
|
|
098754 |
--
|
|
|
098754 |
2.26.3
|
|
|
098754 |
|
|
|
098754 |
|