mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-13 21:56:47 +07:00
netfilter: nat: limit port clash resolution attempts
In case almost or all available ports are taken, clash resolution can take a very long time, resulting in soft lockup. This can happen when many to-be-natted hosts connect to same destination:port (e.g. a proxy) and all connections pass the same SNAT. Pick a random offset in the acceptable range, then try ever smaller number of adjacent port numbers, until either the limit is reached or a useable port was found. This results in at most 248 attempts (128 + 64 + 32 + 16 + 8, i.e. 4 restarts with new search offset) instead of 64000+, Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
b635cbf68f
commit
a504b703bb
@ -40,9 +40,10 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct)
|
||||
{
|
||||
unsigned int range_size, min, max, i;
|
||||
unsigned int range_size, min, max, i, attempts;
|
||||
__be16 *portptr;
|
||||
u_int16_t off;
|
||||
u16 off;
|
||||
static const unsigned int max_attempts = 128;
|
||||
|
||||
if (maniptype == NF_NAT_MANIP_SRC)
|
||||
portptr = &tuple->src.u.all;
|
||||
@ -86,12 +87,28 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
|
||||
off = prandom_u32();
|
||||
}
|
||||
|
||||
for (i = 0; ; ++off) {
|
||||
attempts = range_size;
|
||||
if (attempts > max_attempts)
|
||||
attempts = max_attempts;
|
||||
|
||||
/* We are in softirq; doing a search of the entire range risks
|
||||
* soft lockup when all tuples are already used.
|
||||
*
|
||||
* If we can't find any free port from first offset, pick a new
|
||||
* one and try again, with ever smaller search window.
|
||||
*/
|
||||
another_round:
|
||||
for (i = 0; i < attempts; i++, off++) {
|
||||
*portptr = htons(min + off % range_size);
|
||||
if (++i != range_size && nf_nat_used_tuple(tuple, ct))
|
||||
continue;
|
||||
return;
|
||||
if (!nf_nat_used_tuple(tuple, ct))
|
||||
return;
|
||||
}
|
||||
|
||||
if (attempts >= range_size || attempts < 16)
|
||||
return;
|
||||
attempts /= 2;
|
||||
off = prandom_u32();
|
||||
goto another_round;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user