aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2015-09-02 08:33:42 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-09-02 08:33:42 -0400
commite93c28f39375558409329a02a767d5cadfcc4a31 (patch)
tree9f1b4b5ce765b887b6002cded59fc934e6c9c012 /net/ipv6
parent85a62bf9d8ef8d533635270ae985281c58e8c974 (diff)
parent6fa2d197936ba0b8936e813d0adecefac160062b (diff)
Merge tag 'drm-intel-next-fixes-2015-09-02' into drm-intel-next-queued
Backmerge -fixes since there's more DDI-E related cleanups on top of the pile of -fixes for skl that just landed for 4.3. Conflicts: drivers/gpu/drm/i915/intel_display.c drivers/gpu/drm/i914/intel_dp.c drivers/gpu/drm/i915/intel_lrc.c Conflicts are all fairly harmless adjacent line stuff. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_fib.c2
-rw-r--r--net/ipv6/mcast_snoop.c33
-rw-r--r--net/ipv6/netfilter/ip6t_SYNPROXY.c19
-rw-r--r--net/ipv6/route.c85
-rw-r--r--net/ipv6/tcp_ipv6.c2
5 files changed, 91 insertions, 50 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 55d19861ab20..548c6237b1e7 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -172,6 +172,8 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
172 *ppcpu_rt = NULL; 172 *ppcpu_rt = NULL;
173 } 173 }
174 } 174 }
175
176 non_pcpu_rt->rt6i_pcpu = NULL;
175} 177}
176 178
177static void rt6_release(struct rt6_info *rt) 179static void rt6_release(struct rt6_info *rt)
diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c
index df8afe5ab31e..9405b04eecc6 100644
--- a/net/ipv6/mcast_snoop.c
+++ b/net/ipv6/mcast_snoop.c
@@ -143,34 +143,36 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb,
143 struct sk_buff *skb_chk = NULL; 143 struct sk_buff *skb_chk = NULL;
144 unsigned int transport_len; 144 unsigned int transport_len;
145 unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg); 145 unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg);
146 int ret; 146 int ret = -EINVAL;
147 147
148 transport_len = ntohs(ipv6_hdr(skb)->payload_len); 148 transport_len = ntohs(ipv6_hdr(skb)->payload_len);
149 transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr); 149 transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr);
150 150
151 skb_get(skb);
152 skb_chk = skb_checksum_trimmed(skb, transport_len, 151 skb_chk = skb_checksum_trimmed(skb, transport_len,
153 ipv6_mc_validate_checksum); 152 ipv6_mc_validate_checksum);
154 if (!skb_chk) 153 if (!skb_chk)
155 return -EINVAL; 154 goto err;
156 155
157 if (!pskb_may_pull(skb_chk, len)) { 156 if (!pskb_may_pull(skb_chk, len))
158 kfree_skb(skb_chk); 157 goto err;
159 return -EINVAL;
160 }
161 158
162 ret = ipv6_mc_check_mld_msg(skb_chk); 159 ret = ipv6_mc_check_mld_msg(skb_chk);
163 if (ret) { 160 if (ret)
164 kfree_skb(skb_chk); 161 goto err;
165 return ret;
166 }
167 162
168 if (skb_trimmed) 163 if (skb_trimmed)
169 *skb_trimmed = skb_chk; 164 *skb_trimmed = skb_chk;
170 else 165 /* free now unneeded clone */
166 else if (skb_chk != skb)
171 kfree_skb(skb_chk); 167 kfree_skb(skb_chk);
172 168
173 return 0; 169 ret = 0;
170
171err:
172 if (ret && skb_chk && skb_chk != skb)
173 kfree_skb(skb_chk);
174
175 return ret;
174} 176}
175 177
176/** 178/**
@@ -179,7 +181,7 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb,
179 * @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional) 181 * @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional)
180 * 182 *
181 * Checks whether an IPv6 packet is a valid MLD packet. If so sets 183 * Checks whether an IPv6 packet is a valid MLD packet. If so sets
182 * skb network and transport headers accordingly and returns zero. 184 * skb transport header accordingly and returns zero.
183 * 185 *
184 * -EINVAL: A broken packet was detected, i.e. it violates some internet 186 * -EINVAL: A broken packet was detected, i.e. it violates some internet
185 * standard 187 * standard
@@ -194,7 +196,8 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb,
194 * to leave the original skb and its full frame unchanged (which might be 196 * to leave the original skb and its full frame unchanged (which might be
195 * desirable for layer 2 frame jugglers). 197 * desirable for layer 2 frame jugglers).
196 * 198 *
197 * The caller needs to release a reference count from any returned skb_trimmed. 199 * Caller needs to set the skb network header and free any returned skb if it
200 * differs from the provided skb.
198 */ 201 */
199int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed) 202int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed)
200{ 203{
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 6edb7b106de7..ebbb754c2111 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -37,12 +37,13 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
37} 37}
38 38
39static void 39static void
40synproxy_send_tcp(const struct sk_buff *skb, struct sk_buff *nskb, 40synproxy_send_tcp(const struct synproxy_net *snet,
41 const struct sk_buff *skb, struct sk_buff *nskb,
41 struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo, 42 struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
42 struct ipv6hdr *niph, struct tcphdr *nth, 43 struct ipv6hdr *niph, struct tcphdr *nth,
43 unsigned int tcp_hdr_size) 44 unsigned int tcp_hdr_size)
44{ 45{
45 struct net *net = nf_ct_net((struct nf_conn *)nfct); 46 struct net *net = nf_ct_net(snet->tmpl);
46 struct dst_entry *dst; 47 struct dst_entry *dst;
47 struct flowi6 fl6; 48 struct flowi6 fl6;
48 49
@@ -83,7 +84,8 @@ free_nskb:
83} 84}
84 85
85static void 86static void
86synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th, 87synproxy_send_client_synack(const struct synproxy_net *snet,
88 const struct sk_buff *skb, const struct tcphdr *th,
87 const struct synproxy_options *opts) 89 const struct synproxy_options *opts)
88{ 90{
89 struct sk_buff *nskb; 91 struct sk_buff *nskb;
@@ -119,7 +121,7 @@ synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th,
119 121
120 synproxy_build_options(nth, opts); 122 synproxy_build_options(nth, opts);
121 123
122 synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, 124 synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
123 niph, nth, tcp_hdr_size); 125 niph, nth, tcp_hdr_size);
124} 126}
125 127
@@ -163,7 +165,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
163 165
164 synproxy_build_options(nth, opts); 166 synproxy_build_options(nth, opts);
165 167
166 synproxy_send_tcp(skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW, 168 synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
167 niph, nth, tcp_hdr_size); 169 niph, nth, tcp_hdr_size);
168} 170}
169 171
@@ -203,7 +205,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
203 205
204 synproxy_build_options(nth, opts); 206 synproxy_build_options(nth, opts);
205 207
206 synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); 208 synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
207} 209}
208 210
209static void 211static void
@@ -241,7 +243,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
241 243
242 synproxy_build_options(nth, opts); 244 synproxy_build_options(nth, opts);
243 245
244 synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); 246 synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
247 niph, nth, tcp_hdr_size);
245} 248}
246 249
247static bool 250static bool
@@ -301,7 +304,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
301 XT_SYNPROXY_OPT_SACK_PERM | 304 XT_SYNPROXY_OPT_SACK_PERM |
302 XT_SYNPROXY_OPT_ECN); 305 XT_SYNPROXY_OPT_ECN);
303 306
304 synproxy_send_client_synack(skb, th, &opts); 307 synproxy_send_client_synack(snet, skb, th, &opts);
305 return NF_DROP; 308 return NF_DROP;
306 309
307 } else if (th->ack && !(th->fin || th->rst || th->syn)) { 310 } else if (th->ack && !(th->fin || th->rst || th->syn)) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 6090969937f8..d15586490cec 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -318,8 +318,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
318/* allocate dst with ip6_dst_ops */ 318/* allocate dst with ip6_dst_ops */
319static struct rt6_info *__ip6_dst_alloc(struct net *net, 319static struct rt6_info *__ip6_dst_alloc(struct net *net,
320 struct net_device *dev, 320 struct net_device *dev,
321 int flags, 321 int flags)
322 struct fib6_table *table)
323{ 322{
324 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, 323 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
325 0, DST_OBSOLETE_FORCE_CHK, flags); 324 0, DST_OBSOLETE_FORCE_CHK, flags);
@@ -336,10 +335,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net,
336 335
337static struct rt6_info *ip6_dst_alloc(struct net *net, 336static struct rt6_info *ip6_dst_alloc(struct net *net,
338 struct net_device *dev, 337 struct net_device *dev,
339 int flags, 338 int flags)
340 struct fib6_table *table)
341{ 339{
342 struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags, table); 340 struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags);
343 341
344 if (rt) { 342 if (rt) {
345 rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC); 343 rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC);
@@ -950,8 +948,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
950 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) 948 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
951 ort = (struct rt6_info *)ort->dst.from; 949 ort = (struct rt6_info *)ort->dst.from;
952 950
953 rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 951 rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0);
954 0, ort->rt6i_table);
955 952
956 if (!rt) 953 if (!rt)
957 return NULL; 954 return NULL;
@@ -983,8 +980,7 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
983 struct rt6_info *pcpu_rt; 980 struct rt6_info *pcpu_rt;
984 981
985 pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev), 982 pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev),
986 rt->dst.dev, rt->dst.flags, 983 rt->dst.dev, rt->dst.flags);
987 rt->rt6i_table);
988 984
989 if (!pcpu_rt) 985 if (!pcpu_rt)
990 return NULL; 986 return NULL;
@@ -997,32 +993,53 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
997/* It should be called with read_lock_bh(&tb6_lock) acquired */ 993/* It should be called with read_lock_bh(&tb6_lock) acquired */
998static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt) 994static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt)
999{ 995{
1000 struct rt6_info *pcpu_rt, *prev, **p; 996 struct rt6_info *pcpu_rt, **p;
1001 997
1002 p = this_cpu_ptr(rt->rt6i_pcpu); 998 p = this_cpu_ptr(rt->rt6i_pcpu);
1003 pcpu_rt = *p; 999 pcpu_rt = *p;
1004 1000
1005 if (pcpu_rt) 1001 if (pcpu_rt) {
1006 goto done; 1002 dst_hold(&pcpu_rt->dst);
1003 rt6_dst_from_metrics_check(pcpu_rt);
1004 }
1005 return pcpu_rt;
1006}
1007
1008static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt)
1009{
1010 struct fib6_table *table = rt->rt6i_table;
1011 struct rt6_info *pcpu_rt, *prev, **p;
1007 1012
1008 pcpu_rt = ip6_rt_pcpu_alloc(rt); 1013 pcpu_rt = ip6_rt_pcpu_alloc(rt);
1009 if (!pcpu_rt) { 1014 if (!pcpu_rt) {
1010 struct net *net = dev_net(rt->dst.dev); 1015 struct net *net = dev_net(rt->dst.dev);
1011 1016
1012 pcpu_rt = net->ipv6.ip6_null_entry; 1017 dst_hold(&net->ipv6.ip6_null_entry->dst);
1013 goto done; 1018 return net->ipv6.ip6_null_entry;
1014 } 1019 }
1015 1020
1016 prev = cmpxchg(p, NULL, pcpu_rt); 1021 read_lock_bh(&table->tb6_lock);
1017 if (prev) { 1022 if (rt->rt6i_pcpu) {
1018 /* If someone did it before us, return prev instead */ 1023 p = this_cpu_ptr(rt->rt6i_pcpu);
1024 prev = cmpxchg(p, NULL, pcpu_rt);
1025 if (prev) {
1026 /* If someone did it before us, return prev instead */
1027 dst_destroy(&pcpu_rt->dst);
1028 pcpu_rt = prev;
1029 }
1030 } else {
1031 /* rt has been removed from the fib6 tree
1032 * before we have a chance to acquire the read_lock.
1033 * In this case, don't brother to create a pcpu rt
1034 * since rt is going away anyway. The next
1035 * dst_check() will trigger a re-lookup.
1036 */
1019 dst_destroy(&pcpu_rt->dst); 1037 dst_destroy(&pcpu_rt->dst);
1020 pcpu_rt = prev; 1038 pcpu_rt = rt;
1021 } 1039 }
1022
1023done:
1024 dst_hold(&pcpu_rt->dst); 1040 dst_hold(&pcpu_rt->dst);
1025 rt6_dst_from_metrics_check(pcpu_rt); 1041 rt6_dst_from_metrics_check(pcpu_rt);
1042 read_unlock_bh(&table->tb6_lock);
1026 return pcpu_rt; 1043 return pcpu_rt;
1027} 1044}
1028 1045
@@ -1097,9 +1114,22 @@ redo_rt6_select:
1097 rt->dst.lastuse = jiffies; 1114 rt->dst.lastuse = jiffies;
1098 rt->dst.__use++; 1115 rt->dst.__use++;
1099 pcpu_rt = rt6_get_pcpu_route(rt); 1116 pcpu_rt = rt6_get_pcpu_route(rt);
1100 read_unlock_bh(&table->tb6_lock); 1117
1118 if (pcpu_rt) {
1119 read_unlock_bh(&table->tb6_lock);
1120 } else {
1121 /* We have to do the read_unlock first
1122 * because rt6_make_pcpu_route() may trigger
1123 * ip6_dst_gc() which will take the write_lock.
1124 */
1125 dst_hold(&rt->dst);
1126 read_unlock_bh(&table->tb6_lock);
1127 pcpu_rt = rt6_make_pcpu_route(rt);
1128 dst_release(&rt->dst);
1129 }
1101 1130
1102 return pcpu_rt; 1131 return pcpu_rt;
1132
1103 } 1133 }
1104} 1134}
1105 1135
@@ -1555,7 +1585,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1555 if (unlikely(!idev)) 1585 if (unlikely(!idev))
1556 return ERR_PTR(-ENODEV); 1586 return ERR_PTR(-ENODEV);
1557 1587
1558 rt = ip6_dst_alloc(net, dev, 0, NULL); 1588 rt = ip6_dst_alloc(net, dev, 0);
1559 if (unlikely(!rt)) { 1589 if (unlikely(!rt)) {
1560 in6_dev_put(idev); 1590 in6_dev_put(idev);
1561 dst = ERR_PTR(-ENOMEM); 1591 dst = ERR_PTR(-ENOMEM);
@@ -1742,7 +1772,8 @@ int ip6_route_add(struct fib6_config *cfg)
1742 if (!table) 1772 if (!table)
1743 goto out; 1773 goto out;
1744 1774
1745 rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); 1775 rt = ip6_dst_alloc(net, NULL,
1776 (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT);
1746 1777
1747 if (!rt) { 1778 if (!rt) {
1748 err = -ENOMEM; 1779 err = -ENOMEM;
@@ -1831,6 +1862,7 @@ int ip6_route_add(struct fib6_config *cfg)
1831 int gwa_type; 1862 int gwa_type;
1832 1863
1833 gw_addr = &cfg->fc_gateway; 1864 gw_addr = &cfg->fc_gateway;
1865 gwa_type = ipv6_addr_type(gw_addr);
1834 1866
1835 /* if gw_addr is local we will fail to detect this in case 1867 /* if gw_addr is local we will fail to detect this in case
1836 * address is still TENTATIVE (DAD in progress). rt6_lookup() 1868 * address is still TENTATIVE (DAD in progress). rt6_lookup()
@@ -1838,11 +1870,12 @@ int ip6_route_add(struct fib6_config *cfg)
1838 * prefix route was assigned to, which might be non-loopback. 1870 * prefix route was assigned to, which might be non-loopback.
1839 */ 1871 */
1840 err = -EINVAL; 1872 err = -EINVAL;
1841 if (ipv6_chk_addr_and_flags(net, gw_addr, NULL, 0, 0)) 1873 if (ipv6_chk_addr_and_flags(net, gw_addr,
1874 gwa_type & IPV6_ADDR_LINKLOCAL ?
1875 dev : NULL, 0, 0))
1842 goto out; 1876 goto out;
1843 1877
1844 rt->rt6i_gateway = *gw_addr; 1878 rt->rt6i_gateway = *gw_addr;
1845 gwa_type = ipv6_addr_type(gw_addr);
1846 1879
1847 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { 1880 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
1848 struct rt6_info *grt; 1881 struct rt6_info *grt;
@@ -2397,7 +2430,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2397{ 2430{
2398 struct net *net = dev_net(idev->dev); 2431 struct net *net = dev_net(idev->dev);
2399 struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 2432 struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
2400 DST_NOCOUNT, NULL); 2433 DST_NOCOUNT);
2401 if (!rt) 2434 if (!rt)
2402 return ERR_PTR(-ENOMEM); 2435 return ERR_PTR(-ENOMEM);
2403 2436
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6748c4277aff..7a6cea5e4274 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -943,7 +943,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
943 &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); 943 &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
944 if (req) { 944 if (req) {
945 nsk = tcp_check_req(sk, skb, req, false); 945 nsk = tcp_check_req(sk, skb, req, false);
946 if (!nsk) 946 if (!nsk || nsk == sk)
947 reqsk_put(req); 947 reqsk_put(req);
948 return nsk; 948 return nsk;
949 } 949 }