mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
ipv6: hash net ptr into fragmentation bucket selection
commit 5a352dd0a3aac03b443c94828dfd7144261c8636 upstream. As namespaces are sometimes used with overlapping ip address ranges, we should also use the namespace as input to the hash to select the ip fragmentation counter bucket. Cc: Eric Dumazet <edumazet@google.com> Cc: Flavio Leitner <fbl@redhat.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org> Change-Id: I4cd053112b178ddb0e0efbd1282478075dd064cb
This commit is contained in:
parent
b3c791b3a6
commit
8d0da84afe
5 changed files with 12 additions and 9 deletions
|
@ -580,7 +580,7 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb,
|
|||
case VIRTIO_NET_HDR_GSO_UDP:
|
||||
gso_type = SKB_GSO_UDP;
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
ipv6_proxy_select_ident(skb);
|
||||
ipv6_proxy_select_ident(dev_net(skb->dev), skb);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
@ -720,7 +720,7 @@ static ssize_t tun_get_user(struct tun_struct *tun,
|
|||
case VIRTIO_NET_HDR_GSO_UDP:
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
ipv6_proxy_select_ident(skb);
|
||||
ipv6_proxy_select_ident(dev_net(skb->dev), skb);
|
||||
break;
|
||||
default:
|
||||
tun->dev->stats.rx_frame_errors++;
|
||||
|
|
|
@ -526,8 +526,9 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
|
|||
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
|
||||
void ipv6_proxy_select_ident(struct sk_buff *skb);
|
||||
extern void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr,
|
||||
struct rt6_info *rt);
|
||||
void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
* Prototypes exported by ipv6
|
||||
|
|
|
@ -602,7 +602,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
||||
void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, struct rt6_info *rt)
|
||||
{
|
||||
static u32 ip6_idents_hashrnd __read_mostly;
|
||||
static bool hashrnd_initialized = false;
|
||||
|
@ -614,6 +614,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
|||
}
|
||||
hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd);
|
||||
hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash);
|
||||
hash ^= net_hash_mix(net);
|
||||
|
||||
id = ip_idents_reserve(hash, 1);
|
||||
fhdr->identification = htonl(id);
|
||||
|
@ -710,7 +711,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|||
skb_reset_network_header(skb);
|
||||
memcpy(skb_network_header(skb), tmp_hdr, hlen);
|
||||
|
||||
ipv6_select_ident(fh, rt);
|
||||
ipv6_select_ident(net, fh, rt);
|
||||
fh->nexthdr = nexthdr;
|
||||
fh->reserved = 0;
|
||||
fh->frag_off = htons(IP6_MF);
|
||||
|
@ -859,7 +860,7 @@ slow_path:
|
|||
fh->nexthdr = nexthdr;
|
||||
fh->reserved = 0;
|
||||
if (!frag_id) {
|
||||
ipv6_select_ident(fh, rt);
|
||||
ipv6_select_ident(net, fh, rt);
|
||||
frag_id = fh->identification;
|
||||
} else
|
||||
fh->identification = frag_id;
|
||||
|
@ -1160,7 +1161,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
|||
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
|
||||
sizeof(struct frag_hdr)) & ~7;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
ipv6_select_ident(&fhdr, rt);
|
||||
ipv6_select_ident(sock_net(sk), &fhdr, rt);
|
||||
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
|
||||
__skb_queue_tail(&sk->sk_write_queue, skb);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* This is similar to ipv6_select_ident() but we use an independent hash
|
||||
* seed to limit information leakage.
|
||||
*/
|
||||
void ipv6_proxy_select_ident(struct sk_buff *skb)
|
||||
void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
|
||||
{
|
||||
static u32 ip6_proxy_idents_hashrnd __read_mostly;
|
||||
static bool hashrnd_initialized = false;
|
||||
|
@ -31,6 +31,7 @@ void ipv6_proxy_select_ident(struct sk_buff *skb)
|
|||
}
|
||||
hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
|
||||
hash = __ipv6_addr_jhash(&addrs[0], hash);
|
||||
hash ^= net_hash_mix(net);
|
||||
|
||||
id = ip_idents_reserve(hash, 1);
|
||||
skb_shinfo(skb)->ip6_frag_id = htonl(id);
|
||||
|
|
Loading…
Reference in a new issue