Improve hashing of IPv4 fragments.

Currently, IPv4 fragments are hashed into buckets based on a 32-bit
key which is calculated by (src_ip ^ ip_id) and combined with a random
seed. However, because an attacker can control the values of src_ip
and ip_id, it is possible to construct an attack which causes very
deep chains to form in a given bucket.

To ensure more uniform distribution (and lower predictability for
an attacker), calculate the hash based on a key which includes all
the fields we use to identify a reassembly queue (dst_ip, src_ip,
ip_id, and the ip protocol) as well as a random seed.

Reviewed by:	jhb
Security:	FreeBSD-SA-18:10.ip
Security:	CVE-2018-6923
This commit is contained in:
Jonathan T. Looney 2018-08-14 17:15:47 +00:00
parent 9840c7373c
commit 5d9bd45518
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=337775

View File

@ -148,7 +148,7 @@ ip_reass(struct mbuf *m)
struct ipqhead *head;
int i, hlen, next;
u_int8_t ecn, ecn0;
uint32_t hash;
uint32_t hash, hashkey[3];
#ifdef RSS
uint32_t rss_hash, rss_type;
#endif
@ -202,8 +202,12 @@ ip_reass(struct mbuf *m)
m->m_data += hlen;
m->m_len -= hlen;
hash = ip->ip_src.s_addr ^ ip->ip_id;
hash = jenkins_hash32(&hash, 1, V_ipq_hashseed) & IPREASS_HMASK;
hashkey[0] = ip->ip_src.s_addr;
hashkey[1] = ip->ip_dst.s_addr;
hashkey[2] = (uint32_t)ip->ip_p << 16;
hashkey[2] += ip->ip_id;
hash = jenkins_hash32(hashkey, nitems(hashkey), V_ipq_hashseed);
hash &= IPREASS_HMASK;
head = &V_ipq[hash].head;
IPQ_LOCK(hash);