net/flow_dissector: switch to siphash
UDP IPv6 packets auto flowlabels are using a 32bit secret (static u32 hashrnd in net/core/flow_dissector.c) and apply jhash() over fields known by the receivers. Attackers can easily infer the 32bit secret and use this information to identify a device and/or user, since this 32bit secret is only set at boot time. Really, using jhash() to generate cookies sent on the wire is a serious security concern. Trying to change the rol32(hash, 16) in ip6_make_flowlabel() would be a dead end. Trying to periodically change the secret (like in sch_sfq.c) could change paths taken in the network for long lived flows. Let's switch to siphash, as we did in commitdf453700e8
("inet: switch IP ID generator to siphash") Using a cryptographically strong pseudo random function will solve this privacy issue and more generally remove other weak points in the stack. Packet schedulers using skb_get_hash_perturb() benefit from this change. Fixes:b56774163f
("ipv6: Enable auto flow labels by default") Fixes:42240901f7
("ipv6: Implement different admin modes for automatic flow labels") Fixes:67800f9b1f
("ipv6: Call skb_get_hash_flowi6 to get skb->hash in ip6_make_flowlabel") Fixes:cb1ce2ef38
("ipv6: Implement automatic flow label generation on transmit") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Jonathan Berger <jonathann1@walla.com> Reported-by: Amit Klein <aksecurity@gmail.com> Reported-by: Benny Pinkas <benny@pinkas.net> Cc: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
这个提交包含在:
@@ -18,7 +18,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/siphash.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
@@ -45,7 +45,7 @@ struct sfb_bucket {
|
||||
* (Section 4.4 of SFB reference : moving hash functions)
|
||||
*/
|
||||
struct sfb_bins {
|
||||
u32 perturbation; /* jhash perturbation */
|
||||
siphash_key_t perturbation; /* siphash key */
|
||||
struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS];
|
||||
};
|
||||
|
||||
@@ -217,7 +217,8 @@ static u32 sfb_compute_qlen(u32 *prob_r, u32 *avgpm_r, const struct sfb_sched_da
|
||||
|
||||
static void sfb_init_perturbation(u32 slot, struct sfb_sched_data *q)
|
||||
{
|
||||
q->bins[slot].perturbation = prandom_u32();
|
||||
get_random_bytes(&q->bins[slot].perturbation,
|
||||
sizeof(q->bins[slot].perturbation));
|
||||
}
|
||||
|
||||
static void sfb_swap_slot(struct sfb_sched_data *q)
|
||||
@@ -314,9 +315,9 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
||||
/* If using external classifiers, get result and record it. */
|
||||
if (!sfb_classify(skb, fl, &ret, &salt))
|
||||
goto other_drop;
|
||||
sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
|
||||
sfbhash = siphash_1u32(salt, &q->bins[slot].perturbation);
|
||||
} else {
|
||||
sfbhash = skb_get_hash_perturb(skb, q->bins[slot].perturbation);
|
||||
sfbhash = skb_get_hash_perturb(skb, &q->bins[slot].perturbation);
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +353,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
||||
/* Inelastic flow */
|
||||
if (q->double_buffering) {
|
||||
sfbhash = skb_get_hash_perturb(skb,
|
||||
q->bins[slot].perturbation);
|
||||
&q->bins[slot].perturbation);
|
||||
if (!sfbhash)
|
||||
sfbhash = 1;
|
||||
sfb_skb_cb(skb)->hashes[slot] = sfbhash;
|
||||
|
在新工单中引用
屏蔽一个用户