diff options
author | David S. Miller <davem@davemloft.net> | 2013-06-05 18:56:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-05 19:37:30 -0400 |
commit | 6bc19fb82d4c05a9eee19d6d2aab2ce26e499ec2 (patch) | |
tree | 8b049ef383307f5dae91b5c9cf78dbfb9b74a4d1 /net | |
parent | 11a164a04382d735230b01f4cc46ad78a7c4abf6 (diff) | |
parent | 4d3797d7e1861ac1af150a6189315786c5e1c820 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Merge 'net' bug fixes into 'net-next' as we have patches
that will build on top of them.
This merge commit includes a change from Emil Goode
(emilgoode@gmail.com) that fixes a warning that would
have been introduced by this merge. Specifically it
fixes the pingv6_ops method ipv6_chk_addr() to add a
"const" to the "struct net_device *dev" argument and
likewise update the dummy_ipv6_chk_addr() declaration.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
36 files changed, 297 insertions, 121 deletions
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index c013f38482a1..6cda4e2c2132 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c | |||
@@ -39,6 +39,7 @@ static int __hw_addr_create_ex(struct netdev_hw_addr_list *list, | |||
39 | ha->refcount = 1; | 39 | ha->refcount = 1; |
40 | ha->global_use = global; | 40 | ha->global_use = global; |
41 | ha->synced = sync; | 41 | ha->synced = sync; |
42 | ha->sync_cnt = 0; | ||
42 | list_add_tail_rcu(&ha->list, &list->list); | 43 | list_add_tail_rcu(&ha->list, &list->list); |
43 | list->count++; | 44 | list->count++; |
44 | 45 | ||
@@ -66,7 +67,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, | |||
66 | } | 67 | } |
67 | if (sync) { | 68 | if (sync) { |
68 | if (ha->synced) | 69 | if (ha->synced) |
69 | return 0; | 70 | return -EEXIST; |
70 | else | 71 | else |
71 | ha->synced = true; | 72 | ha->synced = true; |
72 | } | 73 | } |
@@ -139,10 +140,13 @@ static int __hw_addr_sync_one(struct netdev_hw_addr_list *to_list, | |||
139 | 140 | ||
140 | err = __hw_addr_add_ex(to_list, ha->addr, addr_len, ha->type, | 141 | err = __hw_addr_add_ex(to_list, ha->addr, addr_len, ha->type, |
141 | false, true); | 142 | false, true); |
142 | if (err) | 143 | if (err && err != -EEXIST) |
143 | return err; | 144 | return err; |
144 | ha->sync_cnt++; | 145 | |
145 | ha->refcount++; | 146 | if (!err) { |
147 | ha->sync_cnt++; | ||
148 | ha->refcount++; | ||
149 | } | ||
146 | 150 | ||
147 | return 0; | 151 | return 0; |
148 | } | 152 | } |
@@ -159,7 +163,8 @@ static void __hw_addr_unsync_one(struct netdev_hw_addr_list *to_list, | |||
159 | if (err) | 163 | if (err) |
160 | return; | 164 | return; |
161 | ha->sync_cnt--; | 165 | ha->sync_cnt--; |
162 | __hw_addr_del_entry(from_list, ha, false, true); | 166 | /* address on from list is not marked synced */ |
167 | __hw_addr_del_entry(from_list, ha, false, false); | ||
163 | } | 168 | } |
164 | 169 | ||
165 | static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list, | 170 | static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list, |
@@ -796,7 +801,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from) | |||
796 | return -EINVAL; | 801 | return -EINVAL; |
797 | 802 | ||
798 | netif_addr_lock_nested(to); | 803 | netif_addr_lock_nested(to); |
799 | err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); | 804 | err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len); |
800 | if (!err) | 805 | if (!err) |
801 | __dev_set_rx_mode(to); | 806 | __dev_set_rx_mode(to); |
802 | netif_addr_unlock(to); | 807 | netif_addr_unlock(to); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6b1b52c5593b..73f57a0e1523 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -195,7 +195,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node) | |||
195 | * the tail pointer in struct sk_buff! | 195 | * the tail pointer in struct sk_buff! |
196 | */ | 196 | */ |
197 | memset(skb, 0, offsetof(struct sk_buff, tail)); | 197 | memset(skb, 0, offsetof(struct sk_buff, tail)); |
198 | skb->data = NULL; | 198 | skb->head = NULL; |
199 | skb->truesize = sizeof(struct sk_buff); | 199 | skb->truesize = sizeof(struct sk_buff); |
200 | atomic_set(&skb->users, 1); | 200 | atomic_set(&skb->users, 1); |
201 | 201 | ||
@@ -605,7 +605,7 @@ static void skb_release_head_state(struct sk_buff *skb) | |||
605 | static void skb_release_all(struct sk_buff *skb) | 605 | static void skb_release_all(struct sk_buff *skb) |
606 | { | 606 | { |
607 | skb_release_head_state(skb); | 607 | skb_release_head_state(skb); |
608 | if (likely(skb->data)) | 608 | if (likely(skb->head)) |
609 | skb_release_data(skb); | 609 | skb_release_data(skb); |
610 | } | 610 | } |
611 | 611 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 6ba327da79e1..88868a9d21da 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -210,7 +210,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = { | |||
210 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , | 210 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , |
211 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , | 211 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , |
212 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" , | 212 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" , |
213 | "sk_lock-AF_NFC" , "sk_lock-AF_MAX" | 213 | "sk_lock-AF_NFC" , "sk_lock-AF_VSOCK" , "sk_lock-AF_MAX" |
214 | }; | 214 | }; |
215 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { | 215 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { |
216 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , | 216 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , |
@@ -226,7 +226,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = { | |||
226 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , | 226 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , |
227 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , | 227 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , |
228 | "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" , | 228 | "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" , |
229 | "slock-AF_NFC" , "slock-AF_MAX" | 229 | "slock-AF_NFC" , "slock-AF_VSOCK" ,"slock-AF_MAX" |
230 | }; | 230 | }; |
231 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { | 231 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { |
232 | "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , | 232 | "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , |
@@ -242,7 +242,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = { | |||
242 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , | 242 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , |
243 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , | 243 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , |
244 | "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" , | 244 | "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" , |
245 | "clock-AF_NFC" , "clock-AF_MAX" | 245 | "clock-AF_NFC" , "clock-AF_VSOCK" , "clock-AF_MAX" |
246 | }; | 246 | }; |
247 | 247 | ||
248 | /* | 248 | /* |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index b89095c1518f..7c79cf8ad449 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -503,6 +503,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
503 | 503 | ||
504 | inner_iph = (const struct iphdr *)skb_inner_network_header(skb); | 504 | inner_iph = (const struct iphdr *)skb_inner_network_header(skb); |
505 | 505 | ||
506 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | ||
506 | dst = tnl_params->daddr; | 507 | dst = tnl_params->daddr; |
507 | if (dst == 0) { | 508 | if (dst == 0) { |
508 | /* NBMA tunnel */ | 509 | /* NBMA tunnel */ |
@@ -658,7 +659,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
658 | 659 | ||
659 | skb_dst_drop(skb); | 660 | skb_dst_drop(skb); |
660 | skb_dst_set(skb, &rt->dst); | 661 | skb_dst_set(skb, &rt->dst); |
661 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | ||
662 | 662 | ||
663 | /* Push down and install the IP header. */ | 663 | /* Push down and install the IP header. */ |
664 | skb_push(skb, sizeof(struct iphdr)); | 664 | skb_push(skb, sizeof(struct iphdr)); |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index cf08218ddbcf..ff4b781b1056 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -231,8 +231,10 @@ static void ipt_ulog_packet(struct net *net, | |||
231 | put_unaligned(tv.tv_usec, &pm->timestamp_usec); | 231 | put_unaligned(tv.tv_usec, &pm->timestamp_usec); |
232 | put_unaligned(skb->mark, &pm->mark); | 232 | put_unaligned(skb->mark, &pm->mark); |
233 | pm->hook = hooknum; | 233 | pm->hook = hooknum; |
234 | if (prefix != NULL) | 234 | if (prefix != NULL) { |
235 | strncpy(pm->prefix, prefix, sizeof(pm->prefix)); | 235 | strncpy(pm->prefix, prefix, sizeof(pm->prefix) - 1); |
236 | pm->prefix[sizeof(pm->prefix) - 1] = '\0'; | ||
237 | } | ||
236 | else if (loginfo->prefix[0] != '\0') | 238 | else if (loginfo->prefix[0] != '\0') |
237 | strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); | 239 | strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); |
238 | else | 240 | else |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 403e28302869..198ea596f2d9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -768,10 +768,15 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf | |||
768 | { | 768 | { |
769 | struct rtable *rt; | 769 | struct rtable *rt; |
770 | struct flowi4 fl4; | 770 | struct flowi4 fl4; |
771 | const struct iphdr *iph = (const struct iphdr *) skb->data; | ||
772 | int oif = skb->dev->ifindex; | ||
773 | u8 tos = RT_TOS(iph->tos); | ||
774 | u8 prot = iph->protocol; | ||
775 | u32 mark = skb->mark; | ||
771 | 776 | ||
772 | rt = (struct rtable *) dst; | 777 | rt = (struct rtable *) dst; |
773 | 778 | ||
774 | ip_rt_build_flow_key(&fl4, sk, skb); | 779 | __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0); |
775 | __ip_do_redirect(rt, skb, &fl4, true); | 780 | __ip_do_redirect(rt, skb, &fl4, true); |
776 | } | 781 | } |
777 | 782 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7b34f06af344..21010fddb203 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1486,7 +1486,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1486 | } | 1486 | } |
1487 | 1487 | ||
1488 | int ipv6_chk_addr(struct net *net, const struct in6_addr *addr, | 1488 | int ipv6_chk_addr(struct net *net, const struct in6_addr *addr, |
1489 | struct net_device *dev, int strict) | 1489 | const struct net_device *dev, int strict) |
1490 | { | 1490 | { |
1491 | struct inet6_ifaddr *ifp; | 1491 | struct inet6_ifaddr *ifp; |
1492 | unsigned int hash = inet6_addr_hash(addr); | 1492 | unsigned int hash = inet6_addr_hash(addr); |
@@ -2660,8 +2660,10 @@ static void init_loopback(struct net_device *dev) | |||
2660 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); | 2660 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); |
2661 | 2661 | ||
2662 | /* Failure cases are ignored */ | 2662 | /* Failure cases are ignored */ |
2663 | if (!IS_ERR(sp_rt)) | 2663 | if (!IS_ERR(sp_rt)) { |
2664 | sp_ifa->rt = sp_rt; | ||
2664 | ip6_ins_rt(sp_rt); | 2665 | ip6_ins_rt(sp_rt); |
2666 | } | ||
2665 | } | 2667 | } |
2666 | read_unlock_bh(&idev->lock); | 2668 | read_unlock_bh(&idev->lock); |
2667 | } | 2669 | } |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 72836f40b730..95f3f1da0d7f 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/netfilter.h> | 10 | #include <linux/netfilter.h> |
11 | #include <linux/netfilter_ipv6.h> | 11 | #include <linux/netfilter_ipv6.h> |
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <net/addrconf.h> | ||
13 | #include <net/dst.h> | 14 | #include <net/dst.h> |
14 | #include <net/ipv6.h> | 15 | #include <net/ipv6.h> |
15 | #include <net/ip6_route.h> | 16 | #include <net/ip6_route.h> |
@@ -186,6 +187,10 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
186 | return csum; | 187 | return csum; |
187 | }; | 188 | }; |
188 | 189 | ||
190 | static const struct nf_ipv6_ops ipv6ops = { | ||
191 | .chk_addr = ipv6_chk_addr, | ||
192 | }; | ||
193 | |||
189 | static const struct nf_afinfo nf_ip6_afinfo = { | 194 | static const struct nf_afinfo nf_ip6_afinfo = { |
190 | .family = AF_INET6, | 195 | .family = AF_INET6, |
191 | .checksum = nf_ip6_checksum, | 196 | .checksum = nf_ip6_checksum, |
@@ -198,6 +203,7 @@ static const struct nf_afinfo nf_ip6_afinfo = { | |||
198 | 203 | ||
199 | int __init ipv6_netfilter_init(void) | 204 | int __init ipv6_netfilter_init(void) |
200 | { | 205 | { |
206 | RCU_INIT_POINTER(nf_ipv6_ops, &ipv6ops); | ||
201 | return nf_register_afinfo(&nf_ip6_afinfo); | 207 | return nf_register_afinfo(&nf_ip6_afinfo); |
202 | } | 208 | } |
203 | 209 | ||
@@ -206,5 +212,6 @@ int __init ipv6_netfilter_init(void) | |||
206 | */ | 212 | */ |
207 | void ipv6_netfilter_fini(void) | 213 | void ipv6_netfilter_fini(void) |
208 | { | 214 | { |
215 | RCU_INIT_POINTER(nf_ipv6_ops, NULL); | ||
209 | nf_unregister_afinfo(&nf_ip6_afinfo); | 216 | nf_unregister_afinfo(&nf_ip6_afinfo); |
210 | } | 217 | } |
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 62ac5f2e0aaf..a43110385918 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
@@ -73,7 +73,7 @@ int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) | |||
73 | void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | 73 | void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, |
74 | __be16 port, u32 info, u8 *payload) {} | 74 | __be16 port, u32 info, u8 *payload) {} |
75 | int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, | 75 | int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, |
76 | struct net_device *dev, int strict) | 76 | const struct net_device *dev, int strict) |
77 | { | 77 | { |
78 | return 0; | 78 | return 0; |
79 | } | 79 | } |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index f3c1ff4357ff..51c3285b5d9b 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -90,7 +90,7 @@ static const struct snmp_mib snmp6_ipstats_list[] = { | |||
90 | SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), | 90 | SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), |
91 | SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), | 91 | SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), |
92 | SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), | 92 | SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), |
93 | SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS), | 93 | /* IPSTATS_MIB_CSUMERRORS is not relevant in IPv6 (no checksum) */ |
94 | SNMP_MIB_SENTINEL | 94 | SNMP_MIB_SENTINEL |
95 | }; | 95 | }; |
96 | 96 | ||
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 76d401a93c7a..5d1b8d7ac993 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
@@ -46,11 +46,12 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
46 | unsigned int mss; | 46 | unsigned int mss; |
47 | unsigned int unfrag_ip6hlen, unfrag_len; | 47 | unsigned int unfrag_ip6hlen, unfrag_len; |
48 | struct frag_hdr *fptr; | 48 | struct frag_hdr *fptr; |
49 | u8 *mac_start, *prevhdr; | 49 | u8 *packet_start, *prevhdr; |
50 | u8 nexthdr; | 50 | u8 nexthdr; |
51 | u8 frag_hdr_sz = sizeof(struct frag_hdr); | 51 | u8 frag_hdr_sz = sizeof(struct frag_hdr); |
52 | int offset; | 52 | int offset; |
53 | __wsum csum; | 53 | __wsum csum; |
54 | int tnl_hlen; | ||
54 | 55 | ||
55 | mss = skb_shinfo(skb)->gso_size; | 56 | mss = skb_shinfo(skb)->gso_size; |
56 | if (unlikely(skb->len <= mss)) | 57 | if (unlikely(skb->len <= mss)) |
@@ -84,9 +85,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
84 | skb->ip_summed = CHECKSUM_NONE; | 85 | skb->ip_summed = CHECKSUM_NONE; |
85 | 86 | ||
86 | /* Check if there is enough headroom to insert fragment header. */ | 87 | /* Check if there is enough headroom to insert fragment header. */ |
87 | if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && | 88 | tnl_hlen = skb_tnl_header_len(skb); |
88 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) | 89 | if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) { |
89 | goto out; | 90 | if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz)) |
91 | goto out; | ||
92 | } | ||
90 | 93 | ||
91 | /* Find the unfragmentable header and shift it left by frag_hdr_sz | 94 | /* Find the unfragmentable header and shift it left by frag_hdr_sz |
92 | * bytes to insert fragment header. | 95 | * bytes to insert fragment header. |
@@ -94,11 +97,12 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
94 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); | 97 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); |
95 | nexthdr = *prevhdr; | 98 | nexthdr = *prevhdr; |
96 | *prevhdr = NEXTHDR_FRAGMENT; | 99 | *prevhdr = NEXTHDR_FRAGMENT; |
97 | unfrag_len = skb_network_header(skb) - skb_mac_header(skb) + | 100 | unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) + |
98 | unfrag_ip6hlen; | 101 | unfrag_ip6hlen + tnl_hlen; |
99 | mac_start = skb_mac_header(skb); | 102 | packet_start = (u8 *) skb->head + SKB_GSO_CB(skb)->mac_offset; |
100 | memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len); | 103 | memmove(packet_start-frag_hdr_sz, packet_start, unfrag_len); |
101 | 104 | ||
105 | SKB_GSO_CB(skb)->mac_offset -= frag_hdr_sz; | ||
102 | skb->mac_header -= frag_hdr_sz; | 106 | skb->mac_header -= frag_hdr_sz; |
103 | skb->network_header -= frag_hdr_sz; | 107 | skb->network_header -= frag_hdr_sz; |
104 | 108 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index 5b1e5af25713..c5fbd7589681 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -2366,6 +2366,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa | |||
2366 | 2366 | ||
2367 | out: | 2367 | out: |
2368 | xfrm_pol_put(xp); | 2368 | xfrm_pol_put(xp); |
2369 | if (err == 0) | ||
2370 | xfrm_garbage_collect(net); | ||
2369 | return err; | 2371 | return err; |
2370 | } | 2372 | } |
2371 | 2373 | ||
@@ -2615,6 +2617,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_ | |||
2615 | 2617 | ||
2616 | out: | 2618 | out: |
2617 | xfrm_pol_put(xp); | 2619 | xfrm_pol_put(xp); |
2620 | if (delete && err == 0) | ||
2621 | xfrm_garbage_collect(net); | ||
2618 | return err; | 2622 | return err; |
2619 | } | 2623 | } |
2620 | 2624 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d2c3fd178dbe..7c3ba8628d4e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
159 | return 0; | 159 | return 0; |
160 | } | 160 | } |
161 | 161 | ||
162 | static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) | 162 | static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr) |
163 | { | 163 | { |
164 | struct ieee80211_sub_if_data *sdata; | 164 | struct ieee80211_local *local = sdata->local; |
165 | struct ieee80211_sub_if_data *iter; | ||
165 | u64 new, mask, tmp; | 166 | u64 new, mask, tmp; |
166 | u8 *m; | 167 | u8 *m; |
167 | int ret = 0; | 168 | int ret = 0; |
@@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) | |||
181 | 182 | ||
182 | 183 | ||
183 | mutex_lock(&local->iflist_mtx); | 184 | mutex_lock(&local->iflist_mtx); |
184 | list_for_each_entry(sdata, &local->interfaces, list) { | 185 | list_for_each_entry(iter, &local->interfaces, list) { |
185 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | 186 | if (iter == sdata) |
187 | continue; | ||
188 | |||
189 | if (iter->vif.type == NL80211_IFTYPE_MONITOR) | ||
186 | continue; | 190 | continue; |
187 | 191 | ||
188 | m = sdata->vif.addr; | 192 | m = iter->vif.addr; |
189 | tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | 193 | tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | |
190 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | 194 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | |
191 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | 195 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); |
@@ -209,7 +213,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) | |||
209 | if (ieee80211_sdata_running(sdata)) | 213 | if (ieee80211_sdata_running(sdata)) |
210 | return -EBUSY; | 214 | return -EBUSY; |
211 | 215 | ||
212 | ret = ieee80211_verify_mac(sdata->local, sa->sa_data); | 216 | ret = ieee80211_verify_mac(sdata, sa->sa_data); |
213 | if (ret) | 217 | if (ret) |
214 | return ret; | 218 | return ret; |
215 | 219 | ||
@@ -474,6 +478,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
474 | master->control_port_protocol; | 478 | master->control_port_protocol; |
475 | sdata->control_port_no_encrypt = | 479 | sdata->control_port_no_encrypt = |
476 | master->control_port_no_encrypt; | 480 | master->control_port_no_encrypt; |
481 | sdata->vif.cab_queue = master->vif.cab_queue; | ||
482 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, | ||
483 | sizeof(sdata->vif.hw_queue)); | ||
477 | break; | 484 | break; |
478 | } | 485 | } |
479 | case NL80211_IFTYPE_AP: | 486 | case NL80211_IFTYPE_AP: |
@@ -653,7 +660,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
653 | 660 | ||
654 | ieee80211_recalc_ps(local, -1); | 661 | ieee80211_recalc_ps(local, -1); |
655 | 662 | ||
656 | if (dev) { | 663 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
664 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | ||
665 | /* XXX: for AP_VLAN, actually track AP queues */ | ||
666 | netif_tx_start_all_queues(dev); | ||
667 | } else if (dev) { | ||
657 | unsigned long flags; | 668 | unsigned long flags; |
658 | int n_acs = IEEE80211_NUM_ACS; | 669 | int n_acs = IEEE80211_NUM_ACS; |
659 | int ac; | 670 | int ac; |
@@ -1479,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1479 | break; | 1490 | break; |
1480 | } | 1491 | } |
1481 | 1492 | ||
1493 | /* | ||
1494 | * Pick address of existing interface in case user changed | ||
1495 | * MAC address manually, default to perm_addr. | ||
1496 | */ | ||
1482 | m = local->hw.wiphy->perm_addr; | 1497 | m = local->hw.wiphy->perm_addr; |
1498 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1499 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | ||
1500 | continue; | ||
1501 | m = sdata->vif.addr; | ||
1502 | break; | ||
1503 | } | ||
1483 | start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | 1504 | start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | |
1484 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | 1505 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | |
1485 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | 1506 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); |
@@ -1696,6 +1717,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1696 | 1717 | ||
1697 | ASSERT_RTNL(); | 1718 | ASSERT_RTNL(); |
1698 | 1719 | ||
1720 | /* | ||
1721 | * Close all AP_VLAN interfaces first, as otherwise they | ||
1722 | * might be closed while the AP interface they belong to | ||
1723 | * is closed, causing unregister_netdevice_many() to crash. | ||
1724 | */ | ||
1725 | list_for_each_entry(sdata, &local->interfaces, list) | ||
1726 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1727 | dev_close(sdata->dev); | ||
1728 | |||
1699 | mutex_lock(&local->iflist_mtx); | 1729 | mutex_lock(&local->iflist_mtx); |
1700 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1730 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1701 | list_del(&sdata->list); | 1731 | list_del(&sdata->list); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a46e490f20dd..a8c2130c8ba4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3321,10 +3321,6 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
3321 | if (WARN_ON_ONCE(!auth_data)) | 3321 | if (WARN_ON_ONCE(!auth_data)) |
3322 | return -EINVAL; | 3322 | return -EINVAL; |
3323 | 3323 | ||
3324 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
3325 | tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
3326 | IEEE80211_TX_INTFL_MLME_CONN_TX; | ||
3327 | |||
3328 | auth_data->tries++; | 3324 | auth_data->tries++; |
3329 | 3325 | ||
3330 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | 3326 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { |
@@ -3358,6 +3354,10 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
3358 | auth_data->expected_transaction = trans; | 3354 | auth_data->expected_transaction = trans; |
3359 | } | 3355 | } |
3360 | 3356 | ||
3357 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
3358 | tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
3359 | IEEE80211_TX_INTFL_MLME_CONN_TX; | ||
3360 | |||
3361 | ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, | 3361 | ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, |
3362 | auth_data->data, auth_data->data_len, | 3362 | auth_data->data, auth_data->data_len, |
3363 | auth_data->bss->bssid, | 3363 | auth_data->bss->bssid, |
@@ -3381,12 +3381,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
3381 | * will not answer to direct packet in unassociated state. | 3381 | * will not answer to direct packet in unassociated state. |
3382 | */ | 3382 | */ |
3383 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | 3383 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], |
3384 | NULL, 0, (u32) -1, true, tx_flags, | 3384 | NULL, 0, (u32) -1, true, 0, |
3385 | auth_data->bss->channel, false); | 3385 | auth_data->bss->channel, false); |
3386 | rcu_read_unlock(); | 3386 | rcu_read_unlock(); |
3387 | } | 3387 | } |
3388 | 3388 | ||
3389 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { | 3389 | if (tx_flags == 0) { |
3390 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 3390 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
3391 | ifmgd->auth_data->timeout_started = true; | 3391 | ifmgd->auth_data->timeout_started = true; |
3392 | run_again(ifmgd, auth_data->timeout); | 3392 | run_again(ifmgd, auth_data->timeout); |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 07c865a31a3d..857ca9f35177 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -30,6 +30,8 @@ static DEFINE_MUTEX(afinfo_mutex); | |||
30 | 30 | ||
31 | const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; | 31 | const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; |
32 | EXPORT_SYMBOL(nf_afinfo); | 32 | EXPORT_SYMBOL(nf_afinfo); |
33 | const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly; | ||
34 | EXPORT_SYMBOL_GPL(nf_ipv6_ops); | ||
33 | 35 | ||
34 | int nf_register_afinfo(const struct nf_afinfo *afinfo) | 36 | int nf_register_afinfo(const struct nf_afinfo *afinfo) |
35 | { | 37 | { |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 085b5880ab0d..05565d2b3a61 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1001,6 +1001,32 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) | |||
1001 | return th->rst; | 1001 | return th->rst; |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | static inline bool is_new_conn(const struct sk_buff *skb, | ||
1005 | struct ip_vs_iphdr *iph) | ||
1006 | { | ||
1007 | switch (iph->protocol) { | ||
1008 | case IPPROTO_TCP: { | ||
1009 | struct tcphdr _tcph, *th; | ||
1010 | |||
1011 | th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); | ||
1012 | if (th == NULL) | ||
1013 | return false; | ||
1014 | return th->syn; | ||
1015 | } | ||
1016 | case IPPROTO_SCTP: { | ||
1017 | sctp_chunkhdr_t *sch, schunk; | ||
1018 | |||
1019 | sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t), | ||
1020 | sizeof(schunk), &schunk); | ||
1021 | if (sch == NULL) | ||
1022 | return false; | ||
1023 | return sch->type == SCTP_CID_INIT; | ||
1024 | } | ||
1025 | default: | ||
1026 | return false; | ||
1027 | } | ||
1028 | } | ||
1029 | |||
1004 | /* Handle response packets: rewrite addresses and send away... | 1030 | /* Handle response packets: rewrite addresses and send away... |
1005 | */ | 1031 | */ |
1006 | static unsigned int | 1032 | static unsigned int |
@@ -1612,6 +1638,15 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1612 | * Check if the packet belongs to an existing connection entry | 1638 | * Check if the packet belongs to an existing connection entry |
1613 | */ | 1639 | */ |
1614 | cp = pp->conn_in_get(af, skb, &iph, 0); | 1640 | cp = pp->conn_in_get(af, skb, &iph, 0); |
1641 | |||
1642 | if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp && cp->dest && | ||
1643 | unlikely(!atomic_read(&cp->dest->weight)) && !iph.fragoffs && | ||
1644 | is_new_conn(skb, &iph)) { | ||
1645 | ip_vs_conn_expire_now(cp); | ||
1646 | __ip_vs_conn_put(cp); | ||
1647 | cp = NULL; | ||
1648 | } | ||
1649 | |||
1615 | if (unlikely(!cp) && !iph.fragoffs) { | 1650 | if (unlikely(!cp) && !iph.fragoffs) { |
1616 | /* No (second) fragments need to enter here, as nf_defrag_ipv6 | 1651 | /* No (second) fragments need to enter here, as nf_defrag_ipv6 |
1617 | * replayed fragment zero will already have created the cp | 1652 | * replayed fragment zero will already have created the cp |
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index 0df269d7c99f..a65edfe4b16c 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c | |||
@@ -67,8 +67,8 @@ struct ip_vs_sh_bucket { | |||
67 | #define IP_VS_SH_TAB_MASK (IP_VS_SH_TAB_SIZE - 1) | 67 | #define IP_VS_SH_TAB_MASK (IP_VS_SH_TAB_SIZE - 1) |
68 | 68 | ||
69 | struct ip_vs_sh_state { | 69 | struct ip_vs_sh_state { |
70 | struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE]; | ||
71 | struct rcu_head rcu_head; | 70 | struct rcu_head rcu_head; |
71 | struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE]; | ||
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* | 74 | /* |
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index 491c7d821a0b..5ab24843370a 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -737,7 +737,7 @@ static void dump_ipv6_packet(struct sbuff *m, | |||
737 | dump_sk_uid_gid(m, skb->sk); | 737 | dump_sk_uid_gid(m, skb->sk); |
738 | 738 | ||
739 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | 739 | /* Max length: 16 "MARK=0xFFFFFFFF " */ |
740 | if (!recurse && skb->mark) | 740 | if (recurse && skb->mark) |
741 | sb_add(m, "MARK=0x%x ", skb->mark); | 741 | sb_add(m, "MARK=0x%x ", skb->mark); |
742 | } | 742 | } |
743 | 743 | ||
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c index 49c5ff7f6dd6..68ff29f60867 100644 --- a/net/netfilter/xt_addrtype.c +++ b/net/netfilter/xt_addrtype.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <net/ip6_fib.h> | 22 | #include <net/ip6_fib.h> |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | #include <linux/netfilter_ipv6.h> | ||
25 | #include <linux/netfilter/xt_addrtype.h> | 26 | #include <linux/netfilter/xt_addrtype.h> |
26 | #include <linux/netfilter/x_tables.h> | 27 | #include <linux/netfilter/x_tables.h> |
27 | 28 | ||
@@ -33,12 +34,12 @@ MODULE_ALIAS("ip6t_addrtype"); | |||
33 | 34 | ||
34 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | 35 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
35 | static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, | 36 | static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, |
36 | const struct in6_addr *addr) | 37 | const struct in6_addr *addr, u16 mask) |
37 | { | 38 | { |
38 | const struct nf_afinfo *afinfo; | 39 | const struct nf_afinfo *afinfo; |
39 | struct flowi6 flow; | 40 | struct flowi6 flow; |
40 | struct rt6_info *rt; | 41 | struct rt6_info *rt; |
41 | u32 ret; | 42 | u32 ret = 0; |
42 | int route_err; | 43 | int route_err; |
43 | 44 | ||
44 | memset(&flow, 0, sizeof(flow)); | 45 | memset(&flow, 0, sizeof(flow)); |
@@ -49,12 +50,19 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, | |||
49 | rcu_read_lock(); | 50 | rcu_read_lock(); |
50 | 51 | ||
51 | afinfo = nf_get_afinfo(NFPROTO_IPV6); | 52 | afinfo = nf_get_afinfo(NFPROTO_IPV6); |
52 | if (afinfo != NULL) | 53 | if (afinfo != NULL) { |
54 | const struct nf_ipv6_ops *v6ops; | ||
55 | |||
56 | if (dev && (mask & XT_ADDRTYPE_LOCAL)) { | ||
57 | v6ops = nf_get_ipv6_ops(); | ||
58 | if (v6ops && v6ops->chk_addr(net, addr, dev, true)) | ||
59 | ret = XT_ADDRTYPE_LOCAL; | ||
60 | } | ||
53 | route_err = afinfo->route(net, (struct dst_entry **)&rt, | 61 | route_err = afinfo->route(net, (struct dst_entry **)&rt, |
54 | flowi6_to_flowi(&flow), !!dev); | 62 | flowi6_to_flowi(&flow), false); |
55 | else | 63 | } else { |
56 | route_err = 1; | 64 | route_err = 1; |
57 | 65 | } | |
58 | rcu_read_unlock(); | 66 | rcu_read_unlock(); |
59 | 67 | ||
60 | if (route_err) | 68 | if (route_err) |
@@ -62,15 +70,12 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, | |||
62 | 70 | ||
63 | if (rt->rt6i_flags & RTF_REJECT) | 71 | if (rt->rt6i_flags & RTF_REJECT) |
64 | ret = XT_ADDRTYPE_UNREACHABLE; | 72 | ret = XT_ADDRTYPE_UNREACHABLE; |
65 | else | ||
66 | ret = 0; | ||
67 | 73 | ||
68 | if (rt->rt6i_flags & RTF_LOCAL) | 74 | if (dev == NULL && rt->rt6i_flags & RTF_LOCAL) |
69 | ret |= XT_ADDRTYPE_LOCAL; | 75 | ret |= XT_ADDRTYPE_LOCAL; |
70 | if (rt->rt6i_flags & RTF_ANYCAST) | 76 | if (rt->rt6i_flags & RTF_ANYCAST) |
71 | ret |= XT_ADDRTYPE_ANYCAST; | 77 | ret |= XT_ADDRTYPE_ANYCAST; |
72 | 78 | ||
73 | |||
74 | dst_release(&rt->dst); | 79 | dst_release(&rt->dst); |
75 | return ret; | 80 | return ret; |
76 | } | 81 | } |
@@ -90,7 +95,7 @@ static bool match_type6(struct net *net, const struct net_device *dev, | |||
90 | 95 | ||
91 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | | 96 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | |
92 | XT_ADDRTYPE_UNREACHABLE) & mask) | 97 | XT_ADDRTYPE_UNREACHABLE) & mask) |
93 | return !!(mask & match_lookup_rt6(net, dev, addr)); | 98 | return !!(mask & match_lookup_rt6(net, dev, addr, mask)); |
94 | return true; | 99 | return true; |
95 | } | 100 | } |
96 | 101 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 12ac6b47a35c..d0b3dd60d386 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -747,7 +747,7 @@ static void netlink_skb_destructor(struct sk_buff *skb) | |||
747 | atomic_dec(&ring->pending); | 747 | atomic_dec(&ring->pending); |
748 | sock_put(sk); | 748 | sock_put(sk); |
749 | 749 | ||
750 | skb->data = NULL; | 750 | skb->head = NULL; |
751 | } | 751 | } |
752 | #endif | 752 | #endif |
753 | if (skb->sk != NULL) | 753 | if (skb->sk != NULL) |
diff --git a/net/nfc/Makefile b/net/nfc/Makefile index fb799deaed4f..a76f4533cb6c 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile | |||
@@ -5,7 +5,6 @@ | |||
5 | obj-$(CONFIG_NFC) += nfc.o | 5 | obj-$(CONFIG_NFC) += nfc.o |
6 | obj-$(CONFIG_NFC_NCI) += nci/ | 6 | obj-$(CONFIG_NFC_NCI) += nci/ |
7 | obj-$(CONFIG_NFC_HCI) += hci/ | 7 | obj-$(CONFIG_NFC_HCI) += hci/ |
8 | #obj-$(CONFIG_NFC_LLCP) += llcp/ | ||
9 | 8 | ||
10 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ | 9 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ |
11 | llcp_sock.o | 10 | llcp_sock.o |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 823463adbd21..189e3c5b3d09 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -231,14 +231,14 @@ override: | |||
231 | } | 231 | } |
232 | if (R_tab) { | 232 | if (R_tab) { |
233 | police->rate_present = true; | 233 | police->rate_present = true; |
234 | psched_ratecfg_precompute(&police->rate, R_tab->rate.rate); | 234 | psched_ratecfg_precompute(&police->rate, &R_tab->rate); |
235 | qdisc_put_rtab(R_tab); | 235 | qdisc_put_rtab(R_tab); |
236 | } else { | 236 | } else { |
237 | police->rate_present = false; | 237 | police->rate_present = false; |
238 | } | 238 | } |
239 | if (P_tab) { | 239 | if (P_tab) { |
240 | police->peak_present = true; | 240 | police->peak_present = true; |
241 | psched_ratecfg_precompute(&police->peak, P_tab->rate.rate); | 241 | psched_ratecfg_precompute(&police->peak, &P_tab->rate); |
242 | qdisc_put_rtab(P_tab); | 242 | qdisc_put_rtab(P_tab); |
243 | } else { | 243 | } else { |
244 | police->peak_present = false; | 244 | police->peak_present = false; |
@@ -376,9 +376,9 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
376 | }; | 376 | }; |
377 | 377 | ||
378 | if (police->rate_present) | 378 | if (police->rate_present) |
379 | opt.rate.rate = psched_ratecfg_getrate(&police->rate); | 379 | psched_ratecfg_getrate(&opt.rate, &police->rate); |
380 | if (police->peak_present) | 380 | if (police->peak_present) |
381 | opt.peakrate.rate = psched_ratecfg_getrate(&police->peak); | 381 | psched_ratecfg_getrate(&opt.peakrate, &police->peak); |
382 | if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) | 382 | if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) |
383 | goto nla_put_failure; | 383 | goto nla_put_failure; |
384 | if (police->tcfp_result && | 384 | if (police->tcfp_result && |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index eac7e0ee23c1..20224086cc28 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -898,14 +898,16 @@ void dev_shutdown(struct net_device *dev) | |||
898 | WARN_ON(timer_pending(&dev->watchdog_timer)); | 898 | WARN_ON(timer_pending(&dev->watchdog_timer)); |
899 | } | 899 | } |
900 | 900 | ||
901 | void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate) | 901 | void psched_ratecfg_precompute(struct psched_ratecfg *r, |
902 | const struct tc_ratespec *conf) | ||
902 | { | 903 | { |
903 | u64 factor; | 904 | u64 factor; |
904 | u64 mult; | 905 | u64 mult; |
905 | int shift; | 906 | int shift; |
906 | 907 | ||
907 | r->rate_bps = (u64)rate << 3; | 908 | memset(r, 0, sizeof(*r)); |
908 | r->shift = 0; | 909 | r->overhead = conf->overhead; |
910 | r->rate_bps = (u64)conf->rate << 3; | ||
909 | r->mult = 1; | 911 | r->mult = 1; |
910 | /* | 912 | /* |
911 | * Calibrate mult, shift so that token counting is accurate | 913 | * Calibrate mult, shift so that token counting is accurate |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 79b1876b6cd2..adaedd79389c 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -109,7 +109,7 @@ struct htb_class { | |||
109 | } un; | 109 | } un; |
110 | struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ | 110 | struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ |
111 | struct rb_node pq_node; /* node for event queue */ | 111 | struct rb_node pq_node; /* node for event queue */ |
112 | psched_time_t pq_key; | 112 | s64 pq_key; |
113 | 113 | ||
114 | int prio_activity; /* for which prios are we active */ | 114 | int prio_activity; /* for which prios are we active */ |
115 | enum htb_cmode cmode; /* current mode of the class */ | 115 | enum htb_cmode cmode; /* current mode of the class */ |
@@ -121,10 +121,10 @@ struct htb_class { | |||
121 | /* token bucket parameters */ | 121 | /* token bucket parameters */ |
122 | struct psched_ratecfg rate; | 122 | struct psched_ratecfg rate; |
123 | struct psched_ratecfg ceil; | 123 | struct psched_ratecfg ceil; |
124 | s64 buffer, cbuffer; /* token bucket depth/rate */ | 124 | s64 buffer, cbuffer; /* token bucket depth/rate */ |
125 | psched_tdiff_t mbuffer; /* max wait time */ | 125 | s64 mbuffer; /* max wait time */ |
126 | s64 tokens, ctokens; /* current number of tokens */ | 126 | s64 tokens, ctokens; /* current number of tokens */ |
127 | psched_time_t t_c; /* checkpoint time */ | 127 | s64 t_c; /* checkpoint time */ |
128 | }; | 128 | }; |
129 | 129 | ||
130 | struct htb_sched { | 130 | struct htb_sched { |
@@ -141,15 +141,15 @@ struct htb_sched { | |||
141 | struct rb_root wait_pq[TC_HTB_MAXDEPTH]; | 141 | struct rb_root wait_pq[TC_HTB_MAXDEPTH]; |
142 | 142 | ||
143 | /* time of nearest event per level (row) */ | 143 | /* time of nearest event per level (row) */ |
144 | psched_time_t near_ev_cache[TC_HTB_MAXDEPTH]; | 144 | s64 near_ev_cache[TC_HTB_MAXDEPTH]; |
145 | 145 | ||
146 | int defcls; /* class where unclassified flows go to */ | 146 | int defcls; /* class where unclassified flows go to */ |
147 | 147 | ||
148 | /* filters for qdisc itself */ | 148 | /* filters for qdisc itself */ |
149 | struct tcf_proto *filter_list; | 149 | struct tcf_proto *filter_list; |
150 | 150 | ||
151 | int rate2quantum; /* quant = rate / rate2quantum */ | 151 | int rate2quantum; /* quant = rate / rate2quantum */ |
152 | psched_time_t now; /* cached dequeue time */ | 152 | s64 now; /* cached dequeue time */ |
153 | struct qdisc_watchdog watchdog; | 153 | struct qdisc_watchdog watchdog; |
154 | 154 | ||
155 | /* non shaped skbs; let them go directly thru */ | 155 | /* non shaped skbs; let them go directly thru */ |
@@ -664,8 +664,8 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | |||
664 | * next pending event (0 for no event in pq, q->now for too many events). | 664 | * next pending event (0 for no event in pq, q->now for too many events). |
665 | * Note: Applied are events whose have cl->pq_key <= q->now. | 665 | * Note: Applied are events whose have cl->pq_key <= q->now. |
666 | */ | 666 | */ |
667 | static psched_time_t htb_do_events(struct htb_sched *q, int level, | 667 | static s64 htb_do_events(struct htb_sched *q, int level, |
668 | unsigned long start) | 668 | unsigned long start) |
669 | { | 669 | { |
670 | /* don't run for longer than 2 jiffies; 2 is used instead of | 670 | /* don't run for longer than 2 jiffies; 2 is used instead of |
671 | * 1 to simplify things when jiffy is going to be incremented | 671 | * 1 to simplify things when jiffy is going to be incremented |
@@ -857,7 +857,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) | |||
857 | struct sk_buff *skb; | 857 | struct sk_buff *skb; |
858 | struct htb_sched *q = qdisc_priv(sch); | 858 | struct htb_sched *q = qdisc_priv(sch); |
859 | int level; | 859 | int level; |
860 | psched_time_t next_event; | 860 | s64 next_event; |
861 | unsigned long start_at; | 861 | unsigned long start_at; |
862 | 862 | ||
863 | /* try to dequeue direct packets as high prio (!) to minimize cpu work */ | 863 | /* try to dequeue direct packets as high prio (!) to minimize cpu work */ |
@@ -880,7 +880,7 @@ ok: | |||
880 | for (level = 0; level < TC_HTB_MAXDEPTH; level++) { | 880 | for (level = 0; level < TC_HTB_MAXDEPTH; level++) { |
881 | /* common case optimization - skip event handler quickly */ | 881 | /* common case optimization - skip event handler quickly */ |
882 | int m; | 882 | int m; |
883 | psched_time_t event; | 883 | s64 event; |
884 | 884 | ||
885 | if (q->now >= q->near_ev_cache[level]) { | 885 | if (q->now >= q->near_ev_cache[level]) { |
886 | event = htb_do_events(q, level, start_at); | 886 | event = htb_do_events(q, level, start_at); |
@@ -1090,9 +1090,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1090 | 1090 | ||
1091 | memset(&opt, 0, sizeof(opt)); | 1091 | memset(&opt, 0, sizeof(opt)); |
1092 | 1092 | ||
1093 | opt.rate.rate = psched_ratecfg_getrate(&cl->rate); | 1093 | psched_ratecfg_getrate(&opt.rate, &cl->rate); |
1094 | opt.buffer = PSCHED_NS2TICKS(cl->buffer); | 1094 | opt.buffer = PSCHED_NS2TICKS(cl->buffer); |
1095 | opt.ceil.rate = psched_ratecfg_getrate(&cl->ceil); | 1095 | psched_ratecfg_getrate(&opt.ceil, &cl->ceil); |
1096 | opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer); | 1096 | opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer); |
1097 | opt.quantum = cl->quantum; | 1097 | opt.quantum = cl->quantum; |
1098 | opt.prio = cl->prio; | 1098 | opt.prio = cl->prio; |
@@ -1117,8 +1117,8 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d) | |||
1117 | 1117 | ||
1118 | if (!cl->level && cl->un.leaf.q) | 1118 | if (!cl->level && cl->un.leaf.q) |
1119 | cl->qstats.qlen = cl->un.leaf.q->q.qlen; | 1119 | cl->qstats.qlen = cl->un.leaf.q->q.qlen; |
1120 | cl->xstats.tokens = cl->tokens; | 1120 | cl->xstats.tokens = PSCHED_NS2TICKS(cl->tokens); |
1121 | cl->xstats.ctokens = cl->ctokens; | 1121 | cl->xstats.ctokens = PSCHED_NS2TICKS(cl->ctokens); |
1122 | 1122 | ||
1123 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || | 1123 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || |
1124 | gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 || | 1124 | gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 || |
@@ -1200,7 +1200,7 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl, | |||
1200 | parent->un.leaf.q = new_q ? new_q : &noop_qdisc; | 1200 | parent->un.leaf.q = new_q ? new_q : &noop_qdisc; |
1201 | parent->tokens = parent->buffer; | 1201 | parent->tokens = parent->buffer; |
1202 | parent->ctokens = parent->cbuffer; | 1202 | parent->ctokens = parent->cbuffer; |
1203 | parent->t_c = psched_get_time(); | 1203 | parent->t_c = ktime_to_ns(ktime_get()); |
1204 | parent->cmode = HTB_CAN_SEND; | 1204 | parent->cmode = HTB_CAN_SEND; |
1205 | } | 1205 | } |
1206 | 1206 | ||
@@ -1417,8 +1417,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1417 | /* set class to be in HTB_CAN_SEND state */ | 1417 | /* set class to be in HTB_CAN_SEND state */ |
1418 | cl->tokens = PSCHED_TICKS2NS(hopt->buffer); | 1418 | cl->tokens = PSCHED_TICKS2NS(hopt->buffer); |
1419 | cl->ctokens = PSCHED_TICKS2NS(hopt->cbuffer); | 1419 | cl->ctokens = PSCHED_TICKS2NS(hopt->cbuffer); |
1420 | cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */ | 1420 | cl->mbuffer = 60ULL * NSEC_PER_SEC; /* 1min */ |
1421 | cl->t_c = psched_get_time(); | 1421 | cl->t_c = ktime_to_ns(ktime_get()); |
1422 | cl->cmode = HTB_CAN_SEND; | 1422 | cl->cmode = HTB_CAN_SEND; |
1423 | 1423 | ||
1424 | /* attach to the hash list and parent's family */ | 1424 | /* attach to the hash list and parent's family */ |
@@ -1459,8 +1459,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1459 | cl->prio = TC_HTB_NUMPRIO - 1; | 1459 | cl->prio = TC_HTB_NUMPRIO - 1; |
1460 | } | 1460 | } |
1461 | 1461 | ||
1462 | psched_ratecfg_precompute(&cl->rate, hopt->rate.rate); | 1462 | psched_ratecfg_precompute(&cl->rate, &hopt->rate); |
1463 | psched_ratecfg_precompute(&cl->ceil, hopt->ceil.rate); | 1463 | psched_ratecfg_precompute(&cl->ceil, &hopt->ceil); |
1464 | 1464 | ||
1465 | cl->buffer = PSCHED_TICKS2NS(hopt->buffer); | 1465 | cl->buffer = PSCHED_TICKS2NS(hopt->buffer); |
1466 | cl->cbuffer = PSCHED_TICKS2NS(hopt->buffer); | 1466 | cl->cbuffer = PSCHED_TICKS2NS(hopt->buffer); |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 38008b0980d9..1aaf1b6e51a2 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -341,9 +341,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
341 | q->tokens = q->buffer; | 341 | q->tokens = q->buffer; |
342 | q->ptokens = q->mtu; | 342 | q->ptokens = q->mtu; |
343 | 343 | ||
344 | psched_ratecfg_precompute(&q->rate, rtab->rate.rate); | 344 | psched_ratecfg_precompute(&q->rate, &rtab->rate); |
345 | if (ptab) { | 345 | if (ptab) { |
346 | psched_ratecfg_precompute(&q->peak, ptab->rate.rate); | 346 | psched_ratecfg_precompute(&q->peak, &ptab->rate); |
347 | q->peak_present = true; | 347 | q->peak_present = true; |
348 | } else { | 348 | } else { |
349 | q->peak_present = false; | 349 | q->peak_present = false; |
@@ -393,9 +393,9 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
393 | goto nla_put_failure; | 393 | goto nla_put_failure; |
394 | 394 | ||
395 | opt.limit = q->limit; | 395 | opt.limit = q->limit; |
396 | opt.rate.rate = psched_ratecfg_getrate(&q->rate); | 396 | psched_ratecfg_getrate(&opt.rate, &q->rate); |
397 | if (q->peak_present) | 397 | if (q->peak_present) |
398 | opt.peakrate.rate = psched_ratecfg_getrate(&q->peak); | 398 | psched_ratecfg_getrate(&opt.peakrate, &q->peak); |
399 | else | 399 | else |
400 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | 400 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); |
401 | opt.mtu = PSCHED_NS2TICKS(q->mtu); | 401 | opt.mtu = PSCHED_NS2TICKS(q->mtu); |
diff --git a/net/socket.c b/net/socket.c index 6b94633ca61d..9ff6366fee13 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2075,8 +2075,12 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, fla | |||
2075 | { | 2075 | { |
2076 | int fput_needed, err; | 2076 | int fput_needed, err; |
2077 | struct msghdr msg_sys; | 2077 | struct msghdr msg_sys; |
2078 | struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); | 2078 | struct socket *sock; |
2079 | |||
2080 | if (flags & MSG_CMSG_COMPAT) | ||
2081 | return -EINVAL; | ||
2079 | 2082 | ||
2083 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
2080 | if (!sock) | 2084 | if (!sock) |
2081 | goto out; | 2085 | goto out; |
2082 | 2086 | ||
@@ -2149,6 +2153,8 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2149 | SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, | 2153 | SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, |
2150 | unsigned int, vlen, unsigned int, flags) | 2154 | unsigned int, vlen, unsigned int, flags) |
2151 | { | 2155 | { |
2156 | if (flags & MSG_CMSG_COMPAT) | ||
2157 | return -EINVAL; | ||
2152 | return __sys_sendmmsg(fd, mmsg, vlen, flags); | 2158 | return __sys_sendmmsg(fd, mmsg, vlen, flags); |
2153 | } | 2159 | } |
2154 | 2160 | ||
@@ -2249,8 +2255,12 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, | |||
2249 | { | 2255 | { |
2250 | int fput_needed, err; | 2256 | int fput_needed, err; |
2251 | struct msghdr msg_sys; | 2257 | struct msghdr msg_sys; |
2252 | struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); | 2258 | struct socket *sock; |
2259 | |||
2260 | if (flags & MSG_CMSG_COMPAT) | ||
2261 | return -EINVAL; | ||
2253 | 2262 | ||
2263 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
2254 | if (!sock) | 2264 | if (!sock) |
2255 | goto out; | 2265 | goto out; |
2256 | 2266 | ||
@@ -2375,6 +2385,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, | |||
2375 | int datagrams; | 2385 | int datagrams; |
2376 | struct timespec timeout_sys; | 2386 | struct timespec timeout_sys; |
2377 | 2387 | ||
2388 | if (flags & MSG_CMSG_COMPAT) | ||
2389 | return -EINVAL; | ||
2390 | |||
2378 | if (!timeout) | 2391 | if (!timeout) |
2379 | return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); | 2392 | return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); |
2380 | 2393 | ||
@@ -2492,15 +2505,31 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
2492 | (int __user *)a[4]); | 2505 | (int __user *)a[4]); |
2493 | break; | 2506 | break; |
2494 | case SYS_SENDMSG: | 2507 | case SYS_SENDMSG: |
2508 | if (a[2] & MSG_CMSG_COMPAT) { | ||
2509 | err = -EINVAL; | ||
2510 | break; | ||
2511 | } | ||
2495 | err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); | 2512 | err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); |
2496 | break; | 2513 | break; |
2497 | case SYS_SENDMMSG: | 2514 | case SYS_SENDMMSG: |
2515 | if (a[3] & MSG_CMSG_COMPAT) { | ||
2516 | err = -EINVAL; | ||
2517 | break; | ||
2518 | } | ||
2498 | err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); | 2519 | err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); |
2499 | break; | 2520 | break; |
2500 | case SYS_RECVMSG: | 2521 | case SYS_RECVMSG: |
2522 | if (a[2] & MSG_CMSG_COMPAT) { | ||
2523 | err = -EINVAL; | ||
2524 | break; | ||
2525 | } | ||
2501 | err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); | 2526 | err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); |
2502 | break; | 2527 | break; |
2503 | case SYS_RECVMMSG: | 2528 | case SYS_RECVMMSG: |
2529 | if (a[3] & MSG_CMSG_COMPAT) { | ||
2530 | err = -EINVAL; | ||
2531 | break; | ||
2532 | } | ||
2504 | err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], | 2533 | err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], |
2505 | (struct timespec __user *)a[4]); | 2534 | (struct timespec __user *)a[4]); |
2506 | break; | 2535 | break; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 7da6b457f66a..fc2f78d6a9b4 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -52,6 +52,8 @@ | |||
52 | #include <linux/sunrpc/gss_api.h> | 52 | #include <linux/sunrpc/gss_api.h> |
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | 54 | ||
55 | #include "../netns.h" | ||
56 | |||
55 | static const struct rpc_authops authgss_ops; | 57 | static const struct rpc_authops authgss_ops; |
56 | 58 | ||
57 | static const struct rpc_credops gss_credops; | 59 | static const struct rpc_credops gss_credops; |
@@ -85,8 +87,6 @@ struct gss_auth { | |||
85 | }; | 87 | }; |
86 | 88 | ||
87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 89 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
88 | static int pipe_version = -1; | ||
89 | static atomic_t pipe_users = ATOMIC_INIT(0); | ||
90 | static DEFINE_SPINLOCK(pipe_version_lock); | 90 | static DEFINE_SPINLOCK(pipe_version_lock); |
91 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; | 91 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; |
92 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); | 92 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); |
@@ -266,24 +266,27 @@ struct gss_upcall_msg { | |||
266 | char databuf[UPCALL_BUF_LEN]; | 266 | char databuf[UPCALL_BUF_LEN]; |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static int get_pipe_version(void) | 269 | static int get_pipe_version(struct net *net) |
270 | { | 270 | { |
271 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
271 | int ret; | 272 | int ret; |
272 | 273 | ||
273 | spin_lock(&pipe_version_lock); | 274 | spin_lock(&pipe_version_lock); |
274 | if (pipe_version >= 0) { | 275 | if (sn->pipe_version >= 0) { |
275 | atomic_inc(&pipe_users); | 276 | atomic_inc(&sn->pipe_users); |
276 | ret = pipe_version; | 277 | ret = sn->pipe_version; |
277 | } else | 278 | } else |
278 | ret = -EAGAIN; | 279 | ret = -EAGAIN; |
279 | spin_unlock(&pipe_version_lock); | 280 | spin_unlock(&pipe_version_lock); |
280 | return ret; | 281 | return ret; |
281 | } | 282 | } |
282 | 283 | ||
283 | static void put_pipe_version(void) | 284 | static void put_pipe_version(struct net *net) |
284 | { | 285 | { |
285 | if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) { | 286 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
286 | pipe_version = -1; | 287 | |
288 | if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) { | ||
289 | sn->pipe_version = -1; | ||
287 | spin_unlock(&pipe_version_lock); | 290 | spin_unlock(&pipe_version_lock); |
288 | } | 291 | } |
289 | } | 292 | } |
@@ -291,9 +294,10 @@ static void put_pipe_version(void) | |||
291 | static void | 294 | static void |
292 | gss_release_msg(struct gss_upcall_msg *gss_msg) | 295 | gss_release_msg(struct gss_upcall_msg *gss_msg) |
293 | { | 296 | { |
297 | struct net *net = rpc_net_ns(gss_msg->auth->client); | ||
294 | if (!atomic_dec_and_test(&gss_msg->count)) | 298 | if (!atomic_dec_and_test(&gss_msg->count)) |
295 | return; | 299 | return; |
296 | put_pipe_version(); | 300 | put_pipe_version(net); |
297 | BUG_ON(!list_empty(&gss_msg->list)); | 301 | BUG_ON(!list_empty(&gss_msg->list)); |
298 | if (gss_msg->ctx != NULL) | 302 | if (gss_msg->ctx != NULL) |
299 | gss_put_ctx(gss_msg->ctx); | 303 | gss_put_ctx(gss_msg->ctx); |
@@ -439,7 +443,10 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg, | |||
439 | struct rpc_clnt *clnt, | 443 | struct rpc_clnt *clnt, |
440 | const char *service_name) | 444 | const char *service_name) |
441 | { | 445 | { |
442 | if (pipe_version == 0) | 446 | struct net *net = rpc_net_ns(clnt); |
447 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
448 | |||
449 | if (sn->pipe_version == 0) | ||
443 | gss_encode_v0_msg(gss_msg); | 450 | gss_encode_v0_msg(gss_msg); |
444 | else /* pipe_version == 1 */ | 451 | else /* pipe_version == 1 */ |
445 | gss_encode_v1_msg(gss_msg, clnt, service_name); | 452 | gss_encode_v1_msg(gss_msg, clnt, service_name); |
@@ -455,7 +462,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
455 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); | 462 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
456 | if (gss_msg == NULL) | 463 | if (gss_msg == NULL) |
457 | return ERR_PTR(-ENOMEM); | 464 | return ERR_PTR(-ENOMEM); |
458 | vers = get_pipe_version(); | 465 | vers = get_pipe_version(rpc_net_ns(clnt)); |
459 | if (vers < 0) { | 466 | if (vers < 0) { |
460 | kfree(gss_msg); | 467 | kfree(gss_msg); |
461 | return ERR_PTR(vers); | 468 | return ERR_PTR(vers); |
@@ -559,24 +566,34 @@ out: | |||
559 | static inline int | 566 | static inline int |
560 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 567 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
561 | { | 568 | { |
569 | struct net *net = rpc_net_ns(gss_auth->client); | ||
570 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
562 | struct rpc_pipe *pipe; | 571 | struct rpc_pipe *pipe; |
563 | struct rpc_cred *cred = &gss_cred->gc_base; | 572 | struct rpc_cred *cred = &gss_cred->gc_base; |
564 | struct gss_upcall_msg *gss_msg; | 573 | struct gss_upcall_msg *gss_msg; |
574 | unsigned long timeout; | ||
565 | DEFINE_WAIT(wait); | 575 | DEFINE_WAIT(wait); |
566 | int err = 0; | 576 | int err; |
567 | 577 | ||
568 | dprintk("RPC: %s for uid %u\n", | 578 | dprintk("RPC: %s for uid %u\n", |
569 | __func__, from_kuid(&init_user_ns, cred->cr_uid)); | 579 | __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
570 | retry: | 580 | retry: |
581 | err = 0; | ||
582 | /* Default timeout is 15s unless we know that gssd is not running */ | ||
583 | timeout = 15 * HZ; | ||
584 | if (!sn->gssd_running) | ||
585 | timeout = HZ >> 2; | ||
571 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 586 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); |
572 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 587 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
573 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, | 588 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
574 | pipe_version >= 0, 15*HZ); | 589 | sn->pipe_version >= 0, timeout); |
575 | if (pipe_version < 0) { | 590 | if (sn->pipe_version < 0) { |
591 | if (err == 0) | ||
592 | sn->gssd_running = 0; | ||
576 | warn_gssd(); | 593 | warn_gssd(); |
577 | err = -EACCES; | 594 | err = -EACCES; |
578 | } | 595 | } |
579 | if (err) | 596 | if (err < 0) |
580 | goto out; | 597 | goto out; |
581 | goto retry; | 598 | goto retry; |
582 | } | 599 | } |
@@ -707,20 +724,22 @@ out: | |||
707 | 724 | ||
708 | static int gss_pipe_open(struct inode *inode, int new_version) | 725 | static int gss_pipe_open(struct inode *inode, int new_version) |
709 | { | 726 | { |
727 | struct net *net = inode->i_sb->s_fs_info; | ||
728 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
710 | int ret = 0; | 729 | int ret = 0; |
711 | 730 | ||
712 | spin_lock(&pipe_version_lock); | 731 | spin_lock(&pipe_version_lock); |
713 | if (pipe_version < 0) { | 732 | if (sn->pipe_version < 0) { |
714 | /* First open of any gss pipe determines the version: */ | 733 | /* First open of any gss pipe determines the version: */ |
715 | pipe_version = new_version; | 734 | sn->pipe_version = new_version; |
716 | rpc_wake_up(&pipe_version_rpc_waitqueue); | 735 | rpc_wake_up(&pipe_version_rpc_waitqueue); |
717 | wake_up(&pipe_version_waitqueue); | 736 | wake_up(&pipe_version_waitqueue); |
718 | } else if (pipe_version != new_version) { | 737 | } else if (sn->pipe_version != new_version) { |
719 | /* Trying to open a pipe of a different version */ | 738 | /* Trying to open a pipe of a different version */ |
720 | ret = -EBUSY; | 739 | ret = -EBUSY; |
721 | goto out; | 740 | goto out; |
722 | } | 741 | } |
723 | atomic_inc(&pipe_users); | 742 | atomic_inc(&sn->pipe_users); |
724 | out: | 743 | out: |
725 | spin_unlock(&pipe_version_lock); | 744 | spin_unlock(&pipe_version_lock); |
726 | return ret; | 745 | return ret; |
@@ -740,6 +759,7 @@ static int gss_pipe_open_v1(struct inode *inode) | |||
740 | static void | 759 | static void |
741 | gss_pipe_release(struct inode *inode) | 760 | gss_pipe_release(struct inode *inode) |
742 | { | 761 | { |
762 | struct net *net = inode->i_sb->s_fs_info; | ||
743 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; | 763 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
744 | struct gss_upcall_msg *gss_msg; | 764 | struct gss_upcall_msg *gss_msg; |
745 | 765 | ||
@@ -758,7 +778,7 @@ restart: | |||
758 | } | 778 | } |
759 | spin_unlock(&pipe->lock); | 779 | spin_unlock(&pipe->lock); |
760 | 780 | ||
761 | put_pipe_version(); | 781 | put_pipe_version(net); |
762 | } | 782 | } |
763 | 783 | ||
764 | static void | 784 | static void |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 871c73c92165..29b4ba93ab3c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1287,7 +1287,7 @@ static bool use_gss_proxy(struct net *net) | |||
1287 | 1287 | ||
1288 | #ifdef CONFIG_PROC_FS | 1288 | #ifdef CONFIG_PROC_FS |
1289 | 1289 | ||
1290 | static bool set_gss_proxy(struct net *net, int type) | 1290 | static int set_gss_proxy(struct net *net, int type) |
1291 | { | 1291 | { |
1292 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1292 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1293 | int ret = 0; | 1293 | int ret = 0; |
@@ -1317,10 +1317,12 @@ static inline bool gssp_ready(struct sunrpc_net *sn) | |||
1317 | return false; | 1317 | return false; |
1318 | } | 1318 | } |
1319 | 1319 | ||
1320 | static int wait_for_gss_proxy(struct net *net) | 1320 | static int wait_for_gss_proxy(struct net *net, struct file *file) |
1321 | { | 1321 | { |
1322 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1322 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1323 | 1323 | ||
1324 | if (file->f_flags & O_NONBLOCK && !gssp_ready(sn)) | ||
1325 | return -EAGAIN; | ||
1324 | return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); | 1326 | return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); |
1325 | } | 1327 | } |
1326 | 1328 | ||
@@ -1362,7 +1364,7 @@ static ssize_t read_gssp(struct file *file, char __user *buf, | |||
1362 | size_t len; | 1364 | size_t len; |
1363 | int ret; | 1365 | int ret; |
1364 | 1366 | ||
1365 | ret = wait_for_gss_proxy(net); | 1367 | ret = wait_for_gss_proxy(net, file); |
1366 | if (ret) | 1368 | if (ret) |
1367 | return ret; | 1369 | return ret; |
1368 | 1370 | ||
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index 7111a4c9113b..74d948f5d5a1 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -28,7 +28,11 @@ struct sunrpc_net { | |||
28 | wait_queue_head_t gssp_wq; | 28 | wait_queue_head_t gssp_wq; |
29 | struct rpc_clnt *gssp_clnt; | 29 | struct rpc_clnt *gssp_clnt; |
30 | int use_gss_proxy; | 30 | int use_gss_proxy; |
31 | int pipe_version; | ||
32 | atomic_t pipe_users; | ||
31 | struct proc_dir_entry *use_gssp_proc; | 33 | struct proc_dir_entry *use_gssp_proc; |
34 | |||
35 | unsigned int gssd_running; | ||
32 | }; | 36 | }; |
33 | 37 | ||
34 | extern int sunrpc_net_id; | 38 | extern int sunrpc_net_id; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a9129f8d7070..e7ce4b3eb0bd 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -216,11 +216,14 @@ rpc_destroy_inode(struct inode *inode) | |||
216 | static int | 216 | static int |
217 | rpc_pipe_open(struct inode *inode, struct file *filp) | 217 | rpc_pipe_open(struct inode *inode, struct file *filp) |
218 | { | 218 | { |
219 | struct net *net = inode->i_sb->s_fs_info; | ||
220 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
219 | struct rpc_pipe *pipe; | 221 | struct rpc_pipe *pipe; |
220 | int first_open; | 222 | int first_open; |
221 | int res = -ENXIO; | 223 | int res = -ENXIO; |
222 | 224 | ||
223 | mutex_lock(&inode->i_mutex); | 225 | mutex_lock(&inode->i_mutex); |
226 | sn->gssd_running = 1; | ||
224 | pipe = RPC_I(inode)->pipe; | 227 | pipe = RPC_I(inode)->pipe; |
225 | if (pipe == NULL) | 228 | if (pipe == NULL) |
226 | goto out; | 229 | goto out; |
@@ -1069,6 +1072,8 @@ void rpc_pipefs_init_net(struct net *net) | |||
1069 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1072 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1070 | 1073 | ||
1071 | mutex_init(&sn->pipefs_sb_lock); | 1074 | mutex_init(&sn->pipefs_sb_lock); |
1075 | sn->gssd_running = 1; | ||
1076 | sn->pipe_version = -1; | ||
1072 | } | 1077 | } |
1073 | 1078 | ||
1074 | /* | 1079 | /* |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f8529fc8e542..5356b120dbf8 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -324,11 +324,17 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); | |||
324 | * Note: If the task is ASYNC, and is being made runnable after sitting on an | 324 | * Note: If the task is ASYNC, and is being made runnable after sitting on an |
325 | * rpc_wait_queue, this must be called with the queue spinlock held to protect | 325 | * rpc_wait_queue, this must be called with the queue spinlock held to protect |
326 | * the wait queue operation. | 326 | * the wait queue operation. |
327 | * Note the ordering of rpc_test_and_set_running() and rpc_clear_queued(), | ||
328 | * which is needed to ensure that __rpc_execute() doesn't loop (due to the | ||
329 | * lockless RPC_IS_QUEUED() test) before we've had a chance to test | ||
330 | * the RPC_TASK_RUNNING flag. | ||
327 | */ | 331 | */ |
328 | static void rpc_make_runnable(struct rpc_task *task) | 332 | static void rpc_make_runnable(struct rpc_task *task) |
329 | { | 333 | { |
334 | bool need_wakeup = !rpc_test_and_set_running(task); | ||
335 | |||
330 | rpc_clear_queued(task); | 336 | rpc_clear_queued(task); |
331 | if (rpc_test_and_set_running(task)) | 337 | if (!need_wakeup) |
332 | return; | 338 | return; |
333 | if (RPC_IS_ASYNC(task)) { | 339 | if (RPC_IS_ASYNC(task)) { |
334 | INIT_WORK(&task->u.tk_work, rpc_async_schedule); | 340 | INIT_WORK(&task->u.tk_work, rpc_async_schedule); |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index c3f9e1ef7f53..06bdf5a1082c 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -810,11 +810,15 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
810 | goto badcred; | 810 | goto badcred; |
811 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ | 811 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ |
812 | argv->iov_len -= slen*4; | 812 | argv->iov_len -= slen*4; |
813 | 813 | /* | |
814 | * Note: we skip uid_valid()/gid_valid() checks here for | ||
815 | * backwards compatibility with clients that use -1 id's. | ||
816 | * Instead, -1 uid or gid is later mapped to the | ||
817 | * (export-specific) anonymous id by nfsd_setuser. | ||
818 | * Supplementary gid's will be left alone. | ||
819 | */ | ||
814 | cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ | 820 | cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ |
815 | cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ | 821 | cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ |
816 | if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid)) | ||
817 | goto badcred; | ||
818 | slen = svc_getnl(argv); /* gids length */ | 822 | slen = svc_getnl(argv); /* gids length */ |
819 | if (slen > 16 || (len -= (slen + 2)*4) < 0) | 823 | if (slen > 16 || (len -= (slen + 2)*4) < 0) |
820 | goto badcred; | 824 | goto badcred; |
@@ -823,8 +827,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
823 | return SVC_CLOSE; | 827 | return SVC_CLOSE; |
824 | for (i = 0; i < slen; i++) { | 828 | for (i = 0; i < slen; i++) { |
825 | kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); | 829 | kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); |
826 | if (!gid_valid(kgid)) | ||
827 | goto badcred; | ||
828 | GROUP_AT(cred->cr_group_info, i) = kgid; | 830 | GROUP_AT(cred->cr_group_info, i) = kgid; |
829 | } | 831 | } |
830 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { | 832 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index dfdb5e643211..d5aed3bb3945 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3411,7 +3411,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
3411 | (u32)sinfo->rx_bytes)) | 3411 | (u32)sinfo->rx_bytes)) |
3412 | goto nla_put_failure; | 3412 | goto nla_put_failure; |
3413 | if ((sinfo->filled & (STATION_INFO_TX_BYTES | | 3413 | if ((sinfo->filled & (STATION_INFO_TX_BYTES | |
3414 | NL80211_STA_INFO_TX_BYTES64)) && | 3414 | STATION_INFO_TX_BYTES64)) && |
3415 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, | 3415 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, |
3416 | (u32)sinfo->tx_bytes)) | 3416 | (u32)sinfo->tx_bytes)) |
3417 | goto nla_put_failure; | 3417 | goto nla_put_failure; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 8b5eddfba1e5..3ed35c345cae 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -231,6 +231,9 @@ void cfg80211_conn_work(struct work_struct *work) | |||
231 | mutex_lock(&rdev->sched_scan_mtx); | 231 | mutex_lock(&rdev->sched_scan_mtx); |
232 | 232 | ||
233 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 233 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
234 | if (!wdev->netdev) | ||
235 | continue; | ||
236 | |||
234 | wdev_lock(wdev); | 237 | wdev_lock(wdev); |
235 | if (!netif_running(wdev->netdev)) { | 238 | if (!netif_running(wdev->netdev)) { |
236 | wdev_unlock(wdev); | 239 | wdev_unlock(wdev); |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 536ccc95de89..e52cab3591dd 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -2557,11 +2557,12 @@ static void __xfrm_garbage_collect(struct net *net) | |||
2557 | } | 2557 | } |
2558 | } | 2558 | } |
2559 | 2559 | ||
2560 | static void xfrm_garbage_collect(struct net *net) | 2560 | void xfrm_garbage_collect(struct net *net) |
2561 | { | 2561 | { |
2562 | flow_cache_flush(); | 2562 | flow_cache_flush(); |
2563 | __xfrm_garbage_collect(net); | 2563 | __xfrm_garbage_collect(net); |
2564 | } | 2564 | } |
2565 | EXPORT_SYMBOL(xfrm_garbage_collect); | ||
2565 | 2566 | ||
2566 | static void xfrm_garbage_collect_deferred(struct net *net) | 2567 | static void xfrm_garbage_collect_deferred(struct net *net) |
2567 | { | 2568 | { |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index aa778748c565..3f565e495ac6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1681,6 +1681,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1681 | 1681 | ||
1682 | out: | 1682 | out: |
1683 | xfrm_pol_put(xp); | 1683 | xfrm_pol_put(xp); |
1684 | if (delete && err == 0) | ||
1685 | xfrm_garbage_collect(net); | ||
1684 | return err; | 1686 | return err; |
1685 | } | 1687 | } |
1686 | 1688 | ||