Merge branch 'tcp-rfc-6056'
Eric Dumazet says: ==================== tcp: RFC 6056 induced changes This is based on a report from David Dworken. First patch implements RFC 6056 3.3.4 proposal. Second patch is adding a little bit of noise to make attacker life a bit harder. =================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
3a926b0e9c
|
@ -709,6 +709,17 @@ unlock:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(inet_unhash);
|
||||
|
||||
/* RFC 6056 3.3.4. Algorithm 4: Double-Hash Port Selection Algorithm
|
||||
* Note that we use 32bit integers (vs RFC 'short integers')
|
||||
* because 2^16 is not a multiple of num_ephemeral and this
|
||||
* property might be used by clever attacker.
|
||||
* RFC claims using TABLE_LENGTH=10 buckets gives an improvement,
|
||||
* we use 256 instead to really give more isolation and
|
||||
* privacy, this only consumes 1 KB of kernel memory.
|
||||
*/
|
||||
#define INET_TABLE_PERTURB_SHIFT 8
|
||||
static u32 table_perturb[1 << INET_TABLE_PERTURB_SHIFT];
|
||||
|
||||
int __inet_hash_connect(struct inet_timewait_death_row *death_row,
|
||||
struct sock *sk, u32 port_offset,
|
||||
int (*check_established)(struct inet_timewait_death_row *,
|
||||
|
@ -722,8 +733,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
|
|||
struct inet_bind_bucket *tb;
|
||||
u32 remaining, offset;
|
||||
int ret, i, low, high;
|
||||
static u32 hint;
|
||||
int l3mdev;
|
||||
u32 index;
|
||||
|
||||
if (port) {
|
||||
head = &hinfo->bhash[inet_bhashfn(net, port,
|
||||
|
@ -750,7 +761,10 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
|
|||
if (likely(remaining > 1))
|
||||
remaining &= ~1U;
|
||||
|
||||
offset = (hint + port_offset) % remaining;
|
||||
net_get_random_once(table_perturb, sizeof(table_perturb));
|
||||
index = hash_32(port_offset, INET_TABLE_PERTURB_SHIFT);
|
||||
|
||||
offset = (READ_ONCE(table_perturb[index]) + port_offset) % remaining;
|
||||
/* In first pass we try ports of @low parity.
|
||||
* inet_csk_get_port() does the opposite choice.
|
||||
*/
|
||||
|
@ -804,7 +818,12 @@ next_port:
|
|||
return -EADDRNOTAVAIL;
|
||||
|
||||
ok:
|
||||
hint += i + 2;
|
||||
/* If our first attempt found a candidate, skip next candidate
|
||||
* in 1/16 of cases to add some noise.
|
||||
*/
|
||||
if (!i && !(prandom_u32() % 16))
|
||||
i = 2;
|
||||
WRITE_ONCE(table_perturb[index], READ_ONCE(table_perturb[index]) + i + 2);
|
||||
|
||||
/* Head lock still held and bh's disabled */
|
||||
inet_bind_hash(sk, tb, port);
|
||||
|
|
Loading…
Reference in New Issue