aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 082239ffe34a..190199851c9a 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -457,8 +457,31 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
457 return neigh_create(&arp_tbl, pkey, dev); 457 return neigh_create(&arp_tbl, pkey, dev);
458} 458}
459 459
460atomic_t *ip_idents __read_mostly; 460#define IP_IDENTS_SZ 2048u
461EXPORT_SYMBOL(ip_idents); 461struct ip_ident_bucket {
462 atomic_t id;
463 u32 stamp32;
464};
465
466static struct ip_ident_bucket *ip_idents __read_mostly;
467
468/* In order to protect privacy, we add a perturbation to identifiers
469 * if one generator is seldom used. This makes hard for an attacker
470 * to infer how many packets were sent between two points in time.
471 */
472u32 ip_idents_reserve(u32 hash, int segs)
473{
474 struct ip_ident_bucket *bucket = ip_idents + hash % IP_IDENTS_SZ;
475 u32 old = ACCESS_ONCE(bucket->stamp32);
476 u32 now = (u32)jiffies;
477 u32 delta = 0;
478
479 if (old != now && cmpxchg(&bucket->stamp32, old, now) == old)
480 delta = prandom_u32_max(now - old);
481
482 return atomic_add_return(segs + delta, &bucket->id) - segs;
483}
484EXPORT_SYMBOL(ip_idents_reserve);
462 485
463void __ip_select_ident(struct iphdr *iph, int segs) 486void __ip_select_ident(struct iphdr *iph, int segs)
464{ 487{
@@ -467,7 +490,10 @@ void __ip_select_ident(struct iphdr *iph, int segs)
467 490
468 net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd)); 491 net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
469 492
470 hash = jhash_1word((__force u32)iph->daddr, ip_idents_hashrnd); 493 hash = jhash_3words((__force u32)iph->daddr,
494 (__force u32)iph->saddr,
495 iph->protocol,
496 ip_idents_hashrnd);
471 id = ip_idents_reserve(hash, segs); 497 id = ip_idents_reserve(hash, segs);
472 iph->id = htons(id); 498 iph->id = htons(id);
473} 499}
@@ -1010,7 +1036,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
1010 const struct iphdr *iph = (const struct iphdr *) skb->data; 1036 const struct iphdr *iph = (const struct iphdr *) skb->data;
1011 struct flowi4 fl4; 1037 struct flowi4 fl4;
1012 struct rtable *rt; 1038 struct rtable *rt;
1013 struct dst_entry *dst; 1039 struct dst_entry *odst = NULL;
1014 bool new = false; 1040 bool new = false;
1015 1041
1016 bh_lock_sock(sk); 1042 bh_lock_sock(sk);
@@ -1018,16 +1044,17 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
1018 if (!ip_sk_accept_pmtu(sk)) 1044 if (!ip_sk_accept_pmtu(sk))
1019 goto out; 1045 goto out;
1020 1046
1021 rt = (struct rtable *) __sk_dst_get(sk); 1047 odst = sk_dst_get(sk);
1022 1048
1023 if (sock_owned_by_user(sk) || !rt) { 1049 if (sock_owned_by_user(sk) || !odst) {
1024 __ipv4_sk_update_pmtu(skb, sk, mtu); 1050 __ipv4_sk_update_pmtu(skb, sk, mtu);
1025 goto out; 1051 goto out;
1026 } 1052 }
1027 1053
1028 __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); 1054 __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
1029 1055
1030 if (!__sk_dst_check(sk, 0)) { 1056 rt = (struct rtable *)odst;
1057 if (odst->obsolete && odst->ops->check(odst, 0) == NULL) {
1031 rt = ip_route_output_flow(sock_net(sk), &fl4, sk); 1058 rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
1032 if (IS_ERR(rt)) 1059 if (IS_ERR(rt))
1033 goto out; 1060 goto out;
@@ -1037,8 +1064,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
1037 1064
1038 __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); 1065 __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu);
1039 1066
1040 dst = dst_check(&rt->dst, 0); 1067 if (!dst_check(&rt->dst, 0)) {
1041 if (!dst) {
1042 if (new) 1068 if (new)
1043 dst_release(&rt->dst); 1069 dst_release(&rt->dst);
1044 1070
@@ -1050,10 +1076,11 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
1050 } 1076 }
1051 1077
1052 if (new) 1078 if (new)
1053 __sk_dst_set(sk, &rt->dst); 1079 sk_dst_set(sk, &rt->dst);
1054 1080
1055out: 1081out:
1056 bh_unlock_sock(sk); 1082 bh_unlock_sock(sk);
1083 dst_release(odst);
1057} 1084}
1058EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); 1085EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu);
1059 1086