diff options
Diffstat (limited to 'net')
91 files changed, 1219 insertions, 561 deletions
diff --git a/net/Kconfig b/net/Kconfig index 6272420a721b..99815b5454bf 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -6,7 +6,7 @@ menuconfig NET | |||
6 | bool "Networking support" | 6 | bool "Networking support" |
7 | select NLATTR | 7 | select NLATTR |
8 | select GENERIC_NET_UTILS | 8 | select GENERIC_NET_UTILS |
9 | select ANON_INODES | 9 | select BPF |
10 | ---help--- | 10 | ---help--- |
11 | Unless you really know what you are doing, you should say Y here. | 11 | Unless you really know what you are doing, you should say Y here. |
12 | The reason is that some programs need kernel networking support even | 12 | The reason is that some programs need kernel networking support even |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 992ec49a96aa..44cb786b925a 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -112,6 +112,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
112 | 112 | ||
113 | kfree_skb(skb); | 113 | kfree_skb(skb); |
114 | } | 114 | } |
115 | EXPORT_SYMBOL_GPL(br_deliver); | ||
115 | 116 | ||
116 | /* called with rcu_read_lock */ | 117 | /* called with rcu_read_lock */ |
117 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0) | 118 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0) |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 648d79ccf462..c465876c7861 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -813,10 +813,9 @@ static void __br_multicast_send_query(struct net_bridge *br, | |||
813 | return; | 813 | return; |
814 | 814 | ||
815 | if (port) { | 815 | if (port) { |
816 | __skb_push(skb, sizeof(struct ethhdr)); | ||
817 | skb->dev = port->dev; | 816 | skb->dev = port->dev; |
818 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 817 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
819 | dev_queue_xmit); | 818 | br_dev_queue_push_xmit); |
820 | } else { | 819 | } else { |
821 | br_multicast_select_own_querier(br, ip, skb); | 820 | br_multicast_select_own_querier(br, ip, skb); |
822 | netif_rx(skb); | 821 | netif_rx(skb); |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 1bada53bb195..1a4f32c09ad5 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -192,7 +192,6 @@ static inline void nf_bridge_save_header(struct sk_buff *skb) | |||
192 | 192 | ||
193 | static int br_parse_ip_options(struct sk_buff *skb) | 193 | static int br_parse_ip_options(struct sk_buff *skb) |
194 | { | 194 | { |
195 | struct ip_options *opt; | ||
196 | const struct iphdr *iph; | 195 | const struct iphdr *iph; |
197 | struct net_device *dev = skb->dev; | 196 | struct net_device *dev = skb->dev; |
198 | u32 len; | 197 | u32 len; |
@@ -201,7 +200,6 @@ static int br_parse_ip_options(struct sk_buff *skb) | |||
201 | goto inhdr_error; | 200 | goto inhdr_error; |
202 | 201 | ||
203 | iph = ip_hdr(skb); | 202 | iph = ip_hdr(skb); |
204 | opt = &(IPCB(skb)->opt); | ||
205 | 203 | ||
206 | /* Basic sanity checks */ | 204 | /* Basic sanity checks */ |
207 | if (iph->ihl < 5 || iph->version != 4) | 205 | if (iph->ihl < 5 || iph->version != 4) |
@@ -227,23 +225,11 @@ static int br_parse_ip_options(struct sk_buff *skb) | |||
227 | } | 225 | } |
228 | 226 | ||
229 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 227 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
230 | if (iph->ihl == 5) | 228 | /* We should really parse IP options here but until |
231 | return 0; | 229 | * somebody who actually uses IP options complains to |
232 | 230 | * us we'll just silently ignore the options because | |
233 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); | 231 | * we're lazy! |
234 | if (ip_options_compile(dev_net(dev), opt, skb)) | 232 | */ |
235 | goto inhdr_error; | ||
236 | |||
237 | /* Check correct handling of SRR option */ | ||
238 | if (unlikely(opt->srr)) { | ||
239 | struct in_device *in_dev = __in_dev_get_rcu(dev); | ||
240 | if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev)) | ||
241 | goto drop; | ||
242 | |||
243 | if (ip_options_rcv_srr(skb)) | ||
244 | goto drop; | ||
245 | } | ||
246 | |||
247 | return 0; | 233 | return 0; |
248 | 234 | ||
249 | inhdr_error: | 235 | inhdr_error: |
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index da17a5eab8b4..074c557ab505 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c | |||
@@ -75,9 +75,11 @@ static const struct nf_chain_type filter_bridge = { | |||
75 | .type = NFT_CHAIN_T_DEFAULT, | 75 | .type = NFT_CHAIN_T_DEFAULT, |
76 | .family = NFPROTO_BRIDGE, | 76 | .family = NFPROTO_BRIDGE, |
77 | .owner = THIS_MODULE, | 77 | .owner = THIS_MODULE, |
78 | .hook_mask = (1 << NF_BR_LOCAL_IN) | | 78 | .hook_mask = (1 << NF_BR_PRE_ROUTING) | |
79 | (1 << NF_BR_LOCAL_IN) | | ||
79 | (1 << NF_BR_FORWARD) | | 80 | (1 << NF_BR_FORWARD) | |
80 | (1 << NF_BR_LOCAL_OUT), | 81 | (1 << NF_BR_LOCAL_OUT) | |
82 | (1 << NF_BR_POST_ROUTING), | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | static int __init nf_tables_bridge_init(void) | 85 | static int __init nf_tables_bridge_init(void) |
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index a76479535df2..48da2c54a69e 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -16,6 +16,239 @@ | |||
16 | #include <net/netfilter/nft_reject.h> | 16 | #include <net/netfilter/nft_reject.h> |
17 | #include <net/netfilter/ipv4/nf_reject.h> | 17 | #include <net/netfilter/ipv4/nf_reject.h> |
18 | #include <net/netfilter/ipv6/nf_reject.h> | 18 | #include <net/netfilter/ipv6/nf_reject.h> |
19 | #include <linux/ip.h> | ||
20 | #include <net/ip.h> | ||
21 | #include <net/ip6_checksum.h> | ||
22 | #include <linux/netfilter_bridge.h> | ||
23 | #include "../br_private.h" | ||
24 | |||
25 | static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, | ||
26 | struct sk_buff *nskb) | ||
27 | { | ||
28 | struct ethhdr *eth; | ||
29 | |||
30 | eth = (struct ethhdr *)skb_push(nskb, ETH_HLEN); | ||
31 | skb_reset_mac_header(nskb); | ||
32 | ether_addr_copy(eth->h_source, eth_hdr(oldskb)->h_dest); | ||
33 | ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source); | ||
34 | eth->h_proto = eth_hdr(oldskb)->h_proto; | ||
35 | skb_pull(nskb, ETH_HLEN); | ||
36 | } | ||
37 | |||
38 | static int nft_reject_iphdr_validate(struct sk_buff *oldskb) | ||
39 | { | ||
40 | struct iphdr *iph; | ||
41 | u32 len; | ||
42 | |||
43 | if (!pskb_may_pull(oldskb, sizeof(struct iphdr))) | ||
44 | return 0; | ||
45 | |||
46 | iph = ip_hdr(oldskb); | ||
47 | if (iph->ihl < 5 || iph->version != 4) | ||
48 | return 0; | ||
49 | |||
50 | len = ntohs(iph->tot_len); | ||
51 | if (oldskb->len < len) | ||
52 | return 0; | ||
53 | else if (len < (iph->ihl*4)) | ||
54 | return 0; | ||
55 | |||
56 | if (!pskb_may_pull(oldskb, iph->ihl*4)) | ||
57 | return 0; | ||
58 | |||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | ||
63 | { | ||
64 | struct sk_buff *nskb; | ||
65 | struct iphdr *niph; | ||
66 | const struct tcphdr *oth; | ||
67 | struct tcphdr _oth; | ||
68 | |||
69 | if (!nft_reject_iphdr_validate(oldskb)) | ||
70 | return; | ||
71 | |||
72 | oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); | ||
73 | if (!oth) | ||
74 | return; | ||
75 | |||
76 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | ||
77 | LL_MAX_HEADER, GFP_ATOMIC); | ||
78 | if (!nskb) | ||
79 | return; | ||
80 | |||
81 | skb_reserve(nskb, LL_MAX_HEADER); | ||
82 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, | ||
83 | sysctl_ip_default_ttl); | ||
84 | nf_reject_ip_tcphdr_put(nskb, oldskb, oth); | ||
85 | niph->ttl = sysctl_ip_default_ttl; | ||
86 | niph->tot_len = htons(nskb->len); | ||
87 | ip_send_check(niph); | ||
88 | |||
89 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
90 | |||
91 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
92 | } | ||
93 | |||
94 | static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | ||
95 | u8 code) | ||
96 | { | ||
97 | struct sk_buff *nskb; | ||
98 | struct iphdr *niph; | ||
99 | struct icmphdr *icmph; | ||
100 | unsigned int len; | ||
101 | void *payload; | ||
102 | __wsum csum; | ||
103 | |||
104 | if (!nft_reject_iphdr_validate(oldskb)) | ||
105 | return; | ||
106 | |||
107 | /* IP header checks: fragment. */ | ||
108 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | ||
109 | return; | ||
110 | |||
111 | /* RFC says return as much as we can without exceeding 576 bytes. */ | ||
112 | len = min_t(unsigned int, 536, oldskb->len); | ||
113 | |||
114 | if (!pskb_may_pull(oldskb, len)) | ||
115 | return; | ||
116 | |||
117 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), 0)) | ||
118 | return; | ||
119 | |||
120 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) + | ||
121 | LL_MAX_HEADER + len, GFP_ATOMIC); | ||
122 | if (!nskb) | ||
123 | return; | ||
124 | |||
125 | skb_reserve(nskb, LL_MAX_HEADER); | ||
126 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP, | ||
127 | sysctl_ip_default_ttl); | ||
128 | |||
129 | skb_reset_transport_header(nskb); | ||
130 | icmph = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr)); | ||
131 | memset(icmph, 0, sizeof(*icmph)); | ||
132 | icmph->type = ICMP_DEST_UNREACH; | ||
133 | icmph->code = code; | ||
134 | |||
135 | payload = skb_put(nskb, len); | ||
136 | memcpy(payload, skb_network_header(oldskb), len); | ||
137 | |||
138 | csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0); | ||
139 | icmph->checksum = csum_fold(csum); | ||
140 | |||
141 | niph->tot_len = htons(nskb->len); | ||
142 | ip_send_check(niph); | ||
143 | |||
144 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
145 | |||
146 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
147 | } | ||
148 | |||
149 | static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb) | ||
150 | { | ||
151 | struct ipv6hdr *hdr; | ||
152 | u32 pkt_len; | ||
153 | |||
154 | if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr))) | ||
155 | return 0; | ||
156 | |||
157 | hdr = ipv6_hdr(oldskb); | ||
158 | if (hdr->version != 6) | ||
159 | return 0; | ||
160 | |||
161 | pkt_len = ntohs(hdr->payload_len); | ||
162 | if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len) | ||
163 | return 0; | ||
164 | |||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, | ||
169 | struct sk_buff *oldskb, int hook) | ||
170 | { | ||
171 | struct sk_buff *nskb; | ||
172 | const struct tcphdr *oth; | ||
173 | struct tcphdr _oth; | ||
174 | unsigned int otcplen; | ||
175 | struct ipv6hdr *nip6h; | ||
176 | |||
177 | if (!nft_reject_ip6hdr_validate(oldskb)) | ||
178 | return; | ||
179 | |||
180 | oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); | ||
181 | if (!oth) | ||
182 | return; | ||
183 | |||
184 | nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + | ||
185 | LL_MAX_HEADER, GFP_ATOMIC); | ||
186 | if (!nskb) | ||
187 | return; | ||
188 | |||
189 | skb_reserve(nskb, LL_MAX_HEADER); | ||
190 | nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, | ||
191 | net->ipv6.devconf_all->hop_limit); | ||
192 | nf_reject_ip6_tcphdr_put(nskb, oldskb, oth, otcplen); | ||
193 | nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); | ||
194 | |||
195 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
196 | |||
197 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
198 | } | ||
199 | |||
200 | static void nft_reject_br_send_v6_unreach(struct net *net, | ||
201 | struct sk_buff *oldskb, int hook, | ||
202 | u8 code) | ||
203 | { | ||
204 | struct sk_buff *nskb; | ||
205 | struct ipv6hdr *nip6h; | ||
206 | struct icmp6hdr *icmp6h; | ||
207 | unsigned int len; | ||
208 | void *payload; | ||
209 | |||
210 | if (!nft_reject_ip6hdr_validate(oldskb)) | ||
211 | return; | ||
212 | |||
213 | /* Include "As much of invoking packet as possible without the ICMPv6 | ||
214 | * packet exceeding the minimum IPv6 MTU" in the ICMP payload. | ||
215 | */ | ||
216 | len = min_t(unsigned int, 1220, oldskb->len); | ||
217 | |||
218 | if (!pskb_may_pull(oldskb, len)) | ||
219 | return; | ||
220 | |||
221 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) + | ||
222 | LL_MAX_HEADER + len, GFP_ATOMIC); | ||
223 | if (!nskb) | ||
224 | return; | ||
225 | |||
226 | skb_reserve(nskb, LL_MAX_HEADER); | ||
227 | nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_ICMPV6, | ||
228 | net->ipv6.devconf_all->hop_limit); | ||
229 | |||
230 | skb_reset_transport_header(nskb); | ||
231 | icmp6h = (struct icmp6hdr *)skb_put(nskb, sizeof(struct icmp6hdr)); | ||
232 | memset(icmp6h, 0, sizeof(*icmp6h)); | ||
233 | icmp6h->icmp6_type = ICMPV6_DEST_UNREACH; | ||
234 | icmp6h->icmp6_code = code; | ||
235 | |||
236 | payload = skb_put(nskb, len); | ||
237 | memcpy(payload, skb_network_header(oldskb), len); | ||
238 | nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); | ||
239 | |||
240 | icmp6h->icmp6_cksum = | ||
241 | csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, | ||
242 | nskb->len - sizeof(struct ipv6hdr), | ||
243 | IPPROTO_ICMPV6, | ||
244 | csum_partial(icmp6h, | ||
245 | nskb->len - sizeof(struct ipv6hdr), | ||
246 | 0)); | ||
247 | |||
248 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
249 | |||
250 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
251 | } | ||
19 | 252 | ||
20 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | 253 | static void nft_reject_bridge_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 254 | struct nft_data data[NFT_REG_MAX + 1], |
@@ -23,35 +256,46 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
23 | { | 256 | { |
24 | struct nft_reject *priv = nft_expr_priv(expr); | 257 | struct nft_reject *priv = nft_expr_priv(expr); |
25 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | 258 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); |
259 | const unsigned char *dest = eth_hdr(pkt->skb)->h_dest; | ||
260 | |||
261 | if (is_broadcast_ether_addr(dest) || | ||
262 | is_multicast_ether_addr(dest)) | ||
263 | goto out; | ||
26 | 264 | ||
27 | switch (eth_hdr(pkt->skb)->h_proto) { | 265 | switch (eth_hdr(pkt->skb)->h_proto) { |
28 | case htons(ETH_P_IP): | 266 | case htons(ETH_P_IP): |
29 | switch (priv->type) { | 267 | switch (priv->type) { |
30 | case NFT_REJECT_ICMP_UNREACH: | 268 | case NFT_REJECT_ICMP_UNREACH: |
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | 269 | nft_reject_br_send_v4_unreach(pkt->skb, |
270 | pkt->ops->hooknum, | ||
271 | priv->icmp_code); | ||
32 | break; | 272 | break; |
33 | case NFT_REJECT_TCP_RST: | 273 | case NFT_REJECT_TCP_RST: |
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | 274 | nft_reject_br_send_v4_tcp_reset(pkt->skb, |
275 | pkt->ops->hooknum); | ||
35 | break; | 276 | break; |
36 | case NFT_REJECT_ICMPX_UNREACH: | 277 | case NFT_REJECT_ICMPX_UNREACH: |
37 | nf_send_unreach(pkt->skb, | 278 | nft_reject_br_send_v4_unreach(pkt->skb, |
38 | nft_reject_icmp_code(priv->icmp_code)); | 279 | pkt->ops->hooknum, |
280 | nft_reject_icmp_code(priv->icmp_code)); | ||
39 | break; | 281 | break; |
40 | } | 282 | } |
41 | break; | 283 | break; |
42 | case htons(ETH_P_IPV6): | 284 | case htons(ETH_P_IPV6): |
43 | switch (priv->type) { | 285 | switch (priv->type) { |
44 | case NFT_REJECT_ICMP_UNREACH: | 286 | case NFT_REJECT_ICMP_UNREACH: |
45 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | 287 | nft_reject_br_send_v6_unreach(net, pkt->skb, |
46 | pkt->ops->hooknum); | 288 | pkt->ops->hooknum, |
289 | priv->icmp_code); | ||
47 | break; | 290 | break; |
48 | case NFT_REJECT_TCP_RST: | 291 | case NFT_REJECT_TCP_RST: |
49 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | 292 | nft_reject_br_send_v6_tcp_reset(net, pkt->skb, |
293 | pkt->ops->hooknum); | ||
50 | break; | 294 | break; |
51 | case NFT_REJECT_ICMPX_UNREACH: | 295 | case NFT_REJECT_ICMPX_UNREACH: |
52 | nf_send_unreach6(net, pkt->skb, | 296 | nft_reject_br_send_v6_unreach(net, pkt->skb, |
53 | nft_reject_icmpv6_code(priv->icmp_code), | 297 | pkt->ops->hooknum, |
54 | pkt->ops->hooknum); | 298 | nft_reject_icmpv6_code(priv->icmp_code)); |
55 | break; | 299 | break; |
56 | } | 300 | } |
57 | break; | 301 | break; |
@@ -59,15 +303,38 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
59 | /* No explicit way to reject this protocol, drop it. */ | 303 | /* No explicit way to reject this protocol, drop it. */ |
60 | break; | 304 | break; |
61 | } | 305 | } |
306 | out: | ||
62 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 307 | data[NFT_REG_VERDICT].verdict = NF_DROP; |
63 | } | 308 | } |
64 | 309 | ||
310 | static int nft_reject_bridge_validate_hooks(const struct nft_chain *chain) | ||
311 | { | ||
312 | struct nft_base_chain *basechain; | ||
313 | |||
314 | if (chain->flags & NFT_BASE_CHAIN) { | ||
315 | basechain = nft_base_chain(chain); | ||
316 | |||
317 | switch (basechain->ops[0].hooknum) { | ||
318 | case NF_BR_PRE_ROUTING: | ||
319 | case NF_BR_LOCAL_IN: | ||
320 | break; | ||
321 | default: | ||
322 | return -EOPNOTSUPP; | ||
323 | } | ||
324 | } | ||
325 | return 0; | ||
326 | } | ||
327 | |||
65 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, | 328 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, |
66 | const struct nft_expr *expr, | 329 | const struct nft_expr *expr, |
67 | const struct nlattr * const tb[]) | 330 | const struct nlattr * const tb[]) |
68 | { | 331 | { |
69 | struct nft_reject *priv = nft_expr_priv(expr); | 332 | struct nft_reject *priv = nft_expr_priv(expr); |
70 | int icmp_code; | 333 | int icmp_code, err; |
334 | |||
335 | err = nft_reject_bridge_validate_hooks(ctx->chain); | ||
336 | if (err < 0) | ||
337 | return err; | ||
71 | 338 | ||
72 | if (tb[NFTA_REJECT_TYPE] == NULL) | 339 | if (tb[NFTA_REJECT_TYPE] == NULL) |
73 | return -EINVAL; | 340 | return -EINVAL; |
@@ -116,6 +383,13 @@ nla_put_failure: | |||
116 | return -1; | 383 | return -1; |
117 | } | 384 | } |
118 | 385 | ||
386 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, | ||
387 | const struct nft_expr *expr, | ||
388 | const struct nft_data **data) | ||
389 | { | ||
390 | return nft_reject_bridge_validate_hooks(ctx->chain); | ||
391 | } | ||
392 | |||
119 | static struct nft_expr_type nft_reject_bridge_type; | 393 | static struct nft_expr_type nft_reject_bridge_type; |
120 | static const struct nft_expr_ops nft_reject_bridge_ops = { | 394 | static const struct nft_expr_ops nft_reject_bridge_ops = { |
121 | .type = &nft_reject_bridge_type, | 395 | .type = &nft_reject_bridge_type, |
@@ -123,6 +397,7 @@ static const struct nft_expr_ops nft_reject_bridge_ops = { | |||
123 | .eval = nft_reject_bridge_eval, | 397 | .eval = nft_reject_bridge_eval, |
124 | .init = nft_reject_bridge_init, | 398 | .init = nft_reject_bridge_init, |
125 | .dump = nft_reject_bridge_dump, | 399 | .dump = nft_reject_bridge_dump, |
400 | .validate = nft_reject_bridge_validate, | ||
126 | }; | 401 | }; |
127 | 402 | ||
128 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { | 403 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index de6662b14e1f..7e38b729696a 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -149,6 +149,7 @@ static int process_one_ticket(struct ceph_auth_client *ac, | |||
149 | struct ceph_crypto_key old_key; | 149 | struct ceph_crypto_key old_key; |
150 | void *ticket_buf = NULL; | 150 | void *ticket_buf = NULL; |
151 | void *tp, *tpend; | 151 | void *tp, *tpend; |
152 | void **ptp; | ||
152 | struct ceph_timespec new_validity; | 153 | struct ceph_timespec new_validity; |
153 | struct ceph_crypto_key new_session_key; | 154 | struct ceph_crypto_key new_session_key; |
154 | struct ceph_buffer *new_ticket_blob; | 155 | struct ceph_buffer *new_ticket_blob; |
@@ -208,25 +209,19 @@ static int process_one_ticket(struct ceph_auth_client *ac, | |||
208 | goto out; | 209 | goto out; |
209 | } | 210 | } |
210 | tp = ticket_buf; | 211 | tp = ticket_buf; |
211 | dlen = ceph_decode_32(&tp); | 212 | ptp = &tp; |
213 | tpend = *ptp + dlen; | ||
212 | } else { | 214 | } else { |
213 | /* unencrypted */ | 215 | /* unencrypted */ |
214 | ceph_decode_32_safe(p, end, dlen, bad); | 216 | ptp = p; |
215 | ticket_buf = kmalloc(dlen, GFP_NOFS); | 217 | tpend = end; |
216 | if (!ticket_buf) { | ||
217 | ret = -ENOMEM; | ||
218 | goto out; | ||
219 | } | ||
220 | tp = ticket_buf; | ||
221 | ceph_decode_need(p, end, dlen, bad); | ||
222 | ceph_decode_copy(p, ticket_buf, dlen); | ||
223 | } | 218 | } |
224 | tpend = tp + dlen; | 219 | ceph_decode_32_safe(ptp, tpend, dlen, bad); |
225 | dout(" ticket blob is %d bytes\n", dlen); | 220 | dout(" ticket blob is %d bytes\n", dlen); |
226 | ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); | 221 | ceph_decode_need(ptp, tpend, 1 + sizeof(u64), bad); |
227 | blob_struct_v = ceph_decode_8(&tp); | 222 | blob_struct_v = ceph_decode_8(ptp); |
228 | new_secret_id = ceph_decode_64(&tp); | 223 | new_secret_id = ceph_decode_64(ptp); |
229 | ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); | 224 | ret = ceph_decode_buffer(&new_ticket_blob, ptp, tpend); |
230 | if (ret) | 225 | if (ret) |
231 | goto out; | 226 | goto out; |
232 | 227 | ||
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 62fc5e7a9acf..790fe89d90c0 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -90,11 +90,82 @@ static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void) | |||
90 | 90 | ||
91 | static const u8 *aes_iv = (u8 *)CEPH_AES_IV; | 91 | static const u8 *aes_iv = (u8 *)CEPH_AES_IV; |
92 | 92 | ||
93 | /* | ||
94 | * Should be used for buffers allocated with ceph_kvmalloc(). | ||
95 | * Currently these are encrypt out-buffer (ceph_buffer) and decrypt | ||
96 | * in-buffer (msg front). | ||
97 | * | ||
98 | * Dispose of @sgt with teardown_sgtable(). | ||
99 | * | ||
100 | * @prealloc_sg is to avoid memory allocation inside sg_alloc_table() | ||
101 | * in cases where a single sg is sufficient. No attempt to reduce the | ||
102 | * number of sgs by squeezing physically contiguous pages together is | ||
103 | * made though, for simplicity. | ||
104 | */ | ||
105 | static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg, | ||
106 | const void *buf, unsigned int buf_len) | ||
107 | { | ||
108 | struct scatterlist *sg; | ||
109 | const bool is_vmalloc = is_vmalloc_addr(buf); | ||
110 | unsigned int off = offset_in_page(buf); | ||
111 | unsigned int chunk_cnt = 1; | ||
112 | unsigned int chunk_len = PAGE_ALIGN(off + buf_len); | ||
113 | int i; | ||
114 | int ret; | ||
115 | |||
116 | if (buf_len == 0) { | ||
117 | memset(sgt, 0, sizeof(*sgt)); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | if (is_vmalloc) { | ||
122 | chunk_cnt = chunk_len >> PAGE_SHIFT; | ||
123 | chunk_len = PAGE_SIZE; | ||
124 | } | ||
125 | |||
126 | if (chunk_cnt > 1) { | ||
127 | ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | } else { | ||
131 | WARN_ON(chunk_cnt != 1); | ||
132 | sg_init_table(prealloc_sg, 1); | ||
133 | sgt->sgl = prealloc_sg; | ||
134 | sgt->nents = sgt->orig_nents = 1; | ||
135 | } | ||
136 | |||
137 | for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { | ||
138 | struct page *page; | ||
139 | unsigned int len = min(chunk_len - off, buf_len); | ||
140 | |||
141 | if (is_vmalloc) | ||
142 | page = vmalloc_to_page(buf); | ||
143 | else | ||
144 | page = virt_to_page(buf); | ||
145 | |||
146 | sg_set_page(sg, page, len, off); | ||
147 | |||
148 | off = 0; | ||
149 | buf += len; | ||
150 | buf_len -= len; | ||
151 | } | ||
152 | WARN_ON(buf_len != 0); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static void teardown_sgtable(struct sg_table *sgt) | ||
158 | { | ||
159 | if (sgt->orig_nents > 1) | ||
160 | sg_free_table(sgt); | ||
161 | } | ||
162 | |||
93 | static int ceph_aes_encrypt(const void *key, int key_len, | 163 | static int ceph_aes_encrypt(const void *key, int key_len, |
94 | void *dst, size_t *dst_len, | 164 | void *dst, size_t *dst_len, |
95 | const void *src, size_t src_len) | 165 | const void *src, size_t src_len) |
96 | { | 166 | { |
97 | struct scatterlist sg_in[2], sg_out[1]; | 167 | struct scatterlist sg_in[2], prealloc_sg; |
168 | struct sg_table sg_out; | ||
98 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); | 169 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); |
99 | struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; | 170 | struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; |
100 | int ret; | 171 | int ret; |
@@ -110,16 +181,18 @@ static int ceph_aes_encrypt(const void *key, int key_len, | |||
110 | 181 | ||
111 | *dst_len = src_len + zero_padding; | 182 | *dst_len = src_len + zero_padding; |
112 | 183 | ||
113 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | ||
114 | sg_init_table(sg_in, 2); | 184 | sg_init_table(sg_in, 2); |
115 | sg_set_buf(&sg_in[0], src, src_len); | 185 | sg_set_buf(&sg_in[0], src, src_len); |
116 | sg_set_buf(&sg_in[1], pad, zero_padding); | 186 | sg_set_buf(&sg_in[1], pad, zero_padding); |
117 | sg_init_table(sg_out, 1); | 187 | ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); |
118 | sg_set_buf(sg_out, dst, *dst_len); | 188 | if (ret) |
189 | goto out_tfm; | ||
190 | |||
191 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | ||
119 | iv = crypto_blkcipher_crt(tfm)->iv; | 192 | iv = crypto_blkcipher_crt(tfm)->iv; |
120 | ivsize = crypto_blkcipher_ivsize(tfm); | 193 | ivsize = crypto_blkcipher_ivsize(tfm); |
121 | |||
122 | memcpy(iv, aes_iv, ivsize); | 194 | memcpy(iv, aes_iv, ivsize); |
195 | |||
123 | /* | 196 | /* |
124 | print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, | 197 | print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, |
125 | key, key_len, 1); | 198 | key, key_len, 1); |
@@ -128,16 +201,22 @@ static int ceph_aes_encrypt(const void *key, int key_len, | |||
128 | print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, | 201 | print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, |
129 | pad, zero_padding, 1); | 202 | pad, zero_padding, 1); |
130 | */ | 203 | */ |
131 | ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, | 204 | ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, |
132 | src_len + zero_padding); | 205 | src_len + zero_padding); |
133 | crypto_free_blkcipher(tfm); | 206 | if (ret < 0) { |
134 | if (ret < 0) | ||
135 | pr_err("ceph_aes_crypt failed %d\n", ret); | 207 | pr_err("ceph_aes_crypt failed %d\n", ret); |
208 | goto out_sg; | ||
209 | } | ||
136 | /* | 210 | /* |
137 | print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, | 211 | print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, |
138 | dst, *dst_len, 1); | 212 | dst, *dst_len, 1); |
139 | */ | 213 | */ |
140 | return 0; | 214 | |
215 | out_sg: | ||
216 | teardown_sgtable(&sg_out); | ||
217 | out_tfm: | ||
218 | crypto_free_blkcipher(tfm); | ||
219 | return ret; | ||
141 | } | 220 | } |
142 | 221 | ||
143 | static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, | 222 | static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, |
@@ -145,7 +224,8 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, | |||
145 | const void *src1, size_t src1_len, | 224 | const void *src1, size_t src1_len, |
146 | const void *src2, size_t src2_len) | 225 | const void *src2, size_t src2_len) |
147 | { | 226 | { |
148 | struct scatterlist sg_in[3], sg_out[1]; | 227 | struct scatterlist sg_in[3], prealloc_sg; |
228 | struct sg_table sg_out; | ||
149 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); | 229 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); |
150 | struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; | 230 | struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; |
151 | int ret; | 231 | int ret; |
@@ -161,17 +241,19 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, | |||
161 | 241 | ||
162 | *dst_len = src1_len + src2_len + zero_padding; | 242 | *dst_len = src1_len + src2_len + zero_padding; |
163 | 243 | ||
164 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | ||
165 | sg_init_table(sg_in, 3); | 244 | sg_init_table(sg_in, 3); |
166 | sg_set_buf(&sg_in[0], src1, src1_len); | 245 | sg_set_buf(&sg_in[0], src1, src1_len); |
167 | sg_set_buf(&sg_in[1], src2, src2_len); | 246 | sg_set_buf(&sg_in[1], src2, src2_len); |
168 | sg_set_buf(&sg_in[2], pad, zero_padding); | 247 | sg_set_buf(&sg_in[2], pad, zero_padding); |
169 | sg_init_table(sg_out, 1); | 248 | ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); |
170 | sg_set_buf(sg_out, dst, *dst_len); | 249 | if (ret) |
250 | goto out_tfm; | ||
251 | |||
252 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | ||
171 | iv = crypto_blkcipher_crt(tfm)->iv; | 253 | iv = crypto_blkcipher_crt(tfm)->iv; |
172 | ivsize = crypto_blkcipher_ivsize(tfm); | 254 | ivsize = crypto_blkcipher_ivsize(tfm); |
173 | |||
174 | memcpy(iv, aes_iv, ivsize); | 255 | memcpy(iv, aes_iv, ivsize); |
256 | |||
175 | /* | 257 | /* |
176 | print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, | 258 | print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, |
177 | key, key_len, 1); | 259 | key, key_len, 1); |
@@ -182,23 +264,30 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, | |||
182 | print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, | 264 | print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, |
183 | pad, zero_padding, 1); | 265 | pad, zero_padding, 1); |
184 | */ | 266 | */ |
185 | ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, | 267 | ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, |
186 | src1_len + src2_len + zero_padding); | 268 | src1_len + src2_len + zero_padding); |
187 | crypto_free_blkcipher(tfm); | 269 | if (ret < 0) { |
188 | if (ret < 0) | ||
189 | pr_err("ceph_aes_crypt2 failed %d\n", ret); | 270 | pr_err("ceph_aes_crypt2 failed %d\n", ret); |
271 | goto out_sg; | ||
272 | } | ||
190 | /* | 273 | /* |
191 | print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, | 274 | print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, |
192 | dst, *dst_len, 1); | 275 | dst, *dst_len, 1); |
193 | */ | 276 | */ |
194 | return 0; | 277 | |
278 | out_sg: | ||
279 | teardown_sgtable(&sg_out); | ||
280 | out_tfm: | ||
281 | crypto_free_blkcipher(tfm); | ||
282 | return ret; | ||
195 | } | 283 | } |
196 | 284 | ||
197 | static int ceph_aes_decrypt(const void *key, int key_len, | 285 | static int ceph_aes_decrypt(const void *key, int key_len, |
198 | void *dst, size_t *dst_len, | 286 | void *dst, size_t *dst_len, |
199 | const void *src, size_t src_len) | 287 | const void *src, size_t src_len) |
200 | { | 288 | { |
201 | struct scatterlist sg_in[1], sg_out[2]; | 289 | struct sg_table sg_in; |
290 | struct scatterlist sg_out[2], prealloc_sg; | ||
202 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); | 291 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); |
203 | struct blkcipher_desc desc = { .tfm = tfm }; | 292 | struct blkcipher_desc desc = { .tfm = tfm }; |
204 | char pad[16]; | 293 | char pad[16]; |
@@ -210,16 +299,16 @@ static int ceph_aes_decrypt(const void *key, int key_len, | |||
210 | if (IS_ERR(tfm)) | 299 | if (IS_ERR(tfm)) |
211 | return PTR_ERR(tfm); | 300 | return PTR_ERR(tfm); |
212 | 301 | ||
213 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | ||
214 | sg_init_table(sg_in, 1); | ||
215 | sg_init_table(sg_out, 2); | 302 | sg_init_table(sg_out, 2); |
216 | sg_set_buf(sg_in, src, src_len); | ||
217 | sg_set_buf(&sg_out[0], dst, *dst_len); | 303 | sg_set_buf(&sg_out[0], dst, *dst_len); |
218 | sg_set_buf(&sg_out[1], pad, sizeof(pad)); | 304 | sg_set_buf(&sg_out[1], pad, sizeof(pad)); |
305 | ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); | ||
306 | if (ret) | ||
307 | goto out_tfm; | ||
219 | 308 | ||
309 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | ||
220 | iv = crypto_blkcipher_crt(tfm)->iv; | 310 | iv = crypto_blkcipher_crt(tfm)->iv; |
221 | ivsize = crypto_blkcipher_ivsize(tfm); | 311 | ivsize = crypto_blkcipher_ivsize(tfm); |
222 | |||
223 | memcpy(iv, aes_iv, ivsize); | 312 | memcpy(iv, aes_iv, ivsize); |
224 | 313 | ||
225 | /* | 314 | /* |
@@ -228,12 +317,10 @@ static int ceph_aes_decrypt(const void *key, int key_len, | |||
228 | print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, | 317 | print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, |
229 | src, src_len, 1); | 318 | src, src_len, 1); |
230 | */ | 319 | */ |
231 | 320 | ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); | |
232 | ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len); | ||
233 | crypto_free_blkcipher(tfm); | ||
234 | if (ret < 0) { | 321 | if (ret < 0) { |
235 | pr_err("ceph_aes_decrypt failed %d\n", ret); | 322 | pr_err("ceph_aes_decrypt failed %d\n", ret); |
236 | return ret; | 323 | goto out_sg; |
237 | } | 324 | } |
238 | 325 | ||
239 | if (src_len <= *dst_len) | 326 | if (src_len <= *dst_len) |
@@ -251,7 +338,12 @@ static int ceph_aes_decrypt(const void *key, int key_len, | |||
251 | print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1, | 338 | print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1, |
252 | dst, *dst_len, 1); | 339 | dst, *dst_len, 1); |
253 | */ | 340 | */ |
254 | return 0; | 341 | |
342 | out_sg: | ||
343 | teardown_sgtable(&sg_in); | ||
344 | out_tfm: | ||
345 | crypto_free_blkcipher(tfm); | ||
346 | return ret; | ||
255 | } | 347 | } |
256 | 348 | ||
257 | static int ceph_aes_decrypt2(const void *key, int key_len, | 349 | static int ceph_aes_decrypt2(const void *key, int key_len, |
@@ -259,7 +351,8 @@ static int ceph_aes_decrypt2(const void *key, int key_len, | |||
259 | void *dst2, size_t *dst2_len, | 351 | void *dst2, size_t *dst2_len, |
260 | const void *src, size_t src_len) | 352 | const void *src, size_t src_len) |
261 | { | 353 | { |
262 | struct scatterlist sg_in[1], sg_out[3]; | 354 | struct sg_table sg_in; |
355 | struct scatterlist sg_out[3], prealloc_sg; | ||
263 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); | 356 | struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); |
264 | struct blkcipher_desc desc = { .tfm = tfm }; | 357 | struct blkcipher_desc desc = { .tfm = tfm }; |
265 | char pad[16]; | 358 | char pad[16]; |
@@ -271,17 +364,17 @@ static int ceph_aes_decrypt2(const void *key, int key_len, | |||
271 | if (IS_ERR(tfm)) | 364 | if (IS_ERR(tfm)) |
272 | return PTR_ERR(tfm); | 365 | return PTR_ERR(tfm); |
273 | 366 | ||
274 | sg_init_table(sg_in, 1); | ||
275 | sg_set_buf(sg_in, src, src_len); | ||
276 | sg_init_table(sg_out, 3); | 367 | sg_init_table(sg_out, 3); |
277 | sg_set_buf(&sg_out[0], dst1, *dst1_len); | 368 | sg_set_buf(&sg_out[0], dst1, *dst1_len); |
278 | sg_set_buf(&sg_out[1], dst2, *dst2_len); | 369 | sg_set_buf(&sg_out[1], dst2, *dst2_len); |
279 | sg_set_buf(&sg_out[2], pad, sizeof(pad)); | 370 | sg_set_buf(&sg_out[2], pad, sizeof(pad)); |
371 | ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); | ||
372 | if (ret) | ||
373 | goto out_tfm; | ||
280 | 374 | ||
281 | crypto_blkcipher_setkey((void *)tfm, key, key_len); | 375 | crypto_blkcipher_setkey((void *)tfm, key, key_len); |
282 | iv = crypto_blkcipher_crt(tfm)->iv; | 376 | iv = crypto_blkcipher_crt(tfm)->iv; |
283 | ivsize = crypto_blkcipher_ivsize(tfm); | 377 | ivsize = crypto_blkcipher_ivsize(tfm); |
284 | |||
285 | memcpy(iv, aes_iv, ivsize); | 378 | memcpy(iv, aes_iv, ivsize); |
286 | 379 | ||
287 | /* | 380 | /* |
@@ -290,12 +383,10 @@ static int ceph_aes_decrypt2(const void *key, int key_len, | |||
290 | print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, | 383 | print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, |
291 | src, src_len, 1); | 384 | src, src_len, 1); |
292 | */ | 385 | */ |
293 | 386 | ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); | |
294 | ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len); | ||
295 | crypto_free_blkcipher(tfm); | ||
296 | if (ret < 0) { | 387 | if (ret < 0) { |
297 | pr_err("ceph_aes_decrypt failed %d\n", ret); | 388 | pr_err("ceph_aes_decrypt failed %d\n", ret); |
298 | return ret; | 389 | goto out_sg; |
299 | } | 390 | } |
300 | 391 | ||
301 | if (src_len <= *dst1_len) | 392 | if (src_len <= *dst1_len) |
@@ -325,7 +416,11 @@ static int ceph_aes_decrypt2(const void *key, int key_len, | |||
325 | dst2, *dst2_len, 1); | 416 | dst2, *dst2_len, 1); |
326 | */ | 417 | */ |
327 | 418 | ||
328 | return 0; | 419 | out_sg: |
420 | teardown_sgtable(&sg_in); | ||
421 | out_tfm: | ||
422 | crypto_free_blkcipher(tfm); | ||
423 | return ret; | ||
329 | } | 424 | } |
330 | 425 | ||
331 | 426 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 559c9f619c20..8d1653caffdb 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -484,7 +484,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) | |||
484 | IPPROTO_TCP, &sock); | 484 | IPPROTO_TCP, &sock); |
485 | if (ret) | 485 | if (ret) |
486 | return ret; | 486 | return ret; |
487 | sock->sk->sk_allocation = GFP_NOFS; | 487 | sock->sk->sk_allocation = GFP_NOFS | __GFP_MEMALLOC; |
488 | 488 | ||
489 | #ifdef CONFIG_LOCKDEP | 489 | #ifdef CONFIG_LOCKDEP |
490 | lockdep_set_class(&sock->sk->sk_lock, &socket_class); | 490 | lockdep_set_class(&sock->sk->sk_lock, &socket_class); |
@@ -509,6 +509,9 @@ static int ceph_tcp_connect(struct ceph_connection *con) | |||
509 | 509 | ||
510 | return ret; | 510 | return ret; |
511 | } | 511 | } |
512 | |||
513 | sk_set_memalloc(sock->sk); | ||
514 | |||
512 | con->sock = sock; | 515 | con->sock = sock; |
513 | return 0; | 516 | return 0; |
514 | } | 517 | } |
@@ -2769,8 +2772,11 @@ static void con_work(struct work_struct *work) | |||
2769 | { | 2772 | { |
2770 | struct ceph_connection *con = container_of(work, struct ceph_connection, | 2773 | struct ceph_connection *con = container_of(work, struct ceph_connection, |
2771 | work.work); | 2774 | work.work); |
2775 | unsigned long pflags = current->flags; | ||
2772 | bool fault; | 2776 | bool fault; |
2773 | 2777 | ||
2778 | current->flags |= PF_MEMALLOC; | ||
2779 | |||
2774 | mutex_lock(&con->mutex); | 2780 | mutex_lock(&con->mutex); |
2775 | while (true) { | 2781 | while (true) { |
2776 | int ret; | 2782 | int ret; |
@@ -2824,6 +2830,8 @@ static void con_work(struct work_struct *work) | |||
2824 | con_fault_finish(con); | 2830 | con_fault_finish(con); |
2825 | 2831 | ||
2826 | con->ops->put(con); | 2832 | con->ops->put(con); |
2833 | |||
2834 | tsk_restore_flags(current, pflags, PF_MEMALLOC); | ||
2827 | } | 2835 | } |
2828 | 2836 | ||
2829 | /* | 2837 | /* |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index f3fc54eac09d..6f164289bde8 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -1007,8 +1007,8 @@ static void put_osd(struct ceph_osd *osd) | |||
1007 | static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) | 1007 | static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) |
1008 | { | 1008 | { |
1009 | dout("__remove_osd %p\n", osd); | 1009 | dout("__remove_osd %p\n", osd); |
1010 | BUG_ON(!list_empty(&osd->o_requests)); | 1010 | WARN_ON(!list_empty(&osd->o_requests)); |
1011 | BUG_ON(!list_empty(&osd->o_linger_requests)); | 1011 | WARN_ON(!list_empty(&osd->o_linger_requests)); |
1012 | 1012 | ||
1013 | rb_erase(&osd->o_node, &osdc->osds); | 1013 | rb_erase(&osd->o_node, &osdc->osds); |
1014 | list_del_init(&osd->o_osd_lru); | 1014 | list_del_init(&osd->o_osd_lru); |
@@ -1254,6 +1254,8 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc, | |||
1254 | if (list_empty(&req->r_osd_item)) | 1254 | if (list_empty(&req->r_osd_item)) |
1255 | req->r_osd = NULL; | 1255 | req->r_osd = NULL; |
1256 | } | 1256 | } |
1257 | |||
1258 | list_del_init(&req->r_req_lru_item); /* can be on notarget */ | ||
1257 | ceph_osdc_put_request(req); | 1259 | ceph_osdc_put_request(req); |
1258 | } | 1260 | } |
1259 | 1261 | ||
@@ -1395,6 +1397,7 @@ static int __map_request(struct ceph_osd_client *osdc, | |||
1395 | if (req->r_osd) { | 1397 | if (req->r_osd) { |
1396 | __cancel_request(req); | 1398 | __cancel_request(req); |
1397 | list_del_init(&req->r_osd_item); | 1399 | list_del_init(&req->r_osd_item); |
1400 | list_del_init(&req->r_linger_osd_item); | ||
1398 | req->r_osd = NULL; | 1401 | req->r_osd = NULL; |
1399 | } | 1402 | } |
1400 | 1403 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index b793e3521a36..945bbd001359 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4157,6 +4157,10 @@ EXPORT_SYMBOL(napi_gro_receive); | |||
4157 | 4157 | ||
4158 | static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) | 4158 | static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) |
4159 | { | 4159 | { |
4160 | if (unlikely(skb->pfmemalloc)) { | ||
4161 | consume_skb(skb); | ||
4162 | return; | ||
4163 | } | ||
4160 | __skb_pull(skb, skb_headlen(skb)); | 4164 | __skb_pull(skb, skb_headlen(skb)); |
4161 | /* restore the reserve we had after netdev_alloc_skb_ip_align() */ | 4165 | /* restore the reserve we had after netdev_alloc_skb_ip_align() */ |
4162 | skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb)); | 4166 | skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb)); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 1600aa24d36b..06dfb293e5aa 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -1036,7 +1036,8 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
1036 | { | 1036 | { |
1037 | const struct ethtool_ops *ops = dev->ethtool_ops; | 1037 | const struct ethtool_ops *ops = dev->ethtool_ops; |
1038 | 1038 | ||
1039 | if (!ops->get_eeprom || !ops->get_eeprom_len) | 1039 | if (!ops->get_eeprom || !ops->get_eeprom_len || |
1040 | !ops->get_eeprom_len(dev)) | ||
1040 | return -EOPNOTSUPP; | 1041 | return -EOPNOTSUPP; |
1041 | 1042 | ||
1042 | return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom, | 1043 | return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom, |
@@ -1052,7 +1053,8 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
1052 | u8 *data; | 1053 | u8 *data; |
1053 | int ret = 0; | 1054 | int ret = 0; |
1054 | 1055 | ||
1055 | if (!ops->set_eeprom || !ops->get_eeprom_len) | 1056 | if (!ops->set_eeprom || !ops->get_eeprom_len || |
1057 | !ops->get_eeprom_len(dev)) | ||
1056 | return -EOPNOTSUPP; | 1058 | return -EOPNOTSUPP; |
1057 | 1059 | ||
1058 | if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) | 1060 | if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 61059a05ec95..32e31c299631 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -552,20 +552,13 @@ static void kfree_skbmem(struct sk_buff *skb) | |||
552 | case SKB_FCLONE_CLONE: | 552 | case SKB_FCLONE_CLONE: |
553 | fclones = container_of(skb, struct sk_buff_fclones, skb2); | 553 | fclones = container_of(skb, struct sk_buff_fclones, skb2); |
554 | 554 | ||
555 | /* Warning : We must perform the atomic_dec_and_test() before | 555 | /* The clone portion is available for |
556 | * setting skb->fclone back to SKB_FCLONE_FREE, otherwise | 556 | * fast-cloning again. |
557 | * skb_clone() could set clone_ref to 2 before our decrement. | ||
558 | * Anyway, if we are going to free the structure, no need to | ||
559 | * rewrite skb->fclone. | ||
560 | */ | 557 | */ |
561 | if (atomic_dec_and_test(&fclones->fclone_ref)) { | 558 | skb->fclone = SKB_FCLONE_FREE; |
559 | |||
560 | if (atomic_dec_and_test(&fclones->fclone_ref)) | ||
562 | kmem_cache_free(skbuff_fclone_cache, fclones); | 561 | kmem_cache_free(skbuff_fclone_cache, fclones); |
563 | } else { | ||
564 | /* The clone portion is available for | ||
565 | * fast-cloning again. | ||
566 | */ | ||
567 | skb->fclone = SKB_FCLONE_FREE; | ||
568 | } | ||
569 | break; | 562 | break; |
570 | } | 563 | } |
571 | } | 564 | } |
@@ -887,11 +880,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
887 | if (skb->fclone == SKB_FCLONE_ORIG && | 880 | if (skb->fclone == SKB_FCLONE_ORIG && |
888 | n->fclone == SKB_FCLONE_FREE) { | 881 | n->fclone == SKB_FCLONE_FREE) { |
889 | n->fclone = SKB_FCLONE_CLONE; | 882 | n->fclone = SKB_FCLONE_CLONE; |
890 | /* As our fastclone was free, clone_ref must be 1 at this point. | 883 | atomic_inc(&fclones->fclone_ref); |
891 | * We could use atomic_inc() here, but it is faster | ||
892 | * to set the final value. | ||
893 | */ | ||
894 | atomic_set(&fclones->fclone_ref, 2); | ||
895 | } else { | 884 | } else { |
896 | if (skb_pfmemalloc(skb)) | 885 | if (skb_pfmemalloc(skb)) |
897 | gfp_mask |= __GFP_MEMALLOC; | 886 | gfp_mask |= __GFP_MEMALLOC; |
@@ -4070,15 +4059,22 @@ EXPORT_SYMBOL_GPL(skb_scrub_packet); | |||
4070 | unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) | 4059 | unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) |
4071 | { | 4060 | { |
4072 | const struct skb_shared_info *shinfo = skb_shinfo(skb); | 4061 | const struct skb_shared_info *shinfo = skb_shinfo(skb); |
4062 | unsigned int thlen = 0; | ||
4073 | 4063 | ||
4074 | if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) | 4064 | if (skb->encapsulation) { |
4075 | return tcp_hdrlen(skb) + shinfo->gso_size; | 4065 | thlen = skb_inner_transport_header(skb) - |
4066 | skb_transport_header(skb); | ||
4076 | 4067 | ||
4068 | if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) | ||
4069 | thlen += inner_tcp_hdrlen(skb); | ||
4070 | } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { | ||
4071 | thlen = tcp_hdrlen(skb); | ||
4072 | } | ||
4077 | /* UFO sets gso_size to the size of the fragmentation | 4073 | /* UFO sets gso_size to the size of the fragmentation |
4078 | * payload, i.e. the size of the L4 (UDP) header is already | 4074 | * payload, i.e. the size of the L4 (UDP) header is already |
4079 | * accounted for. | 4075 | * accounted for. |
4080 | */ | 4076 | */ |
4081 | return shinfo->gso_size; | 4077 | return thlen + shinfo->gso_size; |
4082 | } | 4078 | } |
4083 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); | 4079 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); |
4084 | 4080 | ||
diff --git a/net/core/tso.c b/net/core/tso.c index 8c3203c585b0..630b30b4fb53 100644 --- a/net/core/tso.c +++ b/net/core/tso.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/export.h> | 1 | #include <linux/export.h> |
2 | #include <net/ip.h> | 2 | #include <net/ip.h> |
3 | #include <net/tso.h> | 3 | #include <net/tso.h> |
4 | #include <asm/unaligned.h> | ||
4 | 5 | ||
5 | /* Calculate expected number of TX descriptors */ | 6 | /* Calculate expected number of TX descriptors */ |
6 | int tso_count_descs(struct sk_buff *skb) | 7 | int tso_count_descs(struct sk_buff *skb) |
@@ -23,7 +24,7 @@ void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, | |||
23 | iph->id = htons(tso->ip_id); | 24 | iph->id = htons(tso->ip_id); |
24 | iph->tot_len = htons(size + hdr_len - mac_hdr_len); | 25 | iph->tot_len = htons(size + hdr_len - mac_hdr_len); |
25 | tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb)); | 26 | tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb)); |
26 | tcph->seq = htonl(tso->tcp_seq); | 27 | put_unaligned_be32(tso->tcp_seq, &tcph->seq); |
27 | tso->ip_id++; | 28 | tso->ip_id++; |
28 | 29 | ||
29 | if (!is_last) { | 30 | if (!is_last) { |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index ca11d283bbeb..93ea80196f0e 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -1080,13 +1080,13 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) | |||
1080 | if (!app) | 1080 | if (!app) |
1081 | return -EMSGSIZE; | 1081 | return -EMSGSIZE; |
1082 | 1082 | ||
1083 | spin_lock(&dcb_lock); | 1083 | spin_lock_bh(&dcb_lock); |
1084 | list_for_each_entry(itr, &dcb_app_list, list) { | 1084 | list_for_each_entry(itr, &dcb_app_list, list) { |
1085 | if (itr->ifindex == netdev->ifindex) { | 1085 | if (itr->ifindex == netdev->ifindex) { |
1086 | err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app), | 1086 | err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app), |
1087 | &itr->app); | 1087 | &itr->app); |
1088 | if (err) { | 1088 | if (err) { |
1089 | spin_unlock(&dcb_lock); | 1089 | spin_unlock_bh(&dcb_lock); |
1090 | return -EMSGSIZE; | 1090 | return -EMSGSIZE; |
1091 | } | 1091 | } |
1092 | } | 1092 | } |
@@ -1097,7 +1097,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) | |||
1097 | else | 1097 | else |
1098 | dcbx = -EOPNOTSUPP; | 1098 | dcbx = -EOPNOTSUPP; |
1099 | 1099 | ||
1100 | spin_unlock(&dcb_lock); | 1100 | spin_unlock_bh(&dcb_lock); |
1101 | nla_nest_end(skb, app); | 1101 | nla_nest_end(skb, app); |
1102 | 1102 | ||
1103 | /* get peer info if available */ | 1103 | /* get peer info if available */ |
@@ -1234,7 +1234,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) | |||
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | /* local app */ | 1236 | /* local app */ |
1237 | spin_lock(&dcb_lock); | 1237 | spin_lock_bh(&dcb_lock); |
1238 | app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE); | 1238 | app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE); |
1239 | if (!app) | 1239 | if (!app) |
1240 | goto dcb_unlock; | 1240 | goto dcb_unlock; |
@@ -1271,7 +1271,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) | |||
1271 | else | 1271 | else |
1272 | dcbx = -EOPNOTSUPP; | 1272 | dcbx = -EOPNOTSUPP; |
1273 | 1273 | ||
1274 | spin_unlock(&dcb_lock); | 1274 | spin_unlock_bh(&dcb_lock); |
1275 | 1275 | ||
1276 | /* features flags */ | 1276 | /* features flags */ |
1277 | if (ops->getfeatcfg) { | 1277 | if (ops->getfeatcfg) { |
@@ -1326,7 +1326,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) | |||
1326 | return 0; | 1326 | return 0; |
1327 | 1327 | ||
1328 | dcb_unlock: | 1328 | dcb_unlock: |
1329 | spin_unlock(&dcb_lock); | 1329 | spin_unlock_bh(&dcb_lock); |
1330 | nla_put_failure: | 1330 | nla_put_failure: |
1331 | return err; | 1331 | return err; |
1332 | } | 1332 | } |
@@ -1762,10 +1762,10 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app) | |||
1762 | struct dcb_app_type *itr; | 1762 | struct dcb_app_type *itr; |
1763 | u8 prio = 0; | 1763 | u8 prio = 0; |
1764 | 1764 | ||
1765 | spin_lock(&dcb_lock); | 1765 | spin_lock_bh(&dcb_lock); |
1766 | if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) | 1766 | if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) |
1767 | prio = itr->app.priority; | 1767 | prio = itr->app.priority; |
1768 | spin_unlock(&dcb_lock); | 1768 | spin_unlock_bh(&dcb_lock); |
1769 | 1769 | ||
1770 | return prio; | 1770 | return prio; |
1771 | } | 1771 | } |
@@ -1789,7 +1789,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new) | |||
1789 | if (dev->dcbnl_ops->getdcbx) | 1789 | if (dev->dcbnl_ops->getdcbx) |
1790 | event.dcbx = dev->dcbnl_ops->getdcbx(dev); | 1790 | event.dcbx = dev->dcbnl_ops->getdcbx(dev); |
1791 | 1791 | ||
1792 | spin_lock(&dcb_lock); | 1792 | spin_lock_bh(&dcb_lock); |
1793 | /* Search for existing match and replace */ | 1793 | /* Search for existing match and replace */ |
1794 | if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) { | 1794 | if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) { |
1795 | if (new->priority) | 1795 | if (new->priority) |
@@ -1804,7 +1804,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new) | |||
1804 | if (new->priority) | 1804 | if (new->priority) |
1805 | err = dcb_app_add(new, dev->ifindex); | 1805 | err = dcb_app_add(new, dev->ifindex); |
1806 | out: | 1806 | out: |
1807 | spin_unlock(&dcb_lock); | 1807 | spin_unlock_bh(&dcb_lock); |
1808 | if (!err) | 1808 | if (!err) |
1809 | call_dcbevent_notifiers(DCB_APP_EVENT, &event); | 1809 | call_dcbevent_notifiers(DCB_APP_EVENT, &event); |
1810 | return err; | 1810 | return err; |
@@ -1823,10 +1823,10 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app) | |||
1823 | struct dcb_app_type *itr; | 1823 | struct dcb_app_type *itr; |
1824 | u8 prio = 0; | 1824 | u8 prio = 0; |
1825 | 1825 | ||
1826 | spin_lock(&dcb_lock); | 1826 | spin_lock_bh(&dcb_lock); |
1827 | if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) | 1827 | if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) |
1828 | prio |= 1 << itr->app.priority; | 1828 | prio |= 1 << itr->app.priority; |
1829 | spin_unlock(&dcb_lock); | 1829 | spin_unlock_bh(&dcb_lock); |
1830 | 1830 | ||
1831 | return prio; | 1831 | return prio; |
1832 | } | 1832 | } |
@@ -1850,7 +1850,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) | |||
1850 | if (dev->dcbnl_ops->getdcbx) | 1850 | if (dev->dcbnl_ops->getdcbx) |
1851 | event.dcbx = dev->dcbnl_ops->getdcbx(dev); | 1851 | event.dcbx = dev->dcbnl_ops->getdcbx(dev); |
1852 | 1852 | ||
1853 | spin_lock(&dcb_lock); | 1853 | spin_lock_bh(&dcb_lock); |
1854 | /* Search for existing match and abort if found */ | 1854 | /* Search for existing match and abort if found */ |
1855 | if (dcb_app_lookup(new, dev->ifindex, new->priority)) { | 1855 | if (dcb_app_lookup(new, dev->ifindex, new->priority)) { |
1856 | err = -EEXIST; | 1856 | err = -EEXIST; |
@@ -1859,7 +1859,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) | |||
1859 | 1859 | ||
1860 | err = dcb_app_add(new, dev->ifindex); | 1860 | err = dcb_app_add(new, dev->ifindex); |
1861 | out: | 1861 | out: |
1862 | spin_unlock(&dcb_lock); | 1862 | spin_unlock_bh(&dcb_lock); |
1863 | if (!err) | 1863 | if (!err) |
1864 | call_dcbevent_notifiers(DCB_APP_EVENT, &event); | 1864 | call_dcbevent_notifiers(DCB_APP_EVENT, &event); |
1865 | return err; | 1865 | return err; |
@@ -1882,7 +1882,7 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del) | |||
1882 | if (dev->dcbnl_ops->getdcbx) | 1882 | if (dev->dcbnl_ops->getdcbx) |
1883 | event.dcbx = dev->dcbnl_ops->getdcbx(dev); | 1883 | event.dcbx = dev->dcbnl_ops->getdcbx(dev); |
1884 | 1884 | ||
1885 | spin_lock(&dcb_lock); | 1885 | spin_lock_bh(&dcb_lock); |
1886 | /* Search for existing match and remove it. */ | 1886 | /* Search for existing match and remove it. */ |
1887 | if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) { | 1887 | if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) { |
1888 | list_del(&itr->list); | 1888 | list_del(&itr->list); |
@@ -1890,7 +1890,7 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del) | |||
1890 | err = 0; | 1890 | err = 0; |
1891 | } | 1891 | } |
1892 | 1892 | ||
1893 | spin_unlock(&dcb_lock); | 1893 | spin_unlock_bh(&dcb_lock); |
1894 | if (!err) | 1894 | if (!err) |
1895 | call_dcbevent_notifiers(DCB_APP_EVENT, &event); | 1895 | call_dcbevent_notifiers(DCB_APP_EVENT, &event); |
1896 | return err; | 1896 | return err; |
@@ -1902,12 +1902,12 @@ static void dcb_flushapp(void) | |||
1902 | struct dcb_app_type *app; | 1902 | struct dcb_app_type *app; |
1903 | struct dcb_app_type *tmp; | 1903 | struct dcb_app_type *tmp; |
1904 | 1904 | ||
1905 | spin_lock(&dcb_lock); | 1905 | spin_lock_bh(&dcb_lock); |
1906 | list_for_each_entry_safe(app, tmp, &dcb_app_list, list) { | 1906 | list_for_each_entry_safe(app, tmp, &dcb_app_list, list) { |
1907 | list_del(&app->list); | 1907 | list_del(&app->list); |
1908 | kfree(app); | 1908 | kfree(app); |
1909 | } | 1909 | } |
1910 | spin_unlock(&dcb_lock); | 1910 | spin_unlock_bh(&dcb_lock); |
1911 | } | 1911 | } |
1912 | 1912 | ||
1913 | static int __init dcbnl_init(void) | 1913 | static int __init dcbnl_init(void) |
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 22f34cf4cb27..6317b41c99b0 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -174,8 +174,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, | |||
174 | dst->rcv = brcm_netdev_ops.rcv; | 174 | dst->rcv = brcm_netdev_ops.rcv; |
175 | break; | 175 | break; |
176 | #endif | 176 | #endif |
177 | default: | 177 | case DSA_TAG_PROTO_NONE: |
178 | break; | 178 | break; |
179 | default: | ||
180 | ret = -ENOPROTOOPT; | ||
181 | goto out; | ||
179 | } | 182 | } |
180 | 183 | ||
181 | dst->tag_protocol = drv->tag_protocol; | 184 | dst->tag_protocol = drv->tag_protocol; |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 6d1817449c36..ab03e00ffe8f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -489,11 +489,14 @@ static void dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
489 | /* We could not connect to a designated PHY, so use the switch internal | 489 | /* We could not connect to a designated PHY, so use the switch internal |
490 | * MDIO bus instead | 490 | * MDIO bus instead |
491 | */ | 491 | */ |
492 | if (!p->phy) | 492 | if (!p->phy) { |
493 | p->phy = ds->slave_mii_bus->phy_map[p->port]; | 493 | p->phy = ds->slave_mii_bus->phy_map[p->port]; |
494 | else | 494 | phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, |
495 | p->phy_interface); | ||
496 | } else { | ||
495 | pr_info("attached PHY at address %d [%s]\n", | 497 | pr_info("attached PHY at address %d [%s]\n", |
496 | p->phy->addr, p->phy->drv->name); | 498 | p->phy->addr, p->phy->drv->name); |
499 | } | ||
497 | } | 500 | } |
498 | 501 | ||
499 | int dsa_slave_suspend(struct net_device *slave_dev) | 502 | int dsa_slave_suspend(struct net_device *slave_dev) |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 92db7a69f2b9..8b7fe5b03906 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1246,7 +1246,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
1246 | 1246 | ||
1247 | encap = SKB_GSO_CB(skb)->encap_level > 0; | 1247 | encap = SKB_GSO_CB(skb)->encap_level > 0; |
1248 | if (encap) | 1248 | if (encap) |
1249 | features = skb->dev->hw_enc_features & netif_skb_features(skb); | 1249 | features &= skb->dev->hw_enc_features; |
1250 | SKB_GSO_CB(skb)->encap_level += ihl; | 1250 | SKB_GSO_CB(skb)->encap_level += ihl; |
1251 | 1251 | ||
1252 | skb_reset_transport_header(skb); | 1252 | skb_reset_transport_header(skb); |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index f2e15738534d..8f7bd56955b0 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -62,6 +62,10 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) | |||
62 | else | 62 | else |
63 | res->tclassid = 0; | 63 | res->tclassid = 0; |
64 | #endif | 64 | #endif |
65 | |||
66 | if (err == -ESRCH) | ||
67 | err = -ENETUNREACH; | ||
68 | |||
65 | return err; | 69 | return err; |
66 | } | 70 | } |
67 | EXPORT_SYMBOL_GPL(__fib_lookup); | 71 | EXPORT_SYMBOL_GPL(__fib_lookup); |
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 32e78924e246..606c520ffd5a 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
@@ -133,6 +133,8 @@ static int fou_gro_complete(struct sk_buff *skb, int nhoff) | |||
133 | int err = -ENOSYS; | 133 | int err = -ENOSYS; |
134 | const struct net_offload **offloads; | 134 | const struct net_offload **offloads; |
135 | 135 | ||
136 | udp_tunnel_gro_complete(skb, nhoff); | ||
137 | |||
136 | rcu_read_lock(); | 138 | rcu_read_lock(); |
137 | offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; | 139 | offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; |
138 | ops = rcu_dereference(offloads[proto]); | 140 | ops = rcu_dereference(offloads[proto]); |
diff --git a/net/ipv4/geneve.c b/net/ipv4/geneve.c index 065cd94c640c..dedb21e99914 100644 --- a/net/ipv4/geneve.c +++ b/net/ipv4/geneve.c | |||
@@ -144,6 +144,8 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt, | |||
144 | gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); | 144 | gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); |
145 | geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); | 145 | geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); |
146 | 146 | ||
147 | skb_set_inner_protocol(skb, htons(ETH_P_TEB)); | ||
148 | |||
147 | return udp_tunnel_xmit_skb(gs->sock, rt, skb, src, dst, | 149 | return udp_tunnel_xmit_skb(gs->sock, rt, skb, src, dst, |
148 | tos, ttl, df, src_port, dst_port, xnet); | 150 | tos, ttl, df, src_port, dst_port, xnet); |
149 | } | 151 | } |
@@ -364,6 +366,7 @@ late_initcall(geneve_init_module); | |||
364 | static void __exit geneve_cleanup_module(void) | 366 | static void __exit geneve_cleanup_module(void) |
365 | { | 367 | { |
366 | destroy_workqueue(geneve_wq); | 368 | destroy_workqueue(geneve_wq); |
369 | unregister_pernet_subsys(&geneve_net_ops); | ||
367 | } | 370 | } |
368 | module_exit(geneve_cleanup_module); | 371 | module_exit(geneve_cleanup_module); |
369 | 372 | ||
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index ccda09628de7..bb5947b0ce2d 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -47,7 +47,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
47 | 47 | ||
48 | greh = (struct gre_base_hdr *)skb_transport_header(skb); | 48 | greh = (struct gre_base_hdr *)skb_transport_header(skb); |
49 | 49 | ||
50 | ghl = skb_inner_network_header(skb) - skb_transport_header(skb); | 50 | ghl = skb_inner_mac_header(skb) - skb_transport_header(skb); |
51 | if (unlikely(ghl < sizeof(*greh))) | 51 | if (unlikely(ghl < sizeof(*greh))) |
52 | goto out; | 52 | goto out; |
53 | 53 | ||
@@ -68,7 +68,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
68 | skb->mac_len = skb_inner_network_offset(skb); | 68 | skb->mac_len = skb_inner_network_offset(skb); |
69 | 69 | ||
70 | /* segment inner packet. */ | 70 | /* segment inner packet. */ |
71 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | 71 | enc_features = skb->dev->hw_enc_features & features; |
72 | segs = skb_mac_gso_segment(skb, enc_features); | 72 | segs = skb_mac_gso_segment(skb, enc_features); |
73 | if (IS_ERR_OR_NULL(segs)) { | 73 | if (IS_ERR_OR_NULL(segs)) { |
74 | skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); | 74 | skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index fb70e3ecc3e4..bb15d0e03d4f 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -318,9 +318,7 @@ igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted) | |||
318 | return scount; | 318 | return scount; |
319 | } | 319 | } |
320 | 320 | ||
321 | #define igmp_skb_size(skb) (*(unsigned int *)((skb)->cb)) | 321 | static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu) |
322 | |||
323 | static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | ||
324 | { | 322 | { |
325 | struct sk_buff *skb; | 323 | struct sk_buff *skb; |
326 | struct rtable *rt; | 324 | struct rtable *rt; |
@@ -330,6 +328,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
330 | struct flowi4 fl4; | 328 | struct flowi4 fl4; |
331 | int hlen = LL_RESERVED_SPACE(dev); | 329 | int hlen = LL_RESERVED_SPACE(dev); |
332 | int tlen = dev->needed_tailroom; | 330 | int tlen = dev->needed_tailroom; |
331 | unsigned int size = mtu; | ||
333 | 332 | ||
334 | while (1) { | 333 | while (1) { |
335 | skb = alloc_skb(size + hlen + tlen, | 334 | skb = alloc_skb(size + hlen + tlen, |
@@ -341,7 +340,6 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
341 | return NULL; | 340 | return NULL; |
342 | } | 341 | } |
343 | skb->priority = TC_PRIO_CONTROL; | 342 | skb->priority = TC_PRIO_CONTROL; |
344 | igmp_skb_size(skb) = size; | ||
345 | 343 | ||
346 | rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0, | 344 | rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0, |
347 | 0, 0, | 345 | 0, 0, |
@@ -354,6 +352,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
354 | skb_dst_set(skb, &rt->dst); | 352 | skb_dst_set(skb, &rt->dst); |
355 | skb->dev = dev; | 353 | skb->dev = dev; |
356 | 354 | ||
355 | skb->reserved_tailroom = skb_end_offset(skb) - | ||
356 | min(mtu, skb_end_offset(skb)); | ||
357 | skb_reserve(skb, hlen); | 357 | skb_reserve(skb, hlen); |
358 | 358 | ||
359 | skb_reset_network_header(skb); | 359 | skb_reset_network_header(skb); |
@@ -423,8 +423,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc, | |||
423 | return skb; | 423 | return skb; |
424 | } | 424 | } |
425 | 425 | ||
426 | #define AVAILABLE(skb) ((skb) ? ((skb)->dev ? igmp_skb_size(skb) - (skb)->len : \ | 426 | #define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0) |
427 | skb_tailroom(skb)) : 0) | ||
428 | 427 | ||
429 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, | 428 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, |
430 | int type, int gdeleted, int sdeleted) | 429 | int type, int gdeleted, int sdeleted) |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 9eb89f3f0ee4..19419b60cb37 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -146,7 +146,6 @@ evict_again: | |||
146 | atomic_inc(&fq->refcnt); | 146 | atomic_inc(&fq->refcnt); |
147 | spin_unlock(&hb->chain_lock); | 147 | spin_unlock(&hb->chain_lock); |
148 | del_timer_sync(&fq->timer); | 148 | del_timer_sync(&fq->timer); |
149 | WARN_ON(atomic_read(&fq->refcnt) != 1); | ||
150 | inet_frag_put(fq, f); | 149 | inet_frag_put(fq, f); |
151 | goto evict_again; | 150 | goto evict_again; |
152 | } | 151 | } |
@@ -285,7 +284,8 @@ static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | |||
285 | struct inet_frag_bucket *hb; | 284 | struct inet_frag_bucket *hb; |
286 | 285 | ||
287 | hb = get_frag_bucket_locked(fq, f); | 286 | hb = get_frag_bucket_locked(fq, f); |
288 | hlist_del(&fq->list); | 287 | if (!(fq->flags & INET_FRAG_EVICTED)) |
288 | hlist_del(&fq->list); | ||
289 | spin_unlock(&hb->chain_lock); | 289 | spin_unlock(&hb->chain_lock); |
290 | } | 290 | } |
291 | 291 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 88e5ef2c7f51..bc6471d4abcd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -231,7 +231,7 @@ static int ip_finish_output_gso(struct sk_buff *skb) | |||
231 | */ | 231 | */ |
232 | features = netif_skb_features(skb); | 232 | features = netif_skb_features(skb); |
233 | segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); | 233 | segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); |
234 | if (IS_ERR(segs)) { | 234 | if (IS_ERR_OR_NULL(segs)) { |
235 | kfree_skb(skb); | 235 | kfree_skb(skb); |
236 | return -ENOMEM; | 236 | return -ENOMEM; |
237 | } | 237 | } |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index c373a9ad4555..9daf2177dc00 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -195,7 +195,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, | |||
195 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { | 195 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { |
196 | if (!CMSG_OK(msg, cmsg)) | 196 | if (!CMSG_OK(msg, cmsg)) |
197 | return -EINVAL; | 197 | return -EINVAL; |
198 | #if defined(CONFIG_IPV6) | 198 | #if IS_ENABLED(CONFIG_IPV6) |
199 | if (allow_ipv6 && | 199 | if (allow_ipv6 && |
200 | cmsg->cmsg_level == SOL_IPV6 && | 200 | cmsg->cmsg_level == SOL_IPV6 && |
201 | cmsg->cmsg_type == IPV6_PKTINFO) { | 201 | cmsg->cmsg_type == IPV6_PKTINFO) { |
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index b023b4eb1a96..1baaa83dfe5c 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c | |||
@@ -6,48 +6,45 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | ||
9 | #include <net/ip.h> | 10 | #include <net/ip.h> |
10 | #include <net/tcp.h> | 11 | #include <net/tcp.h> |
11 | #include <net/route.h> | 12 | #include <net/route.h> |
12 | #include <net/dst.h> | 13 | #include <net/dst.h> |
13 | #include <linux/netfilter_ipv4.h> | 14 | #include <linux/netfilter_ipv4.h> |
15 | #include <net/netfilter/ipv4/nf_reject.h> | ||
14 | 16 | ||
15 | /* Send RST reply */ | 17 | const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, |
16 | void nf_send_reset(struct sk_buff *oldskb, int hook) | 18 | struct tcphdr *_oth, int hook) |
17 | { | 19 | { |
18 | struct sk_buff *nskb; | ||
19 | const struct iphdr *oiph; | ||
20 | struct iphdr *niph; | ||
21 | const struct tcphdr *oth; | 20 | const struct tcphdr *oth; |
22 | struct tcphdr _otcph, *tcph; | ||
23 | 21 | ||
24 | /* IP header checks: fragment. */ | 22 | /* IP header checks: fragment. */ |
25 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | 23 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) |
26 | return; | 24 | return NULL; |
27 | 25 | ||
28 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), | 26 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), |
29 | sizeof(_otcph), &_otcph); | 27 | sizeof(struct tcphdr), _oth); |
30 | if (oth == NULL) | 28 | if (oth == NULL) |
31 | return; | 29 | return NULL; |
32 | 30 | ||
33 | /* No RST for RST. */ | 31 | /* No RST for RST. */ |
34 | if (oth->rst) | 32 | if (oth->rst) |
35 | return; | 33 | return NULL; |
36 | |||
37 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
38 | return; | ||
39 | 34 | ||
40 | /* Check checksum */ | 35 | /* Check checksum */ |
41 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | 36 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) |
42 | return; | 37 | return NULL; |
43 | oiph = ip_hdr(oldskb); | ||
44 | 38 | ||
45 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | 39 | return oth; |
46 | LL_MAX_HEADER, GFP_ATOMIC); | 40 | } |
47 | if (!nskb) | 41 | EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_get); |
48 | return; | ||
49 | 42 | ||
50 | skb_reserve(nskb, LL_MAX_HEADER); | 43 | struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb, |
44 | const struct sk_buff *oldskb, | ||
45 | __be16 protocol, int ttl) | ||
46 | { | ||
47 | struct iphdr *niph, *oiph = ip_hdr(oldskb); | ||
51 | 48 | ||
52 | skb_reset_network_header(nskb); | 49 | skb_reset_network_header(nskb); |
53 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); | 50 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); |
@@ -56,10 +53,23 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
56 | niph->tos = 0; | 53 | niph->tos = 0; |
57 | niph->id = 0; | 54 | niph->id = 0; |
58 | niph->frag_off = htons(IP_DF); | 55 | niph->frag_off = htons(IP_DF); |
59 | niph->protocol = IPPROTO_TCP; | 56 | niph->protocol = protocol; |
60 | niph->check = 0; | 57 | niph->check = 0; |
61 | niph->saddr = oiph->daddr; | 58 | niph->saddr = oiph->daddr; |
62 | niph->daddr = oiph->saddr; | 59 | niph->daddr = oiph->saddr; |
60 | niph->ttl = ttl; | ||
61 | |||
62 | nskb->protocol = htons(ETH_P_IP); | ||
63 | |||
64 | return niph; | ||
65 | } | ||
66 | EXPORT_SYMBOL_GPL(nf_reject_iphdr_put); | ||
67 | |||
68 | void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, | ||
69 | const struct tcphdr *oth) | ||
70 | { | ||
71 | struct iphdr *niph = ip_hdr(nskb); | ||
72 | struct tcphdr *tcph; | ||
63 | 73 | ||
64 | skb_reset_transport_header(nskb); | 74 | skb_reset_transport_header(nskb); |
65 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | 75 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); |
@@ -68,9 +78,9 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
68 | tcph->dest = oth->source; | 78 | tcph->dest = oth->source; |
69 | tcph->doff = sizeof(struct tcphdr) / 4; | 79 | tcph->doff = sizeof(struct tcphdr) / 4; |
70 | 80 | ||
71 | if (oth->ack) | 81 | if (oth->ack) { |
72 | tcph->seq = oth->ack_seq; | 82 | tcph->seq = oth->ack_seq; |
73 | else { | 83 | } else { |
74 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + | 84 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + |
75 | oldskb->len - ip_hdrlen(oldskb) - | 85 | oldskb->len - ip_hdrlen(oldskb) - |
76 | (oth->doff << 2)); | 86 | (oth->doff << 2)); |
@@ -83,16 +93,43 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
83 | nskb->ip_summed = CHECKSUM_PARTIAL; | 93 | nskb->ip_summed = CHECKSUM_PARTIAL; |
84 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | 94 | nskb->csum_start = (unsigned char *)tcph - nskb->head; |
85 | nskb->csum_offset = offsetof(struct tcphdr, check); | 95 | nskb->csum_offset = offsetof(struct tcphdr, check); |
96 | } | ||
97 | EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put); | ||
98 | |||
99 | /* Send RST reply */ | ||
100 | void nf_send_reset(struct sk_buff *oldskb, int hook) | ||
101 | { | ||
102 | struct sk_buff *nskb; | ||
103 | const struct iphdr *oiph; | ||
104 | struct iphdr *niph; | ||
105 | const struct tcphdr *oth; | ||
106 | struct tcphdr _oth; | ||
107 | |||
108 | oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); | ||
109 | if (!oth) | ||
110 | return; | ||
111 | |||
112 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
113 | return; | ||
114 | |||
115 | oiph = ip_hdr(oldskb); | ||
116 | |||
117 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | ||
118 | LL_MAX_HEADER, GFP_ATOMIC); | ||
119 | if (!nskb) | ||
120 | return; | ||
86 | 121 | ||
87 | /* ip_route_me_harder expects skb->dst to be set */ | 122 | /* ip_route_me_harder expects skb->dst to be set */ |
88 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | 123 | skb_dst_set_noref(nskb, skb_dst(oldskb)); |
89 | 124 | ||
90 | nskb->protocol = htons(ETH_P_IP); | 125 | skb_reserve(nskb, LL_MAX_HEADER); |
126 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, | ||
127 | ip4_dst_hoplimit(skb_dst(nskb))); | ||
128 | nf_reject_ip_tcphdr_put(nskb, oldskb, oth); | ||
129 | |||
91 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) | 130 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) |
92 | goto free_nskb; | 131 | goto free_nskb; |
93 | 132 | ||
94 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | ||
95 | |||
96 | /* "Never happens" */ | 133 | /* "Never happens" */ |
97 | if (nskb->len > dst_mtu(skb_dst(nskb))) | 134 | if (nskb->len > dst_mtu(skb_dst(nskb))) |
98 | goto free_nskb; | 135 | goto free_nskb; |
@@ -125,3 +162,5 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
125 | kfree_skb(nskb); | 162 | kfree_skb(nskb); |
126 | } | 163 | } |
127 | EXPORT_SYMBOL_GPL(nf_send_reset); | 164 | EXPORT_SYMBOL_GPL(nf_send_reset); |
165 | |||
166 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c index 1c636d6b5b50..665de06561cd 100644 --- a/net/ipv4/netfilter/nft_masq_ipv4.c +++ b/net/ipv4/netfilter/nft_masq_ipv4.c | |||
@@ -24,6 +24,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, | |||
24 | struct nf_nat_range range; | 24 | struct nf_nat_range range; |
25 | unsigned int verdict; | 25 | unsigned int verdict; |
26 | 26 | ||
27 | memset(&range, 0, sizeof(range)); | ||
27 | range.flags = priv->flags; | 28 | range.flags = priv->flags; |
28 | 29 | ||
29 | verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, | 30 | verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, |
@@ -39,6 +40,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = { | |||
39 | .eval = nft_masq_ipv4_eval, | 40 | .eval = nft_masq_ipv4_eval, |
40 | .init = nft_masq_init, | 41 | .init = nft_masq_init, |
41 | .dump = nft_masq_dump, | 42 | .dump = nft_masq_dump, |
43 | .validate = nft_masq_validate, | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { | 46 | static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 2d4ae469b471..6a2155b02602 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1798,6 +1798,7 @@ local_input: | |||
1798 | no_route: | 1798 | no_route: |
1799 | RT_CACHE_STAT_INC(in_no_route); | 1799 | RT_CACHE_STAT_INC(in_no_route); |
1800 | res.type = RTN_UNREACHABLE; | 1800 | res.type = RTN_UNREACHABLE; |
1801 | res.fi = NULL; | ||
1801 | goto local_input; | 1802 | goto local_input; |
1802 | 1803 | ||
1803 | /* | 1804 | /* |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1bec4e76d88c..39ec0c379545 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2868,61 +2868,42 @@ EXPORT_SYMBOL(compat_tcp_getsockopt); | |||
2868 | #endif | 2868 | #endif |
2869 | 2869 | ||
2870 | #ifdef CONFIG_TCP_MD5SIG | 2870 | #ifdef CONFIG_TCP_MD5SIG |
2871 | static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly; | 2871 | static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool); |
2872 | static DEFINE_MUTEX(tcp_md5sig_mutex); | 2872 | static DEFINE_MUTEX(tcp_md5sig_mutex); |
2873 | 2873 | static bool tcp_md5sig_pool_populated = false; | |
2874 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool) | ||
2875 | { | ||
2876 | int cpu; | ||
2877 | |||
2878 | for_each_possible_cpu(cpu) { | ||
2879 | struct tcp_md5sig_pool *p = per_cpu_ptr(pool, cpu); | ||
2880 | |||
2881 | if (p->md5_desc.tfm) | ||
2882 | crypto_free_hash(p->md5_desc.tfm); | ||
2883 | } | ||
2884 | free_percpu(pool); | ||
2885 | } | ||
2886 | 2874 | ||
2887 | static void __tcp_alloc_md5sig_pool(void) | 2875 | static void __tcp_alloc_md5sig_pool(void) |
2888 | { | 2876 | { |
2889 | int cpu; | 2877 | int cpu; |
2890 | struct tcp_md5sig_pool __percpu *pool; | ||
2891 | |||
2892 | pool = alloc_percpu(struct tcp_md5sig_pool); | ||
2893 | if (!pool) | ||
2894 | return; | ||
2895 | 2878 | ||
2896 | for_each_possible_cpu(cpu) { | 2879 | for_each_possible_cpu(cpu) { |
2897 | struct crypto_hash *hash; | 2880 | if (!per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm) { |
2898 | 2881 | struct crypto_hash *hash; | |
2899 | hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); | ||
2900 | if (IS_ERR_OR_NULL(hash)) | ||
2901 | goto out_free; | ||
2902 | 2882 | ||
2903 | per_cpu_ptr(pool, cpu)->md5_desc.tfm = hash; | 2883 | hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); |
2884 | if (IS_ERR_OR_NULL(hash)) | ||
2885 | return; | ||
2886 | per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash; | ||
2887 | } | ||
2904 | } | 2888 | } |
2905 | /* before setting tcp_md5sig_pool, we must commit all writes | 2889 | /* before setting tcp_md5sig_pool_populated, we must commit all writes |
2906 | * to memory. See ACCESS_ONCE() in tcp_get_md5sig_pool() | 2890 | * to memory. See smp_rmb() in tcp_get_md5sig_pool() |
2907 | */ | 2891 | */ |
2908 | smp_wmb(); | 2892 | smp_wmb(); |
2909 | tcp_md5sig_pool = pool; | 2893 | tcp_md5sig_pool_populated = true; |
2910 | return; | ||
2911 | out_free: | ||
2912 | __tcp_free_md5sig_pool(pool); | ||
2913 | } | 2894 | } |
2914 | 2895 | ||
2915 | bool tcp_alloc_md5sig_pool(void) | 2896 | bool tcp_alloc_md5sig_pool(void) |
2916 | { | 2897 | { |
2917 | if (unlikely(!tcp_md5sig_pool)) { | 2898 | if (unlikely(!tcp_md5sig_pool_populated)) { |
2918 | mutex_lock(&tcp_md5sig_mutex); | 2899 | mutex_lock(&tcp_md5sig_mutex); |
2919 | 2900 | ||
2920 | if (!tcp_md5sig_pool) | 2901 | if (!tcp_md5sig_pool_populated) |
2921 | __tcp_alloc_md5sig_pool(); | 2902 | __tcp_alloc_md5sig_pool(); |
2922 | 2903 | ||
2923 | mutex_unlock(&tcp_md5sig_mutex); | 2904 | mutex_unlock(&tcp_md5sig_mutex); |
2924 | } | 2905 | } |
2925 | return tcp_md5sig_pool != NULL; | 2906 | return tcp_md5sig_pool_populated; |
2926 | } | 2907 | } |
2927 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); | 2908 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); |
2928 | 2909 | ||
@@ -2936,13 +2917,13 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool); | |||
2936 | */ | 2917 | */ |
2937 | struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) | 2918 | struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) |
2938 | { | 2919 | { |
2939 | struct tcp_md5sig_pool __percpu *p; | ||
2940 | |||
2941 | local_bh_disable(); | 2920 | local_bh_disable(); |
2942 | p = ACCESS_ONCE(tcp_md5sig_pool); | ||
2943 | if (p) | ||
2944 | return raw_cpu_ptr(p); | ||
2945 | 2921 | ||
2922 | if (tcp_md5sig_pool_populated) { | ||
2923 | /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */ | ||
2924 | smp_rmb(); | ||
2925 | return this_cpu_ptr(&tcp_md5sig_pool); | ||
2926 | } | ||
2946 | local_bh_enable(); | 2927 | local_bh_enable(); |
2947 | return NULL; | 2928 | return NULL; |
2948 | } | 2929 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a12b455928e5..d107ee246a1d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2315,6 +2315,35 @@ static inline bool tcp_packet_delayed(const struct tcp_sock *tp) | |||
2315 | 2315 | ||
2316 | /* Undo procedures. */ | 2316 | /* Undo procedures. */ |
2317 | 2317 | ||
2318 | /* We can clear retrans_stamp when there are no retransmissions in the | ||
2319 | * window. It would seem that it is trivially available for us in | ||
2320 | * tp->retrans_out, however, that kind of assumptions doesn't consider | ||
2321 | * what will happen if errors occur when sending retransmission for the | ||
2322 | * second time. ...It could the that such segment has only | ||
2323 | * TCPCB_EVER_RETRANS set at the present time. It seems that checking | ||
2324 | * the head skb is enough except for some reneging corner cases that | ||
2325 | * are not worth the effort. | ||
2326 | * | ||
2327 | * Main reason for all this complexity is the fact that connection dying | ||
2328 | * time now depends on the validity of the retrans_stamp, in particular, | ||
2329 | * that successive retransmissions of a segment must not advance | ||
2330 | * retrans_stamp under any conditions. | ||
2331 | */ | ||
2332 | static bool tcp_any_retrans_done(const struct sock *sk) | ||
2333 | { | ||
2334 | const struct tcp_sock *tp = tcp_sk(sk); | ||
2335 | struct sk_buff *skb; | ||
2336 | |||
2337 | if (tp->retrans_out) | ||
2338 | return true; | ||
2339 | |||
2340 | skb = tcp_write_queue_head(sk); | ||
2341 | if (unlikely(skb && TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS)) | ||
2342 | return true; | ||
2343 | |||
2344 | return false; | ||
2345 | } | ||
2346 | |||
2318 | #if FASTRETRANS_DEBUG > 1 | 2347 | #if FASTRETRANS_DEBUG > 1 |
2319 | static void DBGUNDO(struct sock *sk, const char *msg) | 2348 | static void DBGUNDO(struct sock *sk, const char *msg) |
2320 | { | 2349 | { |
@@ -2410,6 +2439,8 @@ static bool tcp_try_undo_recovery(struct sock *sk) | |||
2410 | * is ACKed. For Reno it is MUST to prevent false | 2439 | * is ACKed. For Reno it is MUST to prevent false |
2411 | * fast retransmits (RFC2582). SACK TCP is safe. */ | 2440 | * fast retransmits (RFC2582). SACK TCP is safe. */ |
2412 | tcp_moderate_cwnd(tp); | 2441 | tcp_moderate_cwnd(tp); |
2442 | if (!tcp_any_retrans_done(sk)) | ||
2443 | tp->retrans_stamp = 0; | ||
2413 | return true; | 2444 | return true; |
2414 | } | 2445 | } |
2415 | tcp_set_ca_state(sk, TCP_CA_Open); | 2446 | tcp_set_ca_state(sk, TCP_CA_Open); |
@@ -2430,35 +2461,6 @@ static bool tcp_try_undo_dsack(struct sock *sk) | |||
2430 | return false; | 2461 | return false; |
2431 | } | 2462 | } |
2432 | 2463 | ||
2433 | /* We can clear retrans_stamp when there are no retransmissions in the | ||
2434 | * window. It would seem that it is trivially available for us in | ||
2435 | * tp->retrans_out, however, that kind of assumptions doesn't consider | ||
2436 | * what will happen if errors occur when sending retransmission for the | ||
2437 | * second time. ...It could the that such segment has only | ||
2438 | * TCPCB_EVER_RETRANS set at the present time. It seems that checking | ||
2439 | * the head skb is enough except for some reneging corner cases that | ||
2440 | * are not worth the effort. | ||
2441 | * | ||
2442 | * Main reason for all this complexity is the fact that connection dying | ||
2443 | * time now depends on the validity of the retrans_stamp, in particular, | ||
2444 | * that successive retransmissions of a segment must not advance | ||
2445 | * retrans_stamp under any conditions. | ||
2446 | */ | ||
2447 | static bool tcp_any_retrans_done(const struct sock *sk) | ||
2448 | { | ||
2449 | const struct tcp_sock *tp = tcp_sk(sk); | ||
2450 | struct sk_buff *skb; | ||
2451 | |||
2452 | if (tp->retrans_out) | ||
2453 | return true; | ||
2454 | |||
2455 | skb = tcp_write_queue_head(sk); | ||
2456 | if (unlikely(skb && TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS)) | ||
2457 | return true; | ||
2458 | |||
2459 | return false; | ||
2460 | } | ||
2461 | |||
2462 | /* Undo during loss recovery after partial ACK or using F-RTO. */ | 2464 | /* Undo during loss recovery after partial ACK or using F-RTO. */ |
2463 | static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) | 2465 | static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) |
2464 | { | 2466 | { |
@@ -5229,7 +5231,7 @@ slow_path: | |||
5229 | if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb)) | 5231 | if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb)) |
5230 | goto csum_error; | 5232 | goto csum_error; |
5231 | 5233 | ||
5232 | if (!th->ack && !th->rst) | 5234 | if (!th->ack && !th->rst && !th->syn) |
5233 | goto discard; | 5235 | goto discard; |
5234 | 5236 | ||
5235 | /* | 5237 | /* |
@@ -5648,7 +5650,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5648 | goto discard; | 5650 | goto discard; |
5649 | } | 5651 | } |
5650 | 5652 | ||
5651 | if (!th->ack && !th->rst) | 5653 | if (!th->ack && !th->rst && !th->syn) |
5652 | goto discard; | 5654 | goto discard; |
5653 | 5655 | ||
5654 | if (!tcp_validate_incoming(sk, skb, th, 0)) | 5656 | if (!tcp_validate_incoming(sk, skb, th, 0)) |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 94d1a7757ff7..9c7d7621466b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -206,8 +206,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
206 | inet->inet_dport = usin->sin_port; | 206 | inet->inet_dport = usin->sin_port; |
207 | inet->inet_daddr = daddr; | 207 | inet->inet_daddr = daddr; |
208 | 208 | ||
209 | inet_set_txhash(sk); | ||
210 | |||
211 | inet_csk(sk)->icsk_ext_hdr_len = 0; | 209 | inet_csk(sk)->icsk_ext_hdr_len = 0; |
212 | if (inet_opt) | 210 | if (inet_opt) |
213 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; | 211 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
@@ -224,6 +222,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
224 | if (err) | 222 | if (err) |
225 | goto failure; | 223 | goto failure; |
226 | 224 | ||
225 | inet_set_txhash(sk); | ||
226 | |||
227 | rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, | 227 | rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, |
228 | inet->inet_sport, inet->inet_dport, sk); | 228 | inet->inet_sport, inet->inet_dport, sk); |
229 | if (IS_ERR(rt)) { | 229 | if (IS_ERR(rt)) { |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3af21296d967..a3d453b94747 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2126,7 +2126,7 @@ bool tcp_schedule_loss_probe(struct sock *sk) | |||
2126 | static bool skb_still_in_host_queue(const struct sock *sk, | 2126 | static bool skb_still_in_host_queue(const struct sock *sk, |
2127 | const struct sk_buff *skb) | 2127 | const struct sk_buff *skb) |
2128 | { | 2128 | { |
2129 | if (unlikely(skb_fclone_busy(skb))) { | 2129 | if (unlikely(skb_fclone_busy(sk, skb))) { |
2130 | NET_INC_STATS_BH(sock_net(sk), | 2130 | NET_INC_STATS_BH(sock_net(sk), |
2131 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); | 2131 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); |
2132 | return true; | 2132 | return true; |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 507310ef4b56..6480cea7aa53 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -58,7 +58,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, | |||
58 | skb->encap_hdr_csum = 1; | 58 | skb->encap_hdr_csum = 1; |
59 | 59 | ||
60 | /* segment inner packet. */ | 60 | /* segment inner packet. */ |
61 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | 61 | enc_features = skb->dev->hw_enc_features & features; |
62 | segs = gso_inner_segment(skb, enc_features); | 62 | segs = gso_inner_segment(skb, enc_features); |
63 | if (IS_ERR_OR_NULL(segs)) { | 63 | if (IS_ERR_OR_NULL(segs)) { |
64 | skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, | 64 | skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 725c763270a0..0169ccf5aa4f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -4531,6 +4531,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4531 | } | 4531 | } |
4532 | 4532 | ||
4533 | write_unlock_bh(&idev->lock); | 4533 | write_unlock_bh(&idev->lock); |
4534 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | ||
4534 | addrconf_verify_rtnl(); | 4535 | addrconf_verify_rtnl(); |
4535 | return 0; | 4536 | return 0; |
4536 | } | 4537 | } |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 12c3c8ef3849..4564e1fca3eb 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -961,8 +961,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) | |||
961 | else | 961 | else |
962 | dev->flags &= ~IFF_POINTOPOINT; | 962 | dev->flags &= ~IFF_POINTOPOINT; |
963 | 963 | ||
964 | dev->iflink = p->link; | ||
965 | |||
966 | /* Precalculate GRE options length */ | 964 | /* Precalculate GRE options length */ |
967 | if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { | 965 | if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { |
968 | if (t->parms.o_flags&GRE_CSUM) | 966 | if (t->parms.o_flags&GRE_CSUM) |
@@ -1272,6 +1270,7 @@ static int ip6gre_tunnel_init(struct net_device *dev) | |||
1272 | u64_stats_init(&ip6gre_tunnel_stats->syncp); | 1270 | u64_stats_init(&ip6gre_tunnel_stats->syncp); |
1273 | } | 1271 | } |
1274 | 1272 | ||
1273 | dev->iflink = tunnel->parms.link; | ||
1275 | 1274 | ||
1276 | return 0; | 1275 | return 0; |
1277 | } | 1276 | } |
@@ -1481,6 +1480,8 @@ static int ip6gre_tap_init(struct net_device *dev) | |||
1481 | if (!dev->tstats) | 1480 | if (!dev->tstats) |
1482 | return -ENOMEM; | 1481 | return -ENOMEM; |
1483 | 1482 | ||
1483 | dev->iflink = tunnel->parms.link; | ||
1484 | |||
1484 | return 0; | 1485 | return 0; |
1485 | } | 1486 | } |
1486 | 1487 | ||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 91014d32488d..a071563a7e6e 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -90,7 +90,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
90 | 90 | ||
91 | encap = SKB_GSO_CB(skb)->encap_level > 0; | 91 | encap = SKB_GSO_CB(skb)->encap_level > 0; |
92 | if (encap) | 92 | if (encap) |
93 | features = skb->dev->hw_enc_features & netif_skb_features(skb); | 93 | features &= skb->dev->hw_enc_features; |
94 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); | 94 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); |
95 | 95 | ||
96 | ipv6h = ipv6_hdr(skb); | 96 | ipv6h = ipv6_hdr(skb); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9409887fb664..9cb94cfa0ae7 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -272,9 +272,6 @@ static int ip6_tnl_create2(struct net_device *dev) | |||
272 | int err; | 272 | int err; |
273 | 273 | ||
274 | t = netdev_priv(dev); | 274 | t = netdev_priv(dev); |
275 | err = ip6_tnl_dev_init(dev); | ||
276 | if (err < 0) | ||
277 | goto out; | ||
278 | 275 | ||
279 | err = register_netdevice(dev); | 276 | err = register_netdevice(dev); |
280 | if (err < 0) | 277 | if (err < 0) |
@@ -1462,6 +1459,7 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) | |||
1462 | 1459 | ||
1463 | 1460 | ||
1464 | static const struct net_device_ops ip6_tnl_netdev_ops = { | 1461 | static const struct net_device_ops ip6_tnl_netdev_ops = { |
1462 | .ndo_init = ip6_tnl_dev_init, | ||
1465 | .ndo_uninit = ip6_tnl_dev_uninit, | 1463 | .ndo_uninit = ip6_tnl_dev_uninit, |
1466 | .ndo_start_xmit = ip6_tnl_xmit, | 1464 | .ndo_start_xmit = ip6_tnl_xmit, |
1467 | .ndo_do_ioctl = ip6_tnl_ioctl, | 1465 | .ndo_do_ioctl = ip6_tnl_ioctl, |
@@ -1546,16 +1544,10 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) | |||
1546 | struct ip6_tnl *t = netdev_priv(dev); | 1544 | struct ip6_tnl *t = netdev_priv(dev); |
1547 | struct net *net = dev_net(dev); | 1545 | struct net *net = dev_net(dev); |
1548 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1546 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
1549 | int err = ip6_tnl_dev_init_gen(dev); | ||
1550 | |||
1551 | if (err) | ||
1552 | return err; | ||
1553 | 1547 | ||
1554 | t->parms.proto = IPPROTO_IPV6; | 1548 | t->parms.proto = IPPROTO_IPV6; |
1555 | dev_hold(dev); | 1549 | dev_hold(dev); |
1556 | 1550 | ||
1557 | ip6_tnl_link_config(t); | ||
1558 | |||
1559 | rcu_assign_pointer(ip6n->tnls_wc[0], t); | 1551 | rcu_assign_pointer(ip6n->tnls_wc[0], t); |
1560 | return 0; | 1552 | return 0; |
1561 | } | 1553 | } |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index d440bb585524..31089d153fd3 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -172,10 +172,6 @@ static int vti6_tnl_create2(struct net_device *dev) | |||
172 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); | 172 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); |
173 | int err; | 173 | int err; |
174 | 174 | ||
175 | err = vti6_dev_init(dev); | ||
176 | if (err < 0) | ||
177 | goto out; | ||
178 | |||
179 | err = register_netdevice(dev); | 175 | err = register_netdevice(dev); |
180 | if (err < 0) | 176 | if (err < 0) |
181 | goto out; | 177 | goto out; |
@@ -783,6 +779,7 @@ static int vti6_change_mtu(struct net_device *dev, int new_mtu) | |||
783 | } | 779 | } |
784 | 780 | ||
785 | static const struct net_device_ops vti6_netdev_ops = { | 781 | static const struct net_device_ops vti6_netdev_ops = { |
782 | .ndo_init = vti6_dev_init, | ||
786 | .ndo_uninit = vti6_dev_uninit, | 783 | .ndo_uninit = vti6_dev_uninit, |
787 | .ndo_start_xmit = vti6_tnl_xmit, | 784 | .ndo_start_xmit = vti6_tnl_xmit, |
788 | .ndo_do_ioctl = vti6_ioctl, | 785 | .ndo_do_ioctl = vti6_ioctl, |
@@ -852,16 +849,10 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) | |||
852 | struct ip6_tnl *t = netdev_priv(dev); | 849 | struct ip6_tnl *t = netdev_priv(dev); |
853 | struct net *net = dev_net(dev); | 850 | struct net *net = dev_net(dev); |
854 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); | 851 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); |
855 | int err = vti6_dev_init_gen(dev); | ||
856 | |||
857 | if (err) | ||
858 | return err; | ||
859 | 852 | ||
860 | t->parms.proto = IPPROTO_IPV6; | 853 | t->parms.proto = IPPROTO_IPV6; |
861 | dev_hold(dev); | 854 | dev_hold(dev); |
862 | 855 | ||
863 | vti6_link_config(t); | ||
864 | |||
865 | rcu_assign_pointer(ip6n->tnls_wc[0], t); | 856 | rcu_assign_pointer(ip6n->tnls_wc[0], t); |
866 | return 0; | 857 | return 0; |
867 | } | 858 | } |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 0171f08325c3..1a01d79b8698 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1439,6 +1439,10 @@ reg_pernet_fail: | |||
1439 | 1439 | ||
1440 | void ip6_mr_cleanup(void) | 1440 | void ip6_mr_cleanup(void) |
1441 | { | 1441 | { |
1442 | rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE); | ||
1443 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
1444 | inet6_del_protocol(&pim6_protocol, IPPROTO_PIM); | ||
1445 | #endif | ||
1442 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1446 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1443 | unregister_pernet_subsys(&ip6mr_net_ops); | 1447 | unregister_pernet_subsys(&ip6mr_net_ops); |
1444 | kmem_cache_destroy(mrt_cachep); | 1448 | kmem_cache_destroy(mrt_cachep); |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9648de2b6745..ed2c4e400b46 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1550,7 +1550,7 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb, | |||
1550 | hdr->daddr = *daddr; | 1550 | hdr->daddr = *daddr; |
1551 | } | 1551 | } |
1552 | 1552 | ||
1553 | static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) | 1553 | static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu) |
1554 | { | 1554 | { |
1555 | struct net_device *dev = idev->dev; | 1555 | struct net_device *dev = idev->dev; |
1556 | struct net *net = dev_net(dev); | 1556 | struct net *net = dev_net(dev); |
@@ -1561,13 +1561,13 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) | |||
1561 | const struct in6_addr *saddr; | 1561 | const struct in6_addr *saddr; |
1562 | int hlen = LL_RESERVED_SPACE(dev); | 1562 | int hlen = LL_RESERVED_SPACE(dev); |
1563 | int tlen = dev->needed_tailroom; | 1563 | int tlen = dev->needed_tailroom; |
1564 | unsigned int size = mtu + hlen + tlen; | ||
1564 | int err; | 1565 | int err; |
1565 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1566 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1566 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1567 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1567 | IPV6_TLV_PADN, 0 }; | 1568 | IPV6_TLV_PADN, 0 }; |
1568 | 1569 | ||
1569 | /* we assume size > sizeof(ra) here */ | 1570 | /* we assume size > sizeof(ra) here */ |
1570 | size += hlen + tlen; | ||
1571 | /* limit our allocations to order-0 page */ | 1571 | /* limit our allocations to order-0 page */ |
1572 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); | 1572 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); |
1573 | skb = sock_alloc_send_skb(sk, size, 1, &err); | 1573 | skb = sock_alloc_send_skb(sk, size, 1, &err); |
@@ -1576,6 +1576,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) | |||
1576 | return NULL; | 1576 | return NULL; |
1577 | 1577 | ||
1578 | skb->priority = TC_PRIO_CONTROL; | 1578 | skb->priority = TC_PRIO_CONTROL; |
1579 | skb->reserved_tailroom = skb_end_offset(skb) - | ||
1580 | min(mtu, skb_end_offset(skb)); | ||
1579 | skb_reserve(skb, hlen); | 1581 | skb_reserve(skb, hlen); |
1580 | 1582 | ||
1581 | if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { | 1583 | if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { |
@@ -1690,8 +1692,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1690 | return skb; | 1692 | return skb; |
1691 | } | 1693 | } |
1692 | 1694 | ||
1693 | #define AVAILABLE(skb) ((skb) ? ((skb)->dev ? (skb)->dev->mtu - (skb)->len : \ | 1695 | #define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0) |
1694 | skb_tailroom(skb)) : 0) | ||
1695 | 1696 | ||
1696 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | 1697 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, |
1697 | int type, int gdeleted, int sdeleted, int crsend) | 1698 | int type, int gdeleted, int sdeleted, int crsend) |
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 5f5f0438d74d..015eb8a80766 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c | |||
@@ -5,121 +5,109 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | |||
9 | #include <linux/module.h> | ||
8 | #include <net/ipv6.h> | 10 | #include <net/ipv6.h> |
9 | #include <net/ip6_route.h> | 11 | #include <net/ip6_route.h> |
10 | #include <net/ip6_fib.h> | 12 | #include <net/ip6_fib.h> |
11 | #include <net/ip6_checksum.h> | 13 | #include <net/ip6_checksum.h> |
12 | #include <linux/netfilter_ipv6.h> | 14 | #include <linux/netfilter_ipv6.h> |
15 | #include <net/netfilter/ipv6/nf_reject.h> | ||
13 | 16 | ||
14 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | 17 | const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, |
18 | struct tcphdr *otcph, | ||
19 | unsigned int *otcplen, int hook) | ||
15 | { | 20 | { |
16 | struct sk_buff *nskb; | ||
17 | struct tcphdr otcph, *tcph; | ||
18 | unsigned int otcplen, hh_len; | ||
19 | int tcphoff, needs_ack; | ||
20 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | 21 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
21 | struct ipv6hdr *ip6h; | ||
22 | #define DEFAULT_TOS_VALUE 0x0U | ||
23 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
24 | struct dst_entry *dst = NULL; | ||
25 | u8 proto; | 22 | u8 proto; |
26 | __be16 frag_off; | 23 | __be16 frag_off; |
27 | struct flowi6 fl6; | 24 | int tcphoff; |
28 | |||
29 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
30 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
31 | pr_debug("addr is not unicast.\n"); | ||
32 | return; | ||
33 | } | ||
34 | 25 | ||
35 | proto = oip6h->nexthdr; | 26 | proto = oip6h->nexthdr; |
36 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off); | 27 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), |
28 | &proto, &frag_off); | ||
37 | 29 | ||
38 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 30 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
39 | pr_debug("Cannot get TCP header.\n"); | 31 | pr_debug("Cannot get TCP header.\n"); |
40 | return; | 32 | return NULL; |
41 | } | 33 | } |
42 | 34 | ||
43 | otcplen = oldskb->len - tcphoff; | 35 | *otcplen = oldskb->len - tcphoff; |
44 | 36 | ||
45 | /* IP header checks: fragment, too short. */ | 37 | /* IP header checks: fragment, too short. */ |
46 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { | 38 | if (proto != IPPROTO_TCP || *otcplen < sizeof(struct tcphdr)) { |
47 | pr_debug("proto(%d) != IPPROTO_TCP, " | 39 | pr_debug("proto(%d) != IPPROTO_TCP or too short (len = %d)\n", |
48 | "or too short. otcplen = %d\n", | 40 | proto, *otcplen); |
49 | proto, otcplen); | 41 | return NULL; |
50 | return; | ||
51 | } | 42 | } |
52 | 43 | ||
53 | if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) | 44 | otcph = skb_header_pointer(oldskb, tcphoff, sizeof(struct tcphdr), |
54 | BUG(); | 45 | otcph); |
46 | if (otcph == NULL) | ||
47 | return NULL; | ||
55 | 48 | ||
56 | /* No RST for RST. */ | 49 | /* No RST for RST. */ |
57 | if (otcph.rst) { | 50 | if (otcph->rst) { |
58 | pr_debug("RST is set\n"); | 51 | pr_debug("RST is set\n"); |
59 | return; | 52 | return NULL; |
60 | } | 53 | } |
61 | 54 | ||
62 | /* Check checksum. */ | 55 | /* Check checksum. */ |
63 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { | 56 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { |
64 | pr_debug("TCP checksum is invalid\n"); | 57 | pr_debug("TCP checksum is invalid\n"); |
65 | return; | 58 | return NULL; |
66 | } | 59 | } |
67 | 60 | ||
68 | memset(&fl6, 0, sizeof(fl6)); | 61 | return otcph; |
69 | fl6.flowi6_proto = IPPROTO_TCP; | 62 | } |
70 | fl6.saddr = oip6h->daddr; | 63 | EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_get); |
71 | fl6.daddr = oip6h->saddr; | ||
72 | fl6.fl6_sport = otcph.dest; | ||
73 | fl6.fl6_dport = otcph.source; | ||
74 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | ||
75 | dst = ip6_route_output(net, NULL, &fl6); | ||
76 | if (dst == NULL || dst->error) { | ||
77 | dst_release(dst); | ||
78 | return; | ||
79 | } | ||
80 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
81 | if (IS_ERR(dst)) | ||
82 | return; | ||
83 | |||
84 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
85 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
86 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
87 | GFP_ATOMIC); | ||
88 | |||
89 | if (!nskb) { | ||
90 | net_dbg_ratelimited("cannot alloc skb\n"); | ||
91 | dst_release(dst); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | skb_dst_set(nskb, dst); | ||
96 | 64 | ||
97 | skb_reserve(nskb, hh_len + dst->header_len); | 65 | struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb, |
66 | const struct sk_buff *oldskb, | ||
67 | __be16 protocol, int hoplimit) | ||
68 | { | ||
69 | struct ipv6hdr *ip6h; | ||
70 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | ||
71 | #define DEFAULT_TOS_VALUE 0x0U | ||
72 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
98 | 73 | ||
99 | skb_put(nskb, sizeof(struct ipv6hdr)); | 74 | skb_put(nskb, sizeof(struct ipv6hdr)); |
100 | skb_reset_network_header(nskb); | 75 | skb_reset_network_header(nskb); |
101 | ip6h = ipv6_hdr(nskb); | 76 | ip6h = ipv6_hdr(nskb); |
102 | ip6_flow_hdr(ip6h, tclass, 0); | 77 | ip6_flow_hdr(ip6h, tclass, 0); |
103 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 78 | ip6h->hop_limit = hoplimit; |
104 | ip6h->nexthdr = IPPROTO_TCP; | 79 | ip6h->nexthdr = protocol; |
105 | ip6h->saddr = oip6h->daddr; | 80 | ip6h->saddr = oip6h->daddr; |
106 | ip6h->daddr = oip6h->saddr; | 81 | ip6h->daddr = oip6h->saddr; |
107 | 82 | ||
83 | nskb->protocol = htons(ETH_P_IPV6); | ||
84 | |||
85 | return ip6h; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(nf_reject_ip6hdr_put); | ||
88 | |||
89 | void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, | ||
90 | const struct sk_buff *oldskb, | ||
91 | const struct tcphdr *oth, unsigned int otcplen) | ||
92 | { | ||
93 | struct tcphdr *tcph; | ||
94 | int needs_ack; | ||
95 | |||
108 | skb_reset_transport_header(nskb); | 96 | skb_reset_transport_header(nskb); |
109 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | 97 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); |
110 | /* Truncate to length (no data) */ | 98 | /* Truncate to length (no data) */ |
111 | tcph->doff = sizeof(struct tcphdr)/4; | 99 | tcph->doff = sizeof(struct tcphdr)/4; |
112 | tcph->source = otcph.dest; | 100 | tcph->source = oth->dest; |
113 | tcph->dest = otcph.source; | 101 | tcph->dest = oth->source; |
114 | 102 | ||
115 | if (otcph.ack) { | 103 | if (oth->ack) { |
116 | needs_ack = 0; | 104 | needs_ack = 0; |
117 | tcph->seq = otcph.ack_seq; | 105 | tcph->seq = oth->ack_seq; |
118 | tcph->ack_seq = 0; | 106 | tcph->ack_seq = 0; |
119 | } else { | 107 | } else { |
120 | needs_ack = 1; | 108 | needs_ack = 1; |
121 | tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin | 109 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + |
122 | + otcplen - (otcph.doff<<2)); | 110 | otcplen - (oth->doff<<2)); |
123 | tcph->seq = 0; | 111 | tcph->seq = 0; |
124 | } | 112 | } |
125 | 113 | ||
@@ -137,6 +125,63 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | |||
137 | sizeof(struct tcphdr), IPPROTO_TCP, | 125 | sizeof(struct tcphdr), IPPROTO_TCP, |
138 | csum_partial(tcph, | 126 | csum_partial(tcph, |
139 | sizeof(struct tcphdr), 0)); | 127 | sizeof(struct tcphdr), 0)); |
128 | } | ||
129 | EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put); | ||
130 | |||
131 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | ||
132 | { | ||
133 | struct sk_buff *nskb; | ||
134 | struct tcphdr _otcph; | ||
135 | const struct tcphdr *otcph; | ||
136 | unsigned int otcplen, hh_len; | ||
137 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | ||
138 | struct ipv6hdr *ip6h; | ||
139 | struct dst_entry *dst = NULL; | ||
140 | struct flowi6 fl6; | ||
141 | |||
142 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
143 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
144 | pr_debug("addr is not unicast.\n"); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | otcph = nf_reject_ip6_tcphdr_get(oldskb, &_otcph, &otcplen, hook); | ||
149 | if (!otcph) | ||
150 | return; | ||
151 | |||
152 | memset(&fl6, 0, sizeof(fl6)); | ||
153 | fl6.flowi6_proto = IPPROTO_TCP; | ||
154 | fl6.saddr = oip6h->daddr; | ||
155 | fl6.daddr = oip6h->saddr; | ||
156 | fl6.fl6_sport = otcph->dest; | ||
157 | fl6.fl6_dport = otcph->source; | ||
158 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | ||
159 | dst = ip6_route_output(net, NULL, &fl6); | ||
160 | if (dst == NULL || dst->error) { | ||
161 | dst_release(dst); | ||
162 | return; | ||
163 | } | ||
164 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
165 | if (IS_ERR(dst)) | ||
166 | return; | ||
167 | |||
168 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
169 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
170 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
171 | GFP_ATOMIC); | ||
172 | |||
173 | if (!nskb) { | ||
174 | net_dbg_ratelimited("cannot alloc skb\n"); | ||
175 | dst_release(dst); | ||
176 | return; | ||
177 | } | ||
178 | |||
179 | skb_dst_set(nskb, dst); | ||
180 | |||
181 | skb_reserve(nskb, hh_len + dst->header_len); | ||
182 | ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, | ||
183 | ip6_dst_hoplimit(dst)); | ||
184 | nf_reject_ip6_tcphdr_put(nskb, oldskb, otcph, otcplen); | ||
140 | 185 | ||
141 | nf_ct_attach(nskb, oldskb); | 186 | nf_ct_attach(nskb, oldskb); |
142 | 187 | ||
@@ -161,3 +206,5 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | |||
161 | ip6_local_out(nskb); | 206 | ip6_local_out(nskb); |
162 | } | 207 | } |
163 | EXPORT_SYMBOL_GPL(nf_send_reset6); | 208 | EXPORT_SYMBOL_GPL(nf_send_reset6); |
209 | |||
210 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c index 556262f40761..529c119cbb14 100644 --- a/net/ipv6/netfilter/nft_masq_ipv6.c +++ b/net/ipv6/netfilter/nft_masq_ipv6.c | |||
@@ -25,6 +25,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, | |||
25 | struct nf_nat_range range; | 25 | struct nf_nat_range range; |
26 | unsigned int verdict; | 26 | unsigned int verdict; |
27 | 27 | ||
28 | memset(&range, 0, sizeof(range)); | ||
28 | range.flags = priv->flags; | 29 | range.flags = priv->flags; |
29 | 30 | ||
30 | verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); | 31 | verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); |
@@ -39,6 +40,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = { | |||
39 | .eval = nft_masq_ipv6_eval, | 40 | .eval = nft_masq_ipv6_eval, |
40 | .init = nft_masq_init, | 41 | .init = nft_masq_init, |
41 | .dump = nft_masq_dump, | 42 | .dump = nft_masq_dump, |
43 | .validate = nft_masq_validate, | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { | 46 | static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index fc24c390af05..97f41a3e68d9 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
@@ -3,11 +3,45 @@ | |||
3 | * not configured or static. These functions are needed by GSO/GRO implementation. | 3 | * not configured or static. These functions are needed by GSO/GRO implementation. |
4 | */ | 4 | */ |
5 | #include <linux/export.h> | 5 | #include <linux/export.h> |
6 | #include <net/ip.h> | ||
6 | #include <net/ipv6.h> | 7 | #include <net/ipv6.h> |
7 | #include <net/ip6_fib.h> | 8 | #include <net/ip6_fib.h> |
8 | #include <net/addrconf.h> | 9 | #include <net/addrconf.h> |
9 | #include <net/secure_seq.h> | 10 | #include <net/secure_seq.h> |
10 | 11 | ||
12 | /* This function exists only for tap drivers that must support broken | ||
13 | * clients requesting UFO without specifying an IPv6 fragment ID. | ||
14 | * | ||
15 | * This is similar to ipv6_select_ident() but we use an independent hash | ||
16 | * seed to limit information leakage. | ||
17 | * | ||
18 | * The network header must be set before calling this. | ||
19 | */ | ||
20 | void ipv6_proxy_select_ident(struct sk_buff *skb) | ||
21 | { | ||
22 | static u32 ip6_proxy_idents_hashrnd __read_mostly; | ||
23 | struct in6_addr buf[2]; | ||
24 | struct in6_addr *addrs; | ||
25 | u32 hash, id; | ||
26 | |||
27 | addrs = skb_header_pointer(skb, | ||
28 | skb_network_offset(skb) + | ||
29 | offsetof(struct ipv6hdr, saddr), | ||
30 | sizeof(buf), buf); | ||
31 | if (!addrs) | ||
32 | return; | ||
33 | |||
34 | net_get_random_once(&ip6_proxy_idents_hashrnd, | ||
35 | sizeof(ip6_proxy_idents_hashrnd)); | ||
36 | |||
37 | hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); | ||
38 | hash = __ipv6_addr_jhash(&addrs[0], hash); | ||
39 | |||
40 | id = ip_idents_reserve(hash, 1); | ||
41 | skb_shinfo(skb)->ip6_frag_id = htonl(id); | ||
42 | } | ||
43 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); | ||
44 | |||
11 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 45 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
12 | { | 46 | { |
13 | u16 offset = sizeof(struct ipv6hdr); | 47 | u16 offset = sizeof(struct ipv6hdr); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 58e5b4710127..a24557a1c1d8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -195,10 +195,8 @@ static int ipip6_tunnel_create(struct net_device *dev) | |||
195 | struct sit_net *sitn = net_generic(net, sit_net_id); | 195 | struct sit_net *sitn = net_generic(net, sit_net_id); |
196 | int err; | 196 | int err; |
197 | 197 | ||
198 | err = ipip6_tunnel_init(dev); | 198 | memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); |
199 | if (err < 0) | 199 | memcpy(dev->broadcast, &t->parms.iph.daddr, 4); |
200 | goto out; | ||
201 | ipip6_tunnel_clone_6rd(dev, sitn); | ||
202 | 200 | ||
203 | if ((__force u16)t->parms.i_flags & SIT_ISATAP) | 201 | if ((__force u16)t->parms.i_flags & SIT_ISATAP) |
204 | dev->priv_flags |= IFF_ISATAP; | 202 | dev->priv_flags |= IFF_ISATAP; |
@@ -207,7 +205,8 @@ static int ipip6_tunnel_create(struct net_device *dev) | |||
207 | if (err < 0) | 205 | if (err < 0) |
208 | goto out; | 206 | goto out; |
209 | 207 | ||
210 | strcpy(t->parms.name, dev->name); | 208 | ipip6_tunnel_clone_6rd(dev, sitn); |
209 | |||
211 | dev->rtnl_link_ops = &sit_link_ops; | 210 | dev->rtnl_link_ops = &sit_link_ops; |
212 | 211 | ||
213 | dev_hold(dev); | 212 | dev_hold(dev); |
@@ -1330,6 +1329,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | |||
1330 | } | 1329 | } |
1331 | 1330 | ||
1332 | static const struct net_device_ops ipip6_netdev_ops = { | 1331 | static const struct net_device_ops ipip6_netdev_ops = { |
1332 | .ndo_init = ipip6_tunnel_init, | ||
1333 | .ndo_uninit = ipip6_tunnel_uninit, | 1333 | .ndo_uninit = ipip6_tunnel_uninit, |
1334 | .ndo_start_xmit = sit_tunnel_xmit, | 1334 | .ndo_start_xmit = sit_tunnel_xmit, |
1335 | .ndo_do_ioctl = ipip6_tunnel_ioctl, | 1335 | .ndo_do_ioctl = ipip6_tunnel_ioctl, |
@@ -1378,9 +1378,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1378 | 1378 | ||
1379 | tunnel->dev = dev; | 1379 | tunnel->dev = dev; |
1380 | tunnel->net = dev_net(dev); | 1380 | tunnel->net = dev_net(dev); |
1381 | 1381 | strcpy(tunnel->parms.name, dev->name); | |
1382 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | ||
1383 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | ||
1384 | 1382 | ||
1385 | ipip6_tunnel_bind_dev(dev); | 1383 | ipip6_tunnel_bind_dev(dev); |
1386 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | 1384 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
@@ -1405,7 +1403,6 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1405 | 1403 | ||
1406 | tunnel->dev = dev; | 1404 | tunnel->dev = dev; |
1407 | tunnel->net = dev_net(dev); | 1405 | tunnel->net = dev_net(dev); |
1408 | strcpy(tunnel->parms.name, dev->name); | ||
1409 | 1406 | ||
1410 | iph->version = 4; | 1407 | iph->version = 4; |
1411 | iph->protocol = IPPROTO_IPV6; | 1408 | iph->protocol = IPPROTO_IPV6; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 831495529b82..ace29b60813c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -200,8 +200,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
200 | sk->sk_v6_daddr = usin->sin6_addr; | 200 | sk->sk_v6_daddr = usin->sin6_addr; |
201 | np->flow_label = fl6.flowlabel; | 201 | np->flow_label = fl6.flowlabel; |
202 | 202 | ||
203 | ip6_set_txhash(sk); | ||
204 | |||
205 | /* | 203 | /* |
206 | * TCP over IPv4 | 204 | * TCP over IPv4 |
207 | */ | 205 | */ |
@@ -297,6 +295,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
297 | if (err) | 295 | if (err) |
298 | goto late_failure; | 296 | goto late_failure; |
299 | 297 | ||
298 | ip6_set_txhash(sk); | ||
299 | |||
300 | if (!tp->write_seq && likely(!tp->repair)) | 300 | if (!tp->write_seq && likely(!tp->repair)) |
301 | tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, | 301 | tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, |
302 | sk->sk_v6_daddr.s6_addr32, | 302 | sk->sk_v6_daddr.s6_addr32, |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index ac49f84fe2c3..5f983644373a 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -170,8 +170,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
170 | case IPPROTO_DCCP: | 170 | case IPPROTO_DCCP: |
171 | if (!onlyproto && (nh + offset + 4 < skb->data || | 171 | if (!onlyproto && (nh + offset + 4 < skb->data || |
172 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { | 172 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { |
173 | __be16 *ports = (__be16 *)exthdr; | 173 | __be16 *ports; |
174 | 174 | ||
175 | nh = skb_network_header(skb); | ||
176 | ports = (__be16 *)(nh + offset); | ||
175 | fl6->fl6_sport = ports[!!reverse]; | 177 | fl6->fl6_sport = ports[!!reverse]; |
176 | fl6->fl6_dport = ports[!reverse]; | 178 | fl6->fl6_dport = ports[!reverse]; |
177 | } | 179 | } |
@@ -180,8 +182,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
180 | 182 | ||
181 | case IPPROTO_ICMPV6: | 183 | case IPPROTO_ICMPV6: |
182 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { | 184 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { |
183 | u8 *icmp = (u8 *)exthdr; | 185 | u8 *icmp; |
184 | 186 | ||
187 | nh = skb_network_header(skb); | ||
188 | icmp = (u8 *)(nh + offset); | ||
185 | fl6->fl6_icmp_type = icmp[0]; | 189 | fl6->fl6_icmp_type = icmp[0]; |
186 | fl6->fl6_icmp_code = icmp[1]; | 190 | fl6->fl6_icmp_code = icmp[1]; |
187 | } | 191 | } |
@@ -192,8 +196,9 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
192 | case IPPROTO_MH: | 196 | case IPPROTO_MH: |
193 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 197 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
194 | struct ip6_mh *mh; | 198 | struct ip6_mh *mh; |
195 | mh = (struct ip6_mh *)exthdr; | ||
196 | 199 | ||
200 | nh = skb_network_header(skb); | ||
201 | mh = (struct ip6_mh *)(nh + offset); | ||
197 | fl6->fl6_mh_type = mh->ip6mh_type; | 202 | fl6->fl6_mh_type = mh->ip6mh_type; |
198 | } | 203 | } |
199 | fl6->flowi6_proto = nexthdr; | 204 | fl6->flowi6_proto = nexthdr; |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 91729b807c7d..1b095ca37aa4 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -1764,6 +1764,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1764 | struct ipxhdr *ipx = NULL; | 1764 | struct ipxhdr *ipx = NULL; |
1765 | struct sk_buff *skb; | 1765 | struct sk_buff *skb; |
1766 | int copied, rc; | 1766 | int copied, rc; |
1767 | bool locked = true; | ||
1767 | 1768 | ||
1768 | lock_sock(sk); | 1769 | lock_sock(sk); |
1769 | /* put the autobinding in */ | 1770 | /* put the autobinding in */ |
@@ -1790,6 +1791,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1790 | if (sock_flag(sk, SOCK_ZAPPED)) | 1791 | if (sock_flag(sk, SOCK_ZAPPED)) |
1791 | goto out; | 1792 | goto out; |
1792 | 1793 | ||
1794 | release_sock(sk); | ||
1795 | locked = false; | ||
1793 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1796 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
1794 | flags & MSG_DONTWAIT, &rc); | 1797 | flags & MSG_DONTWAIT, &rc); |
1795 | if (!skb) { | 1798 | if (!skb) { |
@@ -1826,7 +1829,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1826 | out_free: | 1829 | out_free: |
1827 | skb_free_datagram(sk, skb); | 1830 | skb_free_datagram(sk, skb); |
1828 | out: | 1831 | out: |
1829 | release_sock(sk); | 1832 | if (locked) |
1833 | release_sock(sk); | ||
1830 | return rc; | 1834 | return rc; |
1831 | } | 1835 | } |
1832 | 1836 | ||
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 92fafd485deb..3f3a6cbdceb7 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -1064,8 +1064,6 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1064 | 1064 | ||
1065 | if (sk->sk_state != TCP_ESTABLISHED) { | 1065 | if (sk->sk_state != TCP_ESTABLISHED) { |
1066 | sock->state = SS_UNCONNECTED; | 1066 | sock->state = SS_UNCONNECTED; |
1067 | if (sk->sk_prot->disconnect(sk, flags)) | ||
1068 | sock->state = SS_DISCONNECTING; | ||
1069 | err = sock_error(sk); | 1067 | err = sock_error(sk); |
1070 | if (!err) | 1068 | if (!err) |
1071 | err = -ECONNRESET; | 1069 | err = -ECONNRESET; |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index ec24378caaaf..09d9caaec591 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -53,6 +53,9 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | |||
53 | __aligned(__alignof__(struct aead_request)); | 53 | __aligned(__alignof__(struct aead_request)); |
54 | struct aead_request *aead_req = (void *) aead_req_data; | 54 | struct aead_request *aead_req = (void *) aead_req_data; |
55 | 55 | ||
56 | if (data_len == 0) | ||
57 | return -EINVAL; | ||
58 | |||
56 | memset(aead_req, 0, sizeof(aead_req_data)); | 59 | memset(aead_req, 0, sizeof(aead_req_data)); |
57 | 60 | ||
58 | sg_init_one(&pt, data, data_len); | 61 | sg_init_one(&pt, data, data_len); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fb6a1502b6df..343da1e35025 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -3458,7 +3458,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, | |||
3458 | rcu_read_lock(); | 3458 | rcu_read_lock(); |
3459 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3459 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
3460 | if (chanctx_conf) { | 3460 | if (chanctx_conf) { |
3461 | *chandef = chanctx_conf->def; | 3461 | *chandef = sdata->vif.bss_conf.chandef; |
3462 | ret = 0; | 3462 | ret = 0; |
3463 | } else if (local->open_count > 0 && | 3463 | } else if (local->open_count > 0 && |
3464 | local->open_count == local->monitors && | 3464 | local->open_count == local->monitors && |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 56b53571c807..509bc157ce55 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -805,7 +805,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
805 | 805 | ||
806 | memset(¶ms, 0, sizeof(params)); | 806 | memset(¶ms, 0, sizeof(params)); |
807 | memset(&csa_ie, 0, sizeof(csa_ie)); | 807 | memset(&csa_ie, 0, sizeof(csa_ie)); |
808 | err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, | 808 | err = ieee80211_parse_ch_switch_ie(sdata, elems, |
809 | ifibss->chandef.chan->band, | 809 | ifibss->chandef.chan->band, |
810 | sta_flags, ifibss->bssid, &csa_ie); | 810 | sta_flags, ifibss->bssid, &csa_ie); |
811 | /* can't switch to destination channel, fail */ | 811 | /* can't switch to destination channel, fail */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c2aaec4dfcf0..8c68da30595d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1642,7 +1642,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | |||
1642 | * ieee80211_parse_ch_switch_ie - parses channel switch IEs | 1642 | * ieee80211_parse_ch_switch_ie - parses channel switch IEs |
1643 | * @sdata: the sdata of the interface which has received the frame | 1643 | * @sdata: the sdata of the interface which has received the frame |
1644 | * @elems: parsed 802.11 elements received with the frame | 1644 | * @elems: parsed 802.11 elements received with the frame |
1645 | * @beacon: indicates if the frame was a beacon or probe response | ||
1646 | * @current_band: indicates the current band | 1645 | * @current_band: indicates the current band |
1647 | * @sta_flags: contains information about own capabilities and restrictions | 1646 | * @sta_flags: contains information about own capabilities and restrictions |
1648 | * to decide which channel switch announcements can be accepted. Only the | 1647 | * to decide which channel switch announcements can be accepted. Only the |
@@ -1656,7 +1655,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | |||
1656 | * Return: 0 on success, <0 on error and >0 if there is nothing to parse. | 1655 | * Return: 0 on success, <0 on error and >0 if there is nothing to parse. |
1657 | */ | 1656 | */ |
1658 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | 1657 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, |
1659 | struct ieee802_11_elems *elems, bool beacon, | 1658 | struct ieee802_11_elems *elems, |
1660 | enum ieee80211_band current_band, | 1659 | enum ieee80211_band current_band, |
1661 | u32 sta_flags, u8 *bssid, | 1660 | u32 sta_flags, u8 *bssid, |
1662 | struct ieee80211_csa_ie *csa_ie); | 1661 | struct ieee80211_csa_ie *csa_ie); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index af237223a8cd..653f5eb07a27 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -766,10 +766,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
766 | int i, flushed; | 766 | int i, flushed; |
767 | struct ps_data *ps; | 767 | struct ps_data *ps; |
768 | struct cfg80211_chan_def chandef; | 768 | struct cfg80211_chan_def chandef; |
769 | bool cancel_scan; | ||
769 | 770 | ||
770 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 771 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
771 | 772 | ||
772 | if (rcu_access_pointer(local->scan_sdata) == sdata) | 773 | cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; |
774 | if (cancel_scan) | ||
773 | ieee80211_scan_cancel(local); | 775 | ieee80211_scan_cancel(local); |
774 | 776 | ||
775 | /* | 777 | /* |
@@ -898,6 +900,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
898 | list_del(&sdata->u.vlan.list); | 900 | list_del(&sdata->u.vlan.list); |
899 | mutex_unlock(&local->mtx); | 901 | mutex_unlock(&local->mtx); |
900 | RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); | 902 | RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); |
903 | /* see comment in the default case below */ | ||
904 | ieee80211_free_keys(sdata, true); | ||
901 | /* no need to tell driver */ | 905 | /* no need to tell driver */ |
902 | break; | 906 | break; |
903 | case NL80211_IFTYPE_MONITOR: | 907 | case NL80211_IFTYPE_MONITOR: |
@@ -923,17 +927,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
923 | /* | 927 | /* |
924 | * When we get here, the interface is marked down. | 928 | * When we get here, the interface is marked down. |
925 | * Free the remaining keys, if there are any | 929 | * Free the remaining keys, if there are any |
926 | * (shouldn't be, except maybe in WDS mode?) | 930 | * (which can happen in AP mode if userspace sets |
931 | * keys before the interface is operating, and maybe | ||
932 | * also in WDS mode) | ||
927 | * | 933 | * |
928 | * Force the key freeing to always synchronize_net() | 934 | * Force the key freeing to always synchronize_net() |
929 | * to wait for the RX path in case it is using this | 935 | * to wait for the RX path in case it is using this |
930 | * interface enqueuing frames * at this very time on | 936 | * interface enqueuing frames at this very time on |
931 | * another CPU. | 937 | * another CPU. |
932 | */ | 938 | */ |
933 | ieee80211_free_keys(sdata, true); | 939 | ieee80211_free_keys(sdata, true); |
934 | |||
935 | /* fall through */ | ||
936 | case NL80211_IFTYPE_AP: | ||
937 | skb_queue_purge(&sdata->skb_queue); | 940 | skb_queue_purge(&sdata->skb_queue); |
938 | } | 941 | } |
939 | 942 | ||
@@ -991,6 +994,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
991 | 994 | ||
992 | ieee80211_recalc_ps(local, -1); | 995 | ieee80211_recalc_ps(local, -1); |
993 | 996 | ||
997 | if (cancel_scan) | ||
998 | flush_delayed_work(&local->scan_work); | ||
999 | |||
994 | if (local->open_count == 0) { | 1000 | if (local->open_count == 0) { |
995 | ieee80211_stop_device(local); | 1001 | ieee80211_stop_device(local); |
996 | 1002 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e9f99c1e3fad..0c8b2a77d312 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -874,7 +874,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
874 | 874 | ||
875 | memset(¶ms, 0, sizeof(params)); | 875 | memset(¶ms, 0, sizeof(params)); |
876 | memset(&csa_ie, 0, sizeof(csa_ie)); | 876 | memset(&csa_ie, 0, sizeof(csa_ie)); |
877 | err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, | 877 | err = ieee80211_parse_ch_switch_ie(sdata, elems, band, |
878 | sta_flags, sdata->vif.addr, | 878 | sta_flags, sdata->vif.addr, |
879 | &csa_ie); | 879 | &csa_ie); |
880 | if (err < 0) | 880 | if (err < 0) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2de88704278b..93af0f1c9d99 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1072,7 +1072,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1072 | 1072 | ||
1073 | current_band = cbss->channel->band; | 1073 | current_band = cbss->channel->band; |
1074 | memset(&csa_ie, 0, sizeof(csa_ie)); | 1074 | memset(&csa_ie, 0, sizeof(csa_ie)); |
1075 | res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, | 1075 | res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band, |
1076 | ifmgd->flags, | 1076 | ifmgd->flags, |
1077 | ifmgd->associated->bssid, &csa_ie); | 1077 | ifmgd->associated->bssid, &csa_ie); |
1078 | if (res < 0) | 1078 | if (res < 0) |
@@ -1168,7 +1168,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1168 | ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); | 1168 | ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); |
1169 | else | 1169 | else |
1170 | mod_timer(&ifmgd->chswitch_timer, | 1170 | mod_timer(&ifmgd->chswitch_timer, |
1171 | TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); | 1171 | TU_TO_EXP_TIME((csa_ie.count - 1) * |
1172 | cbss->beacon_interval)); | ||
1172 | } | 1173 | } |
1173 | 1174 | ||
1174 | static bool | 1175 | static bool |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 8fdadfd94ba8..6081329784dd 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -448,7 +448,7 @@ static void rate_fixup_ratelist(struct ieee80211_vif *vif, | |||
448 | */ | 448 | */ |
449 | if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) { | 449 | if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) { |
450 | u32 basic_rates = vif->bss_conf.basic_rates; | 450 | u32 basic_rates = vif->bss_conf.basic_rates; |
451 | s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0; | 451 | s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0; |
452 | 452 | ||
453 | rate = &sband->bitrates[rates[0].idx]; | 453 | rate = &sband->bitrates[rates[0].idx]; |
454 | 454 | ||
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index edde723f9f00..2acab1bcaa4b 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -62,14 +62,14 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
62 | unsigned int i, tp, prob, eprob; | 62 | unsigned int i, tp, prob, eprob; |
63 | char *p; | 63 | char *p; |
64 | 64 | ||
65 | ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL); | 65 | ms = kmalloc(2048, GFP_KERNEL); |
66 | if (!ms) | 66 | if (!ms) |
67 | return -ENOMEM; | 67 | return -ENOMEM; |
68 | 68 | ||
69 | file->private_data = ms; | 69 | file->private_data = ms; |
70 | p = ms->buf; | 70 | p = ms->buf; |
71 | p += sprintf(p, "rate throughput ewma prob this prob " | 71 | p += sprintf(p, "rate tpt eprob *prob" |
72 | "this succ/attempt success attempts\n"); | 72 | " *ok(*cum) ok( cum)\n"); |
73 | for (i = 0; i < mi->n_rates; i++) { | 73 | for (i = 0; i < mi->n_rates; i++) { |
74 | struct minstrel_rate *mr = &mi->r[i]; | 74 | struct minstrel_rate *mr = &mi->r[i]; |
75 | struct minstrel_rate_stats *mrs = &mi->r[i].stats; | 75 | struct minstrel_rate_stats *mrs = &mi->r[i].stats; |
@@ -86,8 +86,8 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
86 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); | 86 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); |
87 | eprob = MINSTREL_TRUNC(mrs->probability * 1000); | 87 | eprob = MINSTREL_TRUNC(mrs->probability * 1000); |
88 | 88 | ||
89 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | 89 | p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u" |
90 | " %3u(%3u) %8llu %8llu\n", | 90 | " %4u(%4u) %9llu(%9llu)\n", |
91 | tp / 10, tp % 10, | 91 | tp / 10, tp % 10, |
92 | eprob / 10, eprob % 10, | 92 | eprob / 10, eprob % 10, |
93 | prob / 10, prob % 10, | 93 | prob / 10, prob % 10, |
@@ -102,6 +102,8 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
102 | mi->sample_packets); | 102 | mi->sample_packets); |
103 | ms->len = p - ms->buf; | 103 | ms->len = p - ms->buf; |
104 | 104 | ||
105 | WARN_ON(ms->len + sizeof(*ms) > 2048); | ||
106 | |||
105 | return 0; | 107 | return 0; |
106 | } | 108 | } |
107 | 109 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index df90ce2db00c..408fd8ab4eef 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -252,19 +252,16 @@ minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u8 index, | |||
252 | cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp; | 252 | cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp; |
253 | cur_prob = mi->groups[cur_group].rates[cur_idx].probability; | 253 | cur_prob = mi->groups[cur_group].rates[cur_idx].probability; |
254 | 254 | ||
255 | tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; | 255 | do { |
256 | tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; | ||
257 | tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp; | ||
258 | tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability; | ||
259 | |||
260 | while (j > 0 && (cur_thr > tmp_thr || | ||
261 | (cur_thr == tmp_thr && cur_prob > tmp_prob))) { | ||
262 | j--; | ||
263 | tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; | 256 | tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; |
264 | tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; | 257 | tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; |
265 | tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp; | 258 | tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp; |
266 | tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability; | 259 | tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability; |
267 | } | 260 | if (cur_thr < tmp_thr || |
261 | (cur_thr == tmp_thr && cur_prob <= tmp_prob)) | ||
262 | break; | ||
263 | j--; | ||
264 | } while (j > 0); | ||
268 | 265 | ||
269 | if (j < MAX_THR_RATES - 1) { | 266 | if (j < MAX_THR_RATES - 1) { |
270 | memmove(&tp_list[j + 1], &tp_list[j], (sizeof(*tp_list) * | 267 | memmove(&tp_list[j + 1], &tp_list[j], (sizeof(*tp_list) * |
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index a72ad46f2a04..d537bec93754 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c | |||
@@ -63,8 +63,8 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) | |||
63 | prob = MINSTREL_TRUNC(mr->cur_prob * 1000); | 63 | prob = MINSTREL_TRUNC(mr->cur_prob * 1000); |
64 | eprob = MINSTREL_TRUNC(mr->probability * 1000); | 64 | eprob = MINSTREL_TRUNC(mr->probability * 1000); |
65 | 65 | ||
66 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | 66 | p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u " |
67 | "%3u %3u(%3u) %8llu %8llu\n", | 67 | "%3u %4u(%4u) %9llu(%9llu)\n", |
68 | tp / 10, tp % 10, | 68 | tp / 10, tp % 10, |
69 | eprob / 10, eprob % 10, | 69 | eprob / 10, eprob % 10, |
70 | prob / 10, prob % 10, | 70 | prob / 10, prob % 10, |
@@ -96,14 +96,15 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) | |||
96 | return ret; | 96 | return ret; |
97 | } | 97 | } |
98 | 98 | ||
99 | ms = kmalloc(sizeof(*ms) + 8192, GFP_KERNEL); | 99 | ms = kmalloc(8192, GFP_KERNEL); |
100 | if (!ms) | 100 | if (!ms) |
101 | return -ENOMEM; | 101 | return -ENOMEM; |
102 | 102 | ||
103 | file->private_data = ms; | 103 | file->private_data = ms; |
104 | p = ms->buf; | 104 | p = ms->buf; |
105 | p += sprintf(p, "type rate throughput ewma prob " | 105 | p += sprintf(p, "type rate tpt eprob *prob " |
106 | "this prob retry this succ/attempt success attempts\n"); | 106 | "ret *ok(*cum) ok( cum)\n"); |
107 | |||
107 | 108 | ||
108 | p = minstrel_ht_stats_dump(mi, max_mcs, p); | 109 | p = minstrel_ht_stats_dump(mi, max_mcs, p); |
109 | for (i = 0; i < max_mcs; i++) | 110 | for (i = 0; i < max_mcs; i++) |
@@ -118,6 +119,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) | |||
118 | MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10); | 119 | MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10); |
119 | ms->len = p - ms->buf; | 120 | ms->len = p - ms->buf; |
120 | 121 | ||
122 | WARN_ON(ms->len + sizeof(*ms) > 8192); | ||
123 | |||
121 | return nonseekable_open(inode, file); | 124 | return nonseekable_open(inode, file); |
122 | } | 125 | } |
123 | 126 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b04ca4049c95..a37f9af634cb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1678,11 +1678,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1678 | sc = le16_to_cpu(hdr->seq_ctrl); | 1678 | sc = le16_to_cpu(hdr->seq_ctrl); |
1679 | frag = sc & IEEE80211_SCTL_FRAG; | 1679 | frag = sc & IEEE80211_SCTL_FRAG; |
1680 | 1680 | ||
1681 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || | 1681 | if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) |
1682 | is_multicast_ether_addr(hdr->addr1))) { | 1682 | goto out; |
1683 | /* not fragmented */ | 1683 | |
1684 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
1685 | rx->local->dot11MulticastReceivedFrameCount++; | ||
1684 | goto out; | 1686 | goto out; |
1685 | } | 1687 | } |
1688 | |||
1686 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); | 1689 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); |
1687 | 1690 | ||
1688 | if (skb_linearize(rx->skb)) | 1691 | if (skb_linearize(rx->skb)) |
@@ -1775,10 +1778,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1775 | out: | 1778 | out: |
1776 | if (rx->sta) | 1779 | if (rx->sta) |
1777 | rx->sta->rx_packets++; | 1780 | rx->sta->rx_packets++; |
1778 | if (is_multicast_ether_addr(hdr->addr1)) | 1781 | ieee80211_led_rx(rx->local); |
1779 | rx->local->dot11MulticastReceivedFrameCount++; | ||
1780 | else | ||
1781 | ieee80211_led_rx(rx->local); | ||
1782 | return RX_CONTINUE; | 1782 | return RX_CONTINUE; |
1783 | } | 1783 | } |
1784 | 1784 | ||
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 6ab009070084..efeba56c913b 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "wme.h" | 22 | #include "wme.h" |
23 | 23 | ||
24 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | 24 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, |
25 | struct ieee802_11_elems *elems, bool beacon, | 25 | struct ieee802_11_elems *elems, |
26 | enum ieee80211_band current_band, | 26 | enum ieee80211_band current_band, |
27 | u32 sta_flags, u8 *bssid, | 27 | u32 sta_flags, u8 *bssid, |
28 | struct ieee80211_csa_ie *csa_ie) | 28 | struct ieee80211_csa_ie *csa_ie) |
@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
91 | return -EINVAL; | 91 | return -EINVAL; |
92 | } | 92 | } |
93 | 93 | ||
94 | if (!beacon && sec_chan_offs) { | 94 | if (sec_chan_offs) { |
95 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; | 95 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; |
96 | } else if (beacon && ht_oper) { | ||
97 | secondary_channel_offset = | ||
98 | ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
99 | } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { | 96 | } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { |
100 | /* If it's not a beacon, HT is enabled and the IE not present, | 97 | /* If the secondary channel offset IE is not present, |
101 | * it's 20 MHz, 802.11-2012 8.5.2.6: | 98 | * we can't know what's the post-CSA offset, so the |
102 | * This element [the Secondary Channel Offset Element] is | 99 | * best we can do is use 20MHz. |
103 | * present when switching to a 40 MHz channel. It may be | 100 | */ |
104 | * present when switching to a 20 MHz channel (in which | ||
105 | * case the secondary channel offset is set to SCN). | ||
106 | */ | ||
107 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 101 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
108 | } | 102 | } |
109 | 103 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 42f68cb8957e..bcda2ac7d844 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -336,6 +336,7 @@ struct ieee80211_tx_latency_stat { | |||
336 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for | 336 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for |
337 | * AP only. | 337 | * AP only. |
338 | * @cipher_scheme: optional cipher scheme for this station | 338 | * @cipher_scheme: optional cipher scheme for this station |
339 | * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed | ||
339 | */ | 340 | */ |
340 | struct sta_info { | 341 | struct sta_info { |
341 | /* General information, mostly static */ | 342 | /* General information, mostly static */ |
diff --git a/net/mpls/Makefile b/net/mpls/Makefile index 0a3c171be537..6dec088c2d0f 100644 --- a/net/mpls/Makefile +++ b/net/mpls/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # | 1 | # |
2 | # Makefile for MPLS. | 2 | # Makefile for MPLS. |
3 | # | 3 | # |
4 | obj-y += mpls_gso.o | 4 | obj-$(CONFIG_NET_MPLS_GSO) += mpls_gso.o |
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c index e28ed2ef5b06..e3545f21a099 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c | |||
@@ -48,7 +48,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, | |||
48 | __skb_push(skb, skb->mac_len); | 48 | __skb_push(skb, skb->mac_len); |
49 | 49 | ||
50 | /* Segment inner packet. */ | 50 | /* Segment inner packet. */ |
51 | mpls_features = skb->dev->mpls_features & netif_skb_features(skb); | 51 | mpls_features = skb->dev->mpls_features & features; |
52 | segs = skb_mac_gso_segment(skb, mpls_features); | 52 | segs = skb_mac_gso_segment(skb, mpls_features); |
53 | 53 | ||
54 | 54 | ||
@@ -59,8 +59,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, | |||
59 | * above pulled. It will be re-pushed after returning | 59 | * above pulled. It will be re-pushed after returning |
60 | * skb_mac_gso_segment(), an indirect caller of this function. | 60 | * skb_mac_gso_segment(), an indirect caller of this function. |
61 | */ | 61 | */ |
62 | __skb_push(skb, skb->data - skb_mac_header(skb)); | 62 | __skb_pull(skb, skb->data - skb_mac_header(skb)); |
63 | |||
64 | out: | 63 | out: |
65 | return segs; | 64 | return segs; |
66 | } | 65 | } |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 912e5a05b79d..d259da3ce67a 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -659,7 +659,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index) | |||
659 | struct ip_set *set; | 659 | struct ip_set *set; |
660 | struct ip_set_net *inst = ip_set_pernet(net); | 660 | struct ip_set_net *inst = ip_set_pernet(net); |
661 | 661 | ||
662 | if (index > inst->ip_set_max) | 662 | if (index >= inst->ip_set_max) |
663 | return IPSET_INVALID_ID; | 663 | return IPSET_INVALID_ID; |
664 | 664 | ||
665 | nfnl_lock(NFNL_SUBSYS_IPSET); | 665 | nfnl_lock(NFNL_SUBSYS_IPSET); |
@@ -1863,6 +1863,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) | |||
1863 | if (*op < IP_SET_OP_VERSION) { | 1863 | if (*op < IP_SET_OP_VERSION) { |
1864 | /* Check the version at the beginning of operations */ | 1864 | /* Check the version at the beginning of operations */ |
1865 | struct ip_set_req_version *req_version = data; | 1865 | struct ip_set_req_version *req_version = data; |
1866 | |||
1867 | if (*len < sizeof(struct ip_set_req_version)) { | ||
1868 | ret = -EINVAL; | ||
1869 | goto done; | ||
1870 | } | ||
1871 | |||
1866 | if (req_version->version != IPSET_PROTOCOL) { | 1872 | if (req_version->version != IPSET_PROTOCOL) { |
1867 | ret = -EPROTO; | 1873 | ret = -EPROTO; |
1868 | goto done; | 1874 | goto done; |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 91f17c1eb8a2..bd90bf8107da 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -316,7 +316,7 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, | |||
316 | if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode, | 316 | if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode, |
317 | local))) { | 317 | local))) { |
318 | IP_VS_DBG_RL("We are crossing local and non-local addresses" | 318 | IP_VS_DBG_RL("We are crossing local and non-local addresses" |
319 | " daddr=%pI4\n", &dest->addr.ip); | 319 | " daddr=%pI4\n", &daddr); |
320 | goto err_put; | 320 | goto err_put; |
321 | } | 321 | } |
322 | 322 | ||
@@ -458,7 +458,7 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, | |||
458 | if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode, | 458 | if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode, |
459 | local))) { | 459 | local))) { |
460 | IP_VS_DBG_RL("We are crossing local and non-local addresses" | 460 | IP_VS_DBG_RL("We are crossing local and non-local addresses" |
461 | " daddr=%pI6\n", &dest->addr.in6); | 461 | " daddr=%pI6\n", daddr); |
462 | goto err_put; | 462 | goto err_put; |
463 | } | 463 | } |
464 | 464 | ||
@@ -846,6 +846,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, | |||
846 | new_skb = skb_realloc_headroom(skb, max_headroom); | 846 | new_skb = skb_realloc_headroom(skb, max_headroom); |
847 | if (!new_skb) | 847 | if (!new_skb) |
848 | goto error; | 848 | goto error; |
849 | if (skb->sk) | ||
850 | skb_set_owner_w(new_skb, skb->sk); | ||
849 | consume_skb(skb); | 851 | consume_skb(skb); |
850 | skb = new_skb; | 852 | skb = new_skb; |
851 | } | 853 | } |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 5016a6929085..2c699757bccf 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -611,12 +611,16 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
611 | */ | 611 | */ |
612 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 612 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
613 | pr_debug("Confirming conntrack %p\n", ct); | 613 | pr_debug("Confirming conntrack %p\n", ct); |
614 | /* We have to check the DYING flag inside the lock to prevent | 614 | |
615 | a race against nf_ct_get_next_corpse() possibly called from | 615 | /* We have to check the DYING flag after unlink to prevent |
616 | user context, else we insert an already 'dead' hash, blocking | 616 | * a race against nf_ct_get_next_corpse() possibly called from |
617 | further use of that particular connection -JM */ | 617 | * user context, else we insert an already 'dead' hash, blocking |
618 | * further use of that particular connection -JM. | ||
619 | */ | ||
620 | nf_ct_del_from_dying_or_unconfirmed_list(ct); | ||
618 | 621 | ||
619 | if (unlikely(nf_ct_is_dying(ct))) { | 622 | if (unlikely(nf_ct_is_dying(ct))) { |
623 | nf_ct_add_to_dying_list(ct); | ||
620 | nf_conntrack_double_unlock(hash, reply_hash); | 624 | nf_conntrack_double_unlock(hash, reply_hash); |
621 | local_bh_enable(); | 625 | local_bh_enable(); |
622 | return NF_ACCEPT; | 626 | return NF_ACCEPT; |
@@ -636,8 +640,6 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
636 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | 640 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) |
637 | goto out; | 641 | goto out; |
638 | 642 | ||
639 | nf_ct_del_from_dying_or_unconfirmed_list(ct); | ||
640 | |||
641 | /* Timer relative to confirmation time, not original | 643 | /* Timer relative to confirmation time, not original |
642 | setting time, otherwise we'd get timer wrap in | 644 | setting time, otherwise we'd get timer wrap in |
643 | weird delay cases. */ | 645 | weird delay cases. */ |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 36a3ac8ee9f5..5caa0c41bf26 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -213,7 +213,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
213 | { | 213 | { |
214 | /* REPLY */ | 214 | /* REPLY */ |
215 | /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ | 215 | /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ |
216 | /*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 }, | 216 | /*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 }, |
217 | /* | 217 | /* |
218 | * sNO -> sIV Never reached. | 218 | * sNO -> sIV Never reached. |
219 | * sSS -> sS2 Simultaneous open | 219 | * sSS -> sS2 Simultaneous open |
@@ -223,7 +223,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
223 | * sFW -> sIV | 223 | * sFW -> sIV |
224 | * sCW -> sIV | 224 | * sCW -> sIV |
225 | * sLA -> sIV | 225 | * sLA -> sIV |
226 | * sTW -> sIV Reopened connection, but server may not do it. | 226 | * sTW -> sSS Reopened connection, but server may have switched role |
227 | * sCL -> sIV | 227 | * sCL -> sIV |
228 | */ | 228 | */ |
229 | /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ | 229 | /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 556a0dfa4abc..66e8425dbfe7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -1328,10 +1328,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
1328 | basechain->stats = stats; | 1328 | basechain->stats = stats; |
1329 | } else { | 1329 | } else { |
1330 | stats = netdev_alloc_pcpu_stats(struct nft_stats); | 1330 | stats = netdev_alloc_pcpu_stats(struct nft_stats); |
1331 | if (IS_ERR(stats)) { | 1331 | if (stats == NULL) { |
1332 | module_put(type->owner); | 1332 | module_put(type->owner); |
1333 | kfree(basechain); | 1333 | kfree(basechain); |
1334 | return PTR_ERR(stats); | 1334 | return -ENOMEM; |
1335 | } | 1335 | } |
1336 | rcu_assign_pointer(basechain->stats, stats); | 1336 | rcu_assign_pointer(basechain->stats, stats); |
1337 | } | 1337 | } |
@@ -3484,13 +3484,8 @@ static void nft_chain_commit_update(struct nft_trans *trans) | |||
3484 | } | 3484 | } |
3485 | } | 3485 | } |
3486 | 3486 | ||
3487 | /* Schedule objects for release via rcu to make sure no packets are accesing | 3487 | static void nf_tables_commit_release(struct nft_trans *trans) |
3488 | * removed rules. | ||
3489 | */ | ||
3490 | static void nf_tables_commit_release_rcu(struct rcu_head *rt) | ||
3491 | { | 3488 | { |
3492 | struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head); | ||
3493 | |||
3494 | switch (trans->msg_type) { | 3489 | switch (trans->msg_type) { |
3495 | case NFT_MSG_DELTABLE: | 3490 | case NFT_MSG_DELTABLE: |
3496 | nf_tables_table_destroy(&trans->ctx); | 3491 | nf_tables_table_destroy(&trans->ctx); |
@@ -3612,10 +3607,11 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3612 | } | 3607 | } |
3613 | } | 3608 | } |
3614 | 3609 | ||
3610 | synchronize_rcu(); | ||
3611 | |||
3615 | list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { | 3612 | list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { |
3616 | list_del(&trans->list); | 3613 | list_del(&trans->list); |
3617 | trans->ctx.nla = NULL; | 3614 | nf_tables_commit_release(trans); |
3618 | call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu); | ||
3619 | } | 3615 | } |
3620 | 3616 | ||
3621 | nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); | 3617 | nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); |
@@ -3623,13 +3619,8 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3623 | return 0; | 3619 | return 0; |
3624 | } | 3620 | } |
3625 | 3621 | ||
3626 | /* Schedule objects for release via rcu to make sure no packets are accesing | 3622 | static void nf_tables_abort_release(struct nft_trans *trans) |
3627 | * aborted rules. | ||
3628 | */ | ||
3629 | static void nf_tables_abort_release_rcu(struct rcu_head *rt) | ||
3630 | { | 3623 | { |
3631 | struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head); | ||
3632 | |||
3633 | switch (trans->msg_type) { | 3624 | switch (trans->msg_type) { |
3634 | case NFT_MSG_NEWTABLE: | 3625 | case NFT_MSG_NEWTABLE: |
3635 | nf_tables_table_destroy(&trans->ctx); | 3626 | nf_tables_table_destroy(&trans->ctx); |
@@ -3725,11 +3716,12 @@ static int nf_tables_abort(struct sk_buff *skb) | |||
3725 | } | 3716 | } |
3726 | } | 3717 | } |
3727 | 3718 | ||
3719 | synchronize_rcu(); | ||
3720 | |||
3728 | list_for_each_entry_safe_reverse(trans, next, | 3721 | list_for_each_entry_safe_reverse(trans, next, |
3729 | &net->nft.commit_list, list) { | 3722 | &net->nft.commit_list, list) { |
3730 | list_del(&trans->list); | 3723 | list_del(&trans->list); |
3731 | trans->ctx.nla = NULL; | 3724 | nf_tables_abort_release(trans); |
3732 | call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu); | ||
3733 | } | 3725 | } |
3734 | 3726 | ||
3735 | return 0; | 3727 | return 0; |
@@ -3744,6 +3736,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = { | |||
3744 | .abort = nf_tables_abort, | 3736 | .abort = nf_tables_abort, |
3745 | }; | 3737 | }; |
3746 | 3738 | ||
3739 | int nft_chain_validate_dependency(const struct nft_chain *chain, | ||
3740 | enum nft_chain_type type) | ||
3741 | { | ||
3742 | const struct nft_base_chain *basechain; | ||
3743 | |||
3744 | if (chain->flags & NFT_BASE_CHAIN) { | ||
3745 | basechain = nft_base_chain(chain); | ||
3746 | if (basechain->type->type != type) | ||
3747 | return -EOPNOTSUPP; | ||
3748 | } | ||
3749 | return 0; | ||
3750 | } | ||
3751 | EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); | ||
3752 | |||
3747 | /* | 3753 | /* |
3748 | * Loop detection - walk through the ruleset beginning at the destination chain | 3754 | * Loop detection - walk through the ruleset beginning at the destination chain |
3749 | * of a new jump until either the source chain is reached (loop) or all | 3755 | * of a new jump until either the source chain is reached (loop) or all |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 6c5a915cfa75..13c2e17bbe27 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -47,6 +47,8 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = { | |||
47 | [NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP, | 47 | [NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP, |
48 | [NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP, | 48 | [NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP, |
49 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, | 49 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, |
50 | [NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES, | ||
51 | [NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT, | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | void nfnl_lock(__u8 subsys_id) | 54 | void nfnl_lock(__u8 subsys_id) |
@@ -464,7 +466,12 @@ static void nfnetlink_rcv(struct sk_buff *skb) | |||
464 | static int nfnetlink_bind(int group) | 466 | static int nfnetlink_bind(int group) |
465 | { | 467 | { |
466 | const struct nfnetlink_subsystem *ss; | 468 | const struct nfnetlink_subsystem *ss; |
467 | int type = nfnl_group2type[group]; | 469 | int type; |
470 | |||
471 | if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX) | ||
472 | return -EINVAL; | ||
473 | |||
474 | type = nfnl_group2type[group]; | ||
468 | 475 | ||
469 | rcu_read_lock(); | 476 | rcu_read_lock(); |
470 | ss = nfnetlink_get_subsys(type); | 477 | ss = nfnetlink_get_subsys(type); |
@@ -514,6 +521,9 @@ static int __init nfnetlink_init(void) | |||
514 | { | 521 | { |
515 | int i; | 522 | int i; |
516 | 523 | ||
524 | for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++) | ||
525 | BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE); | ||
526 | |||
517 | for (i=0; i<NFNL_SUBSYS_COUNT; i++) | 527 | for (i=0; i<NFNL_SUBSYS_COUNT; i++) |
518 | mutex_init(&table[i].mutex); | 528 | mutex_init(&table[i].mutex); |
519 | 529 | ||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index b1e3a0579416..5f1be5ba3559 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -43,7 +43,8 @@ | |||
43 | #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE | 43 | #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE |
44 | #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ | 44 | #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ |
45 | #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ | 45 | #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ |
46 | #define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ | 46 | /* max packet size is limited by 16-bit struct nfattr nfa_len field */ |
47 | #define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN) | ||
47 | 48 | ||
48 | #define PRINTR(x, args...) do { if (net_ratelimit()) \ | 49 | #define PRINTR(x, args...) do { if (net_ratelimit()) \ |
49 | printk(x, ## args); } while (0); | 50 | printk(x, ## args); } while (0); |
@@ -252,6 +253,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode, | |||
252 | 253 | ||
253 | case NFULNL_COPY_PACKET: | 254 | case NFULNL_COPY_PACKET: |
254 | inst->copy_mode = mode; | 255 | inst->copy_mode = mode; |
256 | if (range == 0) | ||
257 | range = NFULNL_COPY_RANGE_MAX; | ||
255 | inst->copy_range = min_t(unsigned int, | 258 | inst->copy_range = min_t(unsigned int, |
256 | range, NFULNL_COPY_RANGE_MAX); | 259 | range, NFULNL_COPY_RANGE_MAX); |
257 | break; | 260 | break; |
@@ -343,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size, | |||
343 | return skb; | 346 | return skb; |
344 | } | 347 | } |
345 | 348 | ||
346 | static int | 349 | static void |
347 | __nfulnl_send(struct nfulnl_instance *inst) | 350 | __nfulnl_send(struct nfulnl_instance *inst) |
348 | { | 351 | { |
349 | int status = -1; | ||
350 | |||
351 | if (inst->qlen > 1) { | 352 | if (inst->qlen > 1) { |
352 | struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, | 353 | struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, |
353 | NLMSG_DONE, | 354 | NLMSG_DONE, |
354 | sizeof(struct nfgenmsg), | 355 | sizeof(struct nfgenmsg), |
355 | 0); | 356 | 0); |
356 | if (!nlh) | 357 | if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n", |
358 | inst->skb->len, skb_tailroom(inst->skb))) { | ||
359 | kfree_skb(inst->skb); | ||
357 | goto out; | 360 | goto out; |
361 | } | ||
358 | } | 362 | } |
359 | status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, | 363 | nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, |
360 | MSG_DONTWAIT); | 364 | MSG_DONTWAIT); |
361 | 365 | out: | |
362 | inst->qlen = 0; | 366 | inst->qlen = 0; |
363 | inst->skb = NULL; | 367 | inst->skb = NULL; |
364 | out: | ||
365 | return status; | ||
366 | } | 368 | } |
367 | 369 | ||
368 | static void | 370 | static void |
@@ -649,7 +651,8 @@ nfulnl_log_packet(struct net *net, | |||
649 | + nla_total_size(sizeof(u_int32_t)) /* gid */ | 651 | + nla_total_size(sizeof(u_int32_t)) /* gid */ |
650 | + nla_total_size(plen) /* prefix */ | 652 | + nla_total_size(plen) /* prefix */ |
651 | + nla_total_size(sizeof(struct nfulnl_msg_packet_hw)) | 653 | + nla_total_size(sizeof(struct nfulnl_msg_packet_hw)) |
652 | + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)); | 654 | + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)) |
655 | + nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */ | ||
653 | 656 | ||
654 | if (in && skb_mac_header_was_set(skb)) { | 657 | if (in && skb_mac_header_was_set(skb)) { |
655 | size += nla_total_size(skb->dev->hard_header_len) | 658 | size += nla_total_size(skb->dev->hard_header_len) |
@@ -678,8 +681,7 @@ nfulnl_log_packet(struct net *net, | |||
678 | break; | 681 | break; |
679 | 682 | ||
680 | case NFULNL_COPY_PACKET: | 683 | case NFULNL_COPY_PACKET: |
681 | if (inst->copy_range == 0 | 684 | if (inst->copy_range > skb->len) |
682 | || inst->copy_range > skb->len) | ||
683 | data_len = skb->len; | 685 | data_len = skb->len; |
684 | else | 686 | else |
685 | data_len = inst->copy_range; | 687 | data_len = inst->copy_range; |
@@ -692,8 +694,7 @@ nfulnl_log_packet(struct net *net, | |||
692 | goto unlock_and_release; | 694 | goto unlock_and_release; |
693 | } | 695 | } |
694 | 696 | ||
695 | if (inst->skb && | 697 | if (inst->skb && size > skb_tailroom(inst->skb)) { |
696 | size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) { | ||
697 | /* either the queue len is too high or we don't have | 698 | /* either the queue len is too high or we don't have |
698 | * enough room in the skb left. flush to userspace. */ | 699 | * enough room in the skb left. flush to userspace. */ |
699 | __nfulnl_flush(inst); | 700 | __nfulnl_flush(inst); |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index f823f1538c4f..0db8515e76da 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -665,7 +665,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
665 | * returned by nf_queue. For instance, callers rely on -ECANCELED to | 665 | * returned by nf_queue. For instance, callers rely on -ECANCELED to |
666 | * mean 'ignore this hook'. | 666 | * mean 'ignore this hook'. |
667 | */ | 667 | */ |
668 | if (IS_ERR(segs)) | 668 | if (IS_ERR_OR_NULL(segs)) |
669 | goto out_err; | 669 | goto out_err; |
670 | queued = 0; | 670 | queued = 0; |
671 | err = 0; | 671 | err = 0; |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 7e2683c8a44a..265e190f2218 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -19,9 +19,24 @@ | |||
19 | #include <linux/netfilter/x_tables.h> | 19 | #include <linux/netfilter/x_tables.h> |
20 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | #include <linux/netfilter_ipv4/ip_tables.h> |
21 | #include <linux/netfilter_ipv6/ip6_tables.h> | 21 | #include <linux/netfilter_ipv6/ip6_tables.h> |
22 | #include <asm/uaccess.h> /* for set_fs */ | ||
23 | #include <net/netfilter/nf_tables.h> | 22 | #include <net/netfilter/nf_tables.h> |
24 | 23 | ||
24 | static int nft_compat_chain_validate_dependency(const char *tablename, | ||
25 | const struct nft_chain *chain) | ||
26 | { | ||
27 | const struct nft_base_chain *basechain; | ||
28 | |||
29 | if (!tablename || !(chain->flags & NFT_BASE_CHAIN)) | ||
30 | return 0; | ||
31 | |||
32 | basechain = nft_base_chain(chain); | ||
33 | if (strcmp(tablename, "nat") == 0 && | ||
34 | basechain->type->type != NFT_CHAIN_T_NAT) | ||
35 | return -EINVAL; | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | |||
25 | union nft_entry { | 40 | union nft_entry { |
26 | struct ipt_entry e4; | 41 | struct ipt_entry e4; |
27 | struct ip6t_entry e6; | 42 | struct ip6t_entry e6; |
@@ -74,7 +89,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, | |||
74 | struct xt_target *target, void *info, | 89 | struct xt_target *target, void *info, |
75 | union nft_entry *entry, u8 proto, bool inv) | 90 | union nft_entry *entry, u8 proto, bool inv) |
76 | { | 91 | { |
77 | par->net = &init_net; | 92 | par->net = ctx->net; |
78 | par->table = ctx->table->name; | 93 | par->table = ctx->table->name; |
79 | switch (ctx->afi->family) { | 94 | switch (ctx->afi->family) { |
80 | case AF_INET: | 95 | case AF_INET: |
@@ -95,6 +110,8 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, | |||
95 | const struct nf_hook_ops *ops = &basechain->ops[0]; | 110 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
96 | 111 | ||
97 | par->hook_mask = 1 << ops->hooknum; | 112 | par->hook_mask = 1 << ops->hooknum; |
113 | } else { | ||
114 | par->hook_mask = 0; | ||
98 | } | 115 | } |
99 | par->family = ctx->afi->family; | 116 | par->family = ctx->afi->family; |
100 | } | 117 | } |
@@ -151,6 +168,10 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
151 | union nft_entry e = {}; | 168 | union nft_entry e = {}; |
152 | int ret; | 169 | int ret; |
153 | 170 | ||
171 | ret = nft_compat_chain_validate_dependency(target->table, ctx->chain); | ||
172 | if (ret < 0) | ||
173 | goto err; | ||
174 | |||
154 | target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info); | 175 | target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info); |
155 | 176 | ||
156 | if (ctx->nla[NFTA_RULE_COMPAT]) { | 177 | if (ctx->nla[NFTA_RULE_COMPAT]) { |
@@ -216,6 +237,7 @@ static int nft_target_validate(const struct nft_ctx *ctx, | |||
216 | { | 237 | { |
217 | struct xt_target *target = expr->ops->data; | 238 | struct xt_target *target = expr->ops->data; |
218 | unsigned int hook_mask = 0; | 239 | unsigned int hook_mask = 0; |
240 | int ret; | ||
219 | 241 | ||
220 | if (ctx->chain->flags & NFT_BASE_CHAIN) { | 242 | if (ctx->chain->flags & NFT_BASE_CHAIN) { |
221 | const struct nft_base_chain *basechain = | 243 | const struct nft_base_chain *basechain = |
@@ -223,11 +245,13 @@ static int nft_target_validate(const struct nft_ctx *ctx, | |||
223 | const struct nf_hook_ops *ops = &basechain->ops[0]; | 245 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
224 | 246 | ||
225 | hook_mask = 1 << ops->hooknum; | 247 | hook_mask = 1 << ops->hooknum; |
226 | if (hook_mask & target->hooks) | 248 | if (!(hook_mask & target->hooks)) |
227 | return 0; | 249 | return -EINVAL; |
228 | 250 | ||
229 | /* This target is being called from an invalid chain */ | 251 | ret = nft_compat_chain_validate_dependency(target->table, |
230 | return -EINVAL; | 252 | ctx->chain); |
253 | if (ret < 0) | ||
254 | return ret; | ||
231 | } | 255 | } |
232 | return 0; | 256 | return 0; |
233 | } | 257 | } |
@@ -272,7 +296,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, | |||
272 | struct xt_match *match, void *info, | 296 | struct xt_match *match, void *info, |
273 | union nft_entry *entry, u8 proto, bool inv) | 297 | union nft_entry *entry, u8 proto, bool inv) |
274 | { | 298 | { |
275 | par->net = &init_net; | 299 | par->net = ctx->net; |
276 | par->table = ctx->table->name; | 300 | par->table = ctx->table->name; |
277 | switch (ctx->afi->family) { | 301 | switch (ctx->afi->family) { |
278 | case AF_INET: | 302 | case AF_INET: |
@@ -293,6 +317,8 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, | |||
293 | const struct nf_hook_ops *ops = &basechain->ops[0]; | 317 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
294 | 318 | ||
295 | par->hook_mask = 1 << ops->hooknum; | 319 | par->hook_mask = 1 << ops->hooknum; |
320 | } else { | ||
321 | par->hook_mask = 0; | ||
296 | } | 322 | } |
297 | par->family = ctx->afi->family; | 323 | par->family = ctx->afi->family; |
298 | } | 324 | } |
@@ -320,6 +346,10 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
320 | union nft_entry e = {}; | 346 | union nft_entry e = {}; |
321 | int ret; | 347 | int ret; |
322 | 348 | ||
349 | ret = nft_compat_chain_validate_dependency(match->table, ctx->chain); | ||
350 | if (ret < 0) | ||
351 | goto err; | ||
352 | |||
323 | match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info); | 353 | match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info); |
324 | 354 | ||
325 | if (ctx->nla[NFTA_RULE_COMPAT]) { | 355 | if (ctx->nla[NFTA_RULE_COMPAT]) { |
@@ -379,6 +409,7 @@ static int nft_match_validate(const struct nft_ctx *ctx, | |||
379 | { | 409 | { |
380 | struct xt_match *match = expr->ops->data; | 410 | struct xt_match *match = expr->ops->data; |
381 | unsigned int hook_mask = 0; | 411 | unsigned int hook_mask = 0; |
412 | int ret; | ||
382 | 413 | ||
383 | if (ctx->chain->flags & NFT_BASE_CHAIN) { | 414 | if (ctx->chain->flags & NFT_BASE_CHAIN) { |
384 | const struct nft_base_chain *basechain = | 415 | const struct nft_base_chain *basechain = |
@@ -386,11 +417,13 @@ static int nft_match_validate(const struct nft_ctx *ctx, | |||
386 | const struct nf_hook_ops *ops = &basechain->ops[0]; | 417 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
387 | 418 | ||
388 | hook_mask = 1 << ops->hooknum; | 419 | hook_mask = 1 << ops->hooknum; |
389 | if (hook_mask & match->hooks) | 420 | if (!(hook_mask & match->hooks)) |
390 | return 0; | 421 | return -EINVAL; |
391 | 422 | ||
392 | /* This match is being called from an invalid chain */ | 423 | ret = nft_compat_chain_validate_dependency(match->table, |
393 | return -EINVAL; | 424 | ctx->chain); |
425 | if (ret < 0) | ||
426 | return ret; | ||
394 | } | 427 | } |
395 | return 0; | 428 | return 0; |
396 | } | 429 | } |
@@ -611,7 +644,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
611 | family = ctx->afi->family; | 644 | family = ctx->afi->family; |
612 | 645 | ||
613 | /* Re-use the existing target if it's already loaded. */ | 646 | /* Re-use the existing target if it's already loaded. */ |
614 | list_for_each_entry(nft_target, &nft_match_list, head) { | 647 | list_for_each_entry(nft_target, &nft_target_list, head) { |
615 | struct xt_target *target = nft_target->ops.data; | 648 | struct xt_target *target = nft_target->ops.data; |
616 | 649 | ||
617 | if (strcmp(target->name, tg_name) == 0 && | 650 | if (strcmp(target->name, tg_name) == 0 && |
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c index 6637bab00567..d1ffd5eb3a9b 100644 --- a/net/netfilter/nft_masq.c +++ b/net/netfilter/nft_masq.c | |||
@@ -26,6 +26,11 @@ int nft_masq_init(const struct nft_ctx *ctx, | |||
26 | const struct nlattr * const tb[]) | 26 | const struct nlattr * const tb[]) |
27 | { | 27 | { |
28 | struct nft_masq *priv = nft_expr_priv(expr); | 28 | struct nft_masq *priv = nft_expr_priv(expr); |
29 | int err; | ||
30 | |||
31 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
32 | if (err < 0) | ||
33 | return err; | ||
29 | 34 | ||
30 | if (tb[NFTA_MASQ_FLAGS] == NULL) | 35 | if (tb[NFTA_MASQ_FLAGS] == NULL) |
31 | return 0; | 36 | return 0; |
@@ -55,5 +60,12 @@ nla_put_failure: | |||
55 | } | 60 | } |
56 | EXPORT_SYMBOL_GPL(nft_masq_dump); | 61 | EXPORT_SYMBOL_GPL(nft_masq_dump); |
57 | 62 | ||
63 | int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
64 | const struct nft_data **data) | ||
65 | { | ||
66 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
67 | } | ||
68 | EXPORT_SYMBOL_GPL(nft_masq_validate); | ||
69 | |||
58 | MODULE_LICENSE("GPL"); | 70 | MODULE_LICENSE("GPL"); |
59 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); | 71 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); |
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index 799550b476fb..afe2b0b45ec4 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c | |||
@@ -95,7 +95,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
95 | u32 family; | 95 | u32 family; |
96 | int err; | 96 | int err; |
97 | 97 | ||
98 | if (tb[NFTA_NAT_TYPE] == NULL) | 98 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); |
99 | if (err < 0) | ||
100 | return err; | ||
101 | |||
102 | if (tb[NFTA_NAT_TYPE] == NULL || | ||
103 | (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && | ||
104 | tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) | ||
99 | return -EINVAL; | 105 | return -EINVAL; |
100 | 106 | ||
101 | switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) { | 107 | switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) { |
@@ -120,38 +126,44 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
120 | priv->family = family; | 126 | priv->family = family; |
121 | 127 | ||
122 | if (tb[NFTA_NAT_REG_ADDR_MIN]) { | 128 | if (tb[NFTA_NAT_REG_ADDR_MIN]) { |
123 | priv->sreg_addr_min = ntohl(nla_get_be32( | 129 | priv->sreg_addr_min = |
124 | tb[NFTA_NAT_REG_ADDR_MIN])); | 130 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN])); |
131 | |||
125 | err = nft_validate_input_register(priv->sreg_addr_min); | 132 | err = nft_validate_input_register(priv->sreg_addr_min); |
126 | if (err < 0) | 133 | if (err < 0) |
127 | return err; | 134 | return err; |
128 | } | ||
129 | 135 | ||
130 | if (tb[NFTA_NAT_REG_ADDR_MAX]) { | 136 | if (tb[NFTA_NAT_REG_ADDR_MAX]) { |
131 | priv->sreg_addr_max = ntohl(nla_get_be32( | 137 | priv->sreg_addr_max = |
132 | tb[NFTA_NAT_REG_ADDR_MAX])); | 138 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX])); |
133 | err = nft_validate_input_register(priv->sreg_addr_max); | 139 | |
134 | if (err < 0) | 140 | err = nft_validate_input_register(priv->sreg_addr_max); |
135 | return err; | 141 | if (err < 0) |
136 | } else | 142 | return err; |
137 | priv->sreg_addr_max = priv->sreg_addr_min; | 143 | } else { |
144 | priv->sreg_addr_max = priv->sreg_addr_min; | ||
145 | } | ||
146 | } | ||
138 | 147 | ||
139 | if (tb[NFTA_NAT_REG_PROTO_MIN]) { | 148 | if (tb[NFTA_NAT_REG_PROTO_MIN]) { |
140 | priv->sreg_proto_min = ntohl(nla_get_be32( | 149 | priv->sreg_proto_min = |
141 | tb[NFTA_NAT_REG_PROTO_MIN])); | 150 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN])); |
151 | |||
142 | err = nft_validate_input_register(priv->sreg_proto_min); | 152 | err = nft_validate_input_register(priv->sreg_proto_min); |
143 | if (err < 0) | 153 | if (err < 0) |
144 | return err; | 154 | return err; |
145 | } | ||
146 | 155 | ||
147 | if (tb[NFTA_NAT_REG_PROTO_MAX]) { | 156 | if (tb[NFTA_NAT_REG_PROTO_MAX]) { |
148 | priv->sreg_proto_max = ntohl(nla_get_be32( | 157 | priv->sreg_proto_max = |
149 | tb[NFTA_NAT_REG_PROTO_MAX])); | 158 | ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX])); |
150 | err = nft_validate_input_register(priv->sreg_proto_max); | 159 | |
151 | if (err < 0) | 160 | err = nft_validate_input_register(priv->sreg_proto_max); |
152 | return err; | 161 | if (err < 0) |
153 | } else | 162 | return err; |
154 | priv->sreg_proto_max = priv->sreg_proto_min; | 163 | } else { |
164 | priv->sreg_proto_max = priv->sreg_proto_min; | ||
165 | } | ||
166 | } | ||
155 | 167 | ||
156 | if (tb[NFTA_NAT_FLAGS]) { | 168 | if (tb[NFTA_NAT_FLAGS]) { |
157 | priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS])); | 169 | priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS])); |
@@ -179,17 +191,19 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
179 | 191 | ||
180 | if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family))) | 192 | if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family))) |
181 | goto nla_put_failure; | 193 | goto nla_put_failure; |
182 | if (nla_put_be32(skb, | 194 | |
183 | NFTA_NAT_REG_ADDR_MIN, htonl(priv->sreg_addr_min))) | 195 | if (priv->sreg_addr_min) { |
184 | goto nla_put_failure; | 196 | if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN, |
185 | if (nla_put_be32(skb, | 197 | htonl(priv->sreg_addr_min)) || |
186 | NFTA_NAT_REG_ADDR_MAX, htonl(priv->sreg_addr_max))) | 198 | nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX, |
187 | goto nla_put_failure; | 199 | htonl(priv->sreg_addr_max))) |
200 | goto nla_put_failure; | ||
201 | } | ||
202 | |||
188 | if (priv->sreg_proto_min) { | 203 | if (priv->sreg_proto_min) { |
189 | if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN, | 204 | if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN, |
190 | htonl(priv->sreg_proto_min))) | 205 | htonl(priv->sreg_proto_min)) || |
191 | goto nla_put_failure; | 206 | nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX, |
192 | if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX, | ||
193 | htonl(priv->sreg_proto_max))) | 207 | htonl(priv->sreg_proto_max))) |
194 | goto nla_put_failure; | 208 | goto nla_put_failure; |
195 | } | 209 | } |
@@ -205,6 +219,13 @@ nla_put_failure: | |||
205 | return -1; | 219 | return -1; |
206 | } | 220 | } |
207 | 221 | ||
222 | static int nft_nat_validate(const struct nft_ctx *ctx, | ||
223 | const struct nft_expr *expr, | ||
224 | const struct nft_data **data) | ||
225 | { | ||
226 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
227 | } | ||
228 | |||
208 | static struct nft_expr_type nft_nat_type; | 229 | static struct nft_expr_type nft_nat_type; |
209 | static const struct nft_expr_ops nft_nat_ops = { | 230 | static const struct nft_expr_ops nft_nat_ops = { |
210 | .type = &nft_nat_type, | 231 | .type = &nft_nat_type, |
@@ -212,6 +233,7 @@ static const struct nft_expr_ops nft_nat_ops = { | |||
212 | .eval = nft_nat_eval, | 233 | .eval = nft_nat_eval, |
213 | .init = nft_nat_init, | 234 | .init = nft_nat_init, |
214 | .dump = nft_nat_dump, | 235 | .dump = nft_nat_dump, |
236 | .validate = nft_nat_validate, | ||
215 | }; | 237 | }; |
216 | 238 | ||
217 | static struct nft_expr_type nft_nat_type __read_mostly = { | 239 | static struct nft_expr_type nft_nat_type __read_mostly = { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 7a186e74b1b3..0007b8180397 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -96,6 +96,14 @@ static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); | |||
96 | static int netlink_dump(struct sock *sk); | 96 | static int netlink_dump(struct sock *sk); |
97 | static void netlink_skb_destructor(struct sk_buff *skb); | 97 | static void netlink_skb_destructor(struct sk_buff *skb); |
98 | 98 | ||
99 | /* nl_table locking explained: | ||
100 | * Lookup and traversal are protected with nl_sk_hash_lock or nl_table_lock | ||
101 | * combined with an RCU read-side lock. Insertion and removal are protected | ||
102 | * with nl_sk_hash_lock while using RCU list modification primitives and may | ||
103 | * run in parallel to nl_table_lock protected lookups. Destruction of the | ||
104 | * Netlink socket may only occur *after* nl_table_lock has been acquired | ||
105 | * either during or after the socket has been removed from the list. | ||
106 | */ | ||
99 | DEFINE_RWLOCK(nl_table_lock); | 107 | DEFINE_RWLOCK(nl_table_lock); |
100 | EXPORT_SYMBOL_GPL(nl_table_lock); | 108 | EXPORT_SYMBOL_GPL(nl_table_lock); |
101 | static atomic_t nl_table_users = ATOMIC_INIT(0); | 109 | static atomic_t nl_table_users = ATOMIC_INIT(0); |
@@ -109,10 +117,10 @@ EXPORT_SYMBOL_GPL(nl_sk_hash_lock); | |||
109 | static int lockdep_nl_sk_hash_is_held(void) | 117 | static int lockdep_nl_sk_hash_is_held(void) |
110 | { | 118 | { |
111 | #ifdef CONFIG_LOCKDEP | 119 | #ifdef CONFIG_LOCKDEP |
112 | return (debug_locks) ? lockdep_is_held(&nl_sk_hash_lock) : 1; | 120 | if (debug_locks) |
113 | #else | 121 | return lockdep_is_held(&nl_sk_hash_lock) || lockdep_is_held(&nl_table_lock); |
114 | return 1; | ||
115 | #endif | 122 | #endif |
123 | return 1; | ||
116 | } | 124 | } |
117 | 125 | ||
118 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); | 126 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); |
@@ -1028,11 +1036,13 @@ static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) | |||
1028 | struct netlink_table *table = &nl_table[protocol]; | 1036 | struct netlink_table *table = &nl_table[protocol]; |
1029 | struct sock *sk; | 1037 | struct sock *sk; |
1030 | 1038 | ||
1039 | read_lock(&nl_table_lock); | ||
1031 | rcu_read_lock(); | 1040 | rcu_read_lock(); |
1032 | sk = __netlink_lookup(table, portid, net); | 1041 | sk = __netlink_lookup(table, portid, net); |
1033 | if (sk) | 1042 | if (sk) |
1034 | sock_hold(sk); | 1043 | sock_hold(sk); |
1035 | rcu_read_unlock(); | 1044 | rcu_read_unlock(); |
1045 | read_unlock(&nl_table_lock); | ||
1036 | 1046 | ||
1037 | return sk; | 1047 | return sk; |
1038 | } | 1048 | } |
@@ -1257,9 +1267,6 @@ static int netlink_release(struct socket *sock) | |||
1257 | } | 1267 | } |
1258 | netlink_table_ungrab(); | 1268 | netlink_table_ungrab(); |
1259 | 1269 | ||
1260 | /* Wait for readers to complete */ | ||
1261 | synchronize_net(); | ||
1262 | |||
1263 | kfree(nlk->groups); | 1270 | kfree(nlk->groups); |
1264 | nlk->groups = NULL; | 1271 | nlk->groups = NULL; |
1265 | 1272 | ||
@@ -1281,6 +1288,7 @@ static int netlink_autobind(struct socket *sock) | |||
1281 | 1288 | ||
1282 | retry: | 1289 | retry: |
1283 | cond_resched(); | 1290 | cond_resched(); |
1291 | netlink_table_grab(); | ||
1284 | rcu_read_lock(); | 1292 | rcu_read_lock(); |
1285 | if (__netlink_lookup(table, portid, net)) { | 1293 | if (__netlink_lookup(table, portid, net)) { |
1286 | /* Bind collision, search negative portid values. */ | 1294 | /* Bind collision, search negative portid values. */ |
@@ -1288,9 +1296,11 @@ retry: | |||
1288 | if (rover > -4097) | 1296 | if (rover > -4097) |
1289 | rover = -4097; | 1297 | rover = -4097; |
1290 | rcu_read_unlock(); | 1298 | rcu_read_unlock(); |
1299 | netlink_table_ungrab(); | ||
1291 | goto retry; | 1300 | goto retry; |
1292 | } | 1301 | } |
1293 | rcu_read_unlock(); | 1302 | rcu_read_unlock(); |
1303 | netlink_table_ungrab(); | ||
1294 | 1304 | ||
1295 | err = netlink_insert(sk, net, portid); | 1305 | err = netlink_insert(sk, net, portid); |
1296 | if (err == -EADDRINUSE) | 1306 | if (err == -EADDRINUSE) |
@@ -1430,7 +1440,7 @@ static void netlink_unbind(int group, long unsigned int groups, | |||
1430 | return; | 1440 | return; |
1431 | 1441 | ||
1432 | for (undo = 0; undo < group; undo++) | 1442 | for (undo = 0; undo < group; undo++) |
1433 | if (test_bit(group, &groups)) | 1443 | if (test_bit(undo, &groups)) |
1434 | nlk->netlink_unbind(undo); | 1444 | nlk->netlink_unbind(undo); |
1435 | } | 1445 | } |
1436 | 1446 | ||
@@ -1482,7 +1492,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
1482 | netlink_insert(sk, net, nladdr->nl_pid) : | 1492 | netlink_insert(sk, net, nladdr->nl_pid) : |
1483 | netlink_autobind(sock); | 1493 | netlink_autobind(sock); |
1484 | if (err) { | 1494 | if (err) { |
1485 | netlink_unbind(nlk->ngroups - 1, groups, nlk); | 1495 | netlink_unbind(nlk->ngroups, groups, nlk); |
1486 | return err; | 1496 | return err; |
1487 | } | 1497 | } |
1488 | } | 1498 | } |
@@ -2499,6 +2509,7 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module, | |||
2499 | nl_table[unit].module = module; | 2509 | nl_table[unit].module = module; |
2500 | if (cfg) { | 2510 | if (cfg) { |
2501 | nl_table[unit].bind = cfg->bind; | 2511 | nl_table[unit].bind = cfg->bind; |
2512 | nl_table[unit].unbind = cfg->unbind; | ||
2502 | nl_table[unit].flags = cfg->flags; | 2513 | nl_table[unit].flags = cfg->flags; |
2503 | if (cfg->compare) | 2514 | if (cfg->compare) |
2504 | nl_table[unit].compare = cfg->compare; | 2515 | nl_table[unit].compare = cfg->compare; |
@@ -2921,14 +2932,16 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) | |||
2921 | } | 2932 | } |
2922 | 2933 | ||
2923 | static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) | 2934 | static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) |
2924 | __acquires(RCU) | 2935 | __acquires(nl_table_lock) __acquires(RCU) |
2925 | { | 2936 | { |
2937 | read_lock(&nl_table_lock); | ||
2926 | rcu_read_lock(); | 2938 | rcu_read_lock(); |
2927 | return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 2939 | return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
2928 | } | 2940 | } |
2929 | 2941 | ||
2930 | static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 2942 | static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
2931 | { | 2943 | { |
2944 | struct rhashtable *ht; | ||
2932 | struct netlink_sock *nlk; | 2945 | struct netlink_sock *nlk; |
2933 | struct nl_seq_iter *iter; | 2946 | struct nl_seq_iter *iter; |
2934 | struct net *net; | 2947 | struct net *net; |
@@ -2943,19 +2956,19 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2943 | iter = seq->private; | 2956 | iter = seq->private; |
2944 | nlk = v; | 2957 | nlk = v; |
2945 | 2958 | ||
2946 | rht_for_each_entry_rcu(nlk, nlk->node.next, node) | 2959 | i = iter->link; |
2960 | ht = &nl_table[i].hash; | ||
2961 | rht_for_each_entry(nlk, nlk->node.next, ht, node) | ||
2947 | if (net_eq(sock_net((struct sock *)nlk), net)) | 2962 | if (net_eq(sock_net((struct sock *)nlk), net)) |
2948 | return nlk; | 2963 | return nlk; |
2949 | 2964 | ||
2950 | i = iter->link; | ||
2951 | j = iter->hash_idx + 1; | 2965 | j = iter->hash_idx + 1; |
2952 | 2966 | ||
2953 | do { | 2967 | do { |
2954 | struct rhashtable *ht = &nl_table[i].hash; | ||
2955 | const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); | 2968 | const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); |
2956 | 2969 | ||
2957 | for (; j < tbl->size; j++) { | 2970 | for (; j < tbl->size; j++) { |
2958 | rht_for_each_entry_rcu(nlk, tbl->buckets[j], node) { | 2971 | rht_for_each_entry(nlk, tbl->buckets[j], ht, node) { |
2959 | if (net_eq(sock_net((struct sock *)nlk), net)) { | 2972 | if (net_eq(sock_net((struct sock *)nlk), net)) { |
2960 | iter->link = i; | 2973 | iter->link = i; |
2961 | iter->hash_idx = j; | 2974 | iter->hash_idx = j; |
@@ -2971,9 +2984,10 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2971 | } | 2984 | } |
2972 | 2985 | ||
2973 | static void netlink_seq_stop(struct seq_file *seq, void *v) | 2986 | static void netlink_seq_stop(struct seq_file *seq, void *v) |
2974 | __releases(RCU) | 2987 | __releases(RCU) __releases(nl_table_lock) |
2975 | { | 2988 | { |
2976 | rcu_read_unlock(); | 2989 | rcu_read_unlock(); |
2990 | read_unlock(&nl_table_lock); | ||
2977 | } | 2991 | } |
2978 | 2992 | ||
2979 | 2993 | ||
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 006886dbee36..8c4229b11c34 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -246,11 +246,11 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto, | |||
246 | { | 246 | { |
247 | int transport_len = skb->len - skb_transport_offset(skb); | 247 | int transport_len = skb->len - skb_transport_offset(skb); |
248 | 248 | ||
249 | if (l4_proto == IPPROTO_TCP) { | 249 | if (l4_proto == NEXTHDR_TCP) { |
250 | if (likely(transport_len >= sizeof(struct tcphdr))) | 250 | if (likely(transport_len >= sizeof(struct tcphdr))) |
251 | inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb, | 251 | inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb, |
252 | addr, new_addr, 1); | 252 | addr, new_addr, 1); |
253 | } else if (l4_proto == IPPROTO_UDP) { | 253 | } else if (l4_proto == NEXTHDR_UDP) { |
254 | if (likely(transport_len >= sizeof(struct udphdr))) { | 254 | if (likely(transport_len >= sizeof(struct udphdr))) { |
255 | struct udphdr *uh = udp_hdr(skb); | 255 | struct udphdr *uh = udp_hdr(skb); |
256 | 256 | ||
@@ -261,6 +261,10 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto, | |||
261 | uh->check = CSUM_MANGLED_0; | 261 | uh->check = CSUM_MANGLED_0; |
262 | } | 262 | } |
263 | } | 263 | } |
264 | } else if (l4_proto == NEXTHDR_ICMP) { | ||
265 | if (likely(transport_len >= sizeof(struct icmp6hdr))) | ||
266 | inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum, | ||
267 | skb, addr, new_addr, 1); | ||
264 | } | 268 | } |
265 | } | 269 | } |
266 | 270 | ||
@@ -722,8 +726,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, | |||
722 | 726 | ||
723 | case OVS_ACTION_ATTR_SAMPLE: | 727 | case OVS_ACTION_ATTR_SAMPLE: |
724 | err = sample(dp, skb, key, a); | 728 | err = sample(dp, skb, key, a); |
725 | if (unlikely(err)) /* skb already freed. */ | ||
726 | return err; | ||
727 | break; | 729 | break; |
728 | } | 730 | } |
729 | 731 | ||
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 2e31d9e7f4dc..f9e556b56086 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -324,6 +324,8 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, | |||
324 | segs = __skb_gso_segment(skb, NETIF_F_SG, false); | 324 | segs = __skb_gso_segment(skb, NETIF_F_SG, false); |
325 | if (IS_ERR(segs)) | 325 | if (IS_ERR(segs)) |
326 | return PTR_ERR(segs); | 326 | return PTR_ERR(segs); |
327 | if (segs == NULL) | ||
328 | return -EINVAL; | ||
327 | 329 | ||
328 | /* Queue all of the segments. */ | 330 | /* Queue all of the segments. */ |
329 | skb = segs; | 331 | skb = segs; |
@@ -1263,7 +1265,7 @@ static size_t ovs_dp_cmd_msg_size(void) | |||
1263 | return msgsize; | 1265 | return msgsize; |
1264 | } | 1266 | } |
1265 | 1267 | ||
1266 | /* Called with ovs_mutex or RCU read lock. */ | 1268 | /* Called with ovs_mutex. */ |
1267 | static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, | 1269 | static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, |
1268 | u32 portid, u32 seq, u32 flags, u8 cmd) | 1270 | u32 portid, u32 seq, u32 flags, u8 cmd) |
1269 | { | 1271 | { |
@@ -1553,7 +1555,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1553 | if (!reply) | 1555 | if (!reply) |
1554 | return -ENOMEM; | 1556 | return -ENOMEM; |
1555 | 1557 | ||
1556 | rcu_read_lock(); | 1558 | ovs_lock(); |
1557 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); | 1559 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); |
1558 | if (IS_ERR(dp)) { | 1560 | if (IS_ERR(dp)) { |
1559 | err = PTR_ERR(dp); | 1561 | err = PTR_ERR(dp); |
@@ -1562,12 +1564,12 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1562 | err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, | 1564 | err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, |
1563 | info->snd_seq, 0, OVS_DP_CMD_NEW); | 1565 | info->snd_seq, 0, OVS_DP_CMD_NEW); |
1564 | BUG_ON(err < 0); | 1566 | BUG_ON(err < 0); |
1565 | rcu_read_unlock(); | 1567 | ovs_unlock(); |
1566 | 1568 | ||
1567 | return genlmsg_reply(reply, info); | 1569 | return genlmsg_reply(reply, info); |
1568 | 1570 | ||
1569 | err_unlock_free: | 1571 | err_unlock_free: |
1570 | rcu_read_unlock(); | 1572 | ovs_unlock(); |
1571 | kfree_skb(reply); | 1573 | kfree_skb(reply); |
1572 | return err; | 1574 | return err; |
1573 | } | 1575 | } |
@@ -1579,8 +1581,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1579 | int skip = cb->args[0]; | 1581 | int skip = cb->args[0]; |
1580 | int i = 0; | 1582 | int i = 0; |
1581 | 1583 | ||
1582 | rcu_read_lock(); | 1584 | ovs_lock(); |
1583 | list_for_each_entry_rcu(dp, &ovs_net->dps, list_node) { | 1585 | list_for_each_entry(dp, &ovs_net->dps, list_node) { |
1584 | if (i >= skip && | 1586 | if (i >= skip && |
1585 | ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid, | 1587 | ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid, |
1586 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1588 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
@@ -1588,7 +1590,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1588 | break; | 1590 | break; |
1589 | i++; | 1591 | i++; |
1590 | } | 1592 | } |
1591 | rcu_read_unlock(); | 1593 | ovs_unlock(); |
1592 | 1594 | ||
1593 | cb->args[0] = i; | 1595 | cb->args[0] = i; |
1594 | 1596 | ||
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 939bcb32100f..089b195c064a 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -145,7 +145,7 @@ static bool match_validate(const struct sw_flow_match *match, | |||
145 | if (match->key->eth.type == htons(ETH_P_ARP) | 145 | if (match->key->eth.type == htons(ETH_P_ARP) |
146 | || match->key->eth.type == htons(ETH_P_RARP)) { | 146 | || match->key->eth.type == htons(ETH_P_RARP)) { |
147 | key_expected |= 1 << OVS_KEY_ATTR_ARP; | 147 | key_expected |= 1 << OVS_KEY_ATTR_ARP; |
148 | if (match->mask && (match->mask->key.eth.type == htons(0xffff))) | 148 | if (match->mask && (match->mask->key.tp.src == htons(0xff))) |
149 | mask_allowed |= 1 << OVS_KEY_ATTR_ARP; | 149 | mask_allowed |= 1 << OVS_KEY_ATTR_ARP; |
150 | } | 150 | } |
151 | 151 | ||
@@ -689,6 +689,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, | |||
689 | ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX); | 689 | ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX); |
690 | return -EINVAL; | 690 | return -EINVAL; |
691 | } | 691 | } |
692 | |||
693 | if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) { | ||
694 | OVS_NLERR("IPv6 flow label %x is out of range (max=%x).\n", | ||
695 | ntohl(ipv6_key->ipv6_label), (1 << 20) - 1); | ||
696 | return -EINVAL; | ||
697 | } | ||
698 | |||
692 | SW_FLOW_KEY_PUT(match, ipv6.label, | 699 | SW_FLOW_KEY_PUT(match, ipv6.label, |
693 | ipv6_key->ipv6_label, is_mask); | 700 | ipv6_key->ipv6_label, is_mask); |
694 | SW_FLOW_KEY_PUT(match, ip.proto, | 701 | SW_FLOW_KEY_PUT(match, ip.proto, |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 2cf61b3e633c..76f402e05bd6 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -947,7 +947,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
947 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) { | 947 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) { |
948 | if (qdisc_is_percpu_stats(sch)) { | 948 | if (qdisc_is_percpu_stats(sch)) { |
949 | sch->cpu_bstats = | 949 | sch->cpu_bstats = |
950 | alloc_percpu(struct gnet_stats_basic_cpu); | 950 | netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); |
951 | if (!sch->cpu_bstats) | 951 | if (!sch->cpu_bstats) |
952 | goto err_out4; | 952 | goto err_out4; |
953 | 953 | ||
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c index 33d7a98a7a97..b783a446d884 100644 --- a/net/sched/sch_pie.c +++ b/net/sched/sch_pie.c | |||
@@ -445,7 +445,6 @@ static int pie_init(struct Qdisc *sch, struct nlattr *opt) | |||
445 | sch->limit = q->params.limit; | 445 | sch->limit = q->params.limit; |
446 | 446 | ||
447 | setup_timer(&q->adapt_timer, pie_timer, (unsigned long)sch); | 447 | setup_timer(&q->adapt_timer, pie_timer, (unsigned long)sch); |
448 | mod_timer(&q->adapt_timer, jiffies + HZ / 2); | ||
449 | 448 | ||
450 | if (opt) { | 449 | if (opt) { |
451 | int err = pie_change(sch, opt); | 450 | int err = pie_change(sch, opt); |
@@ -454,6 +453,7 @@ static int pie_init(struct Qdisc *sch, struct nlattr *opt) | |||
454 | return err; | 453 | return err; |
455 | } | 454 | } |
456 | 455 | ||
456 | mod_timer(&q->adapt_timer, jiffies + HZ / 2); | ||
457 | return 0; | 457 | return 0; |
458 | } | 458 | } |
459 | 459 | ||
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 0e8529113dc5..fb7976aee61c 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -862,8 +862,6 @@ int sctp_auth_set_key(struct sctp_endpoint *ep, | |||
862 | list_add(&cur_key->key_list, sh_keys); | 862 | list_add(&cur_key->key_list, sh_keys); |
863 | 863 | ||
864 | cur_key->key = key; | 864 | cur_key->key = key; |
865 | sctp_auth_key_hold(key); | ||
866 | |||
867 | return 0; | 865 | return 0; |
868 | nomem: | 866 | nomem: |
869 | if (!replace) | 867 | if (!replace) |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index ab734be8cb20..9f32741abb1c 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -2609,6 +2609,9 @@ do_addr_param: | |||
2609 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2609 | addr_param = param.v + sizeof(sctp_addip_param_t); |
2610 | 2610 | ||
2611 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2611 | af = sctp_get_af_specific(param_type2af(param.p->type)); |
2612 | if (af == NULL) | ||
2613 | break; | ||
2614 | |||
2612 | af->from_addr_param(&addr, addr_param, | 2615 | af->from_addr_param(&addr, addr_param, |
2613 | htons(asoc->peer.port), 0); | 2616 | htons(asoc->peer.port), 0); |
2614 | 2617 | ||
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index afb292cd797d..53ed8d3f8897 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1353,6 +1353,7 @@ gss_stringify_acceptor(struct rpc_cred *cred) | |||
1353 | char *string = NULL; | 1353 | char *string = NULL; |
1354 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1354 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1355 | struct gss_cl_ctx *ctx; | 1355 | struct gss_cl_ctx *ctx; |
1356 | unsigned int len; | ||
1356 | struct xdr_netobj *acceptor; | 1357 | struct xdr_netobj *acceptor; |
1357 | 1358 | ||
1358 | rcu_read_lock(); | 1359 | rcu_read_lock(); |
@@ -1360,15 +1361,39 @@ gss_stringify_acceptor(struct rpc_cred *cred) | |||
1360 | if (!ctx) | 1361 | if (!ctx) |
1361 | goto out; | 1362 | goto out; |
1362 | 1363 | ||
1363 | acceptor = &ctx->gc_acceptor; | 1364 | len = ctx->gc_acceptor.len; |
1365 | rcu_read_unlock(); | ||
1364 | 1366 | ||
1365 | /* no point if there's no string */ | 1367 | /* no point if there's no string */ |
1366 | if (!acceptor->len) | 1368 | if (!len) |
1367 | goto out; | 1369 | return NULL; |
1368 | 1370 | realloc: | |
1369 | string = kmalloc(acceptor->len + 1, GFP_KERNEL); | 1371 | string = kmalloc(len + 1, GFP_KERNEL); |
1370 | if (!string) | 1372 | if (!string) |
1373 | return NULL; | ||
1374 | |||
1375 | rcu_read_lock(); | ||
1376 | ctx = rcu_dereference(gss_cred->gc_ctx); | ||
1377 | |||
1378 | /* did the ctx disappear or was it replaced by one with no acceptor? */ | ||
1379 | if (!ctx || !ctx->gc_acceptor.len) { | ||
1380 | kfree(string); | ||
1381 | string = NULL; | ||
1371 | goto out; | 1382 | goto out; |
1383 | } | ||
1384 | |||
1385 | acceptor = &ctx->gc_acceptor; | ||
1386 | |||
1387 | /* | ||
1388 | * Did we find a new acceptor that's longer than the original? Allocate | ||
1389 | * a longer buffer and try again. | ||
1390 | */ | ||
1391 | if (len < acceptor->len) { | ||
1392 | len = acceptor->len; | ||
1393 | rcu_read_unlock(); | ||
1394 | kfree(string); | ||
1395 | goto realloc; | ||
1396 | } | ||
1372 | 1397 | ||
1373 | memcpy(string, acceptor->data, acceptor->len); | 1398 | memcpy(string, acceptor->data, acceptor->len); |
1374 | string[acceptor->len] = '\0'; | 1399 | string[acceptor->len] = '\0'; |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 90cee4a6fce4..5781634e957d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -219,11 +219,11 @@ void tipc_node_abort_sock_conns(struct list_head *conns) | |||
219 | void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 219 | void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
220 | { | 220 | { |
221 | struct tipc_link **active = &n_ptr->active_links[0]; | 221 | struct tipc_link **active = &n_ptr->active_links[0]; |
222 | u32 addr = n_ptr->addr; | ||
223 | 222 | ||
224 | n_ptr->working_links++; | 223 | n_ptr->working_links++; |
225 | tipc_nametbl_publish(TIPC_LINK_STATE, addr, addr, TIPC_NODE_SCOPE, | 224 | n_ptr->action_flags |= TIPC_NOTIFY_LINK_UP; |
226 | l_ptr->bearer_id, addr); | 225 | n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id; |
226 | |||
227 | pr_info("Established link <%s> on network plane %c\n", | 227 | pr_info("Established link <%s> on network plane %c\n", |
228 | l_ptr->name, l_ptr->net_plane); | 228 | l_ptr->name, l_ptr->net_plane); |
229 | 229 | ||
@@ -284,10 +284,10 @@ static void node_select_active_links(struct tipc_node *n_ptr) | |||
284 | void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 284 | void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
285 | { | 285 | { |
286 | struct tipc_link **active; | 286 | struct tipc_link **active; |
287 | u32 addr = n_ptr->addr; | ||
288 | 287 | ||
289 | n_ptr->working_links--; | 288 | n_ptr->working_links--; |
290 | tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, l_ptr->bearer_id, addr); | 289 | n_ptr->action_flags |= TIPC_NOTIFY_LINK_DOWN; |
290 | n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id; | ||
291 | 291 | ||
292 | if (!tipc_link_is_active(l_ptr)) { | 292 | if (!tipc_link_is_active(l_ptr)) { |
293 | pr_info("Lost standby link <%s> on network plane %c\n", | 293 | pr_info("Lost standby link <%s> on network plane %c\n", |
@@ -552,28 +552,30 @@ void tipc_node_unlock(struct tipc_node *node) | |||
552 | LIST_HEAD(conn_sks); | 552 | LIST_HEAD(conn_sks); |
553 | struct sk_buff_head waiting_sks; | 553 | struct sk_buff_head waiting_sks; |
554 | u32 addr = 0; | 554 | u32 addr = 0; |
555 | unsigned int flags = node->action_flags; | 555 | int flags = node->action_flags; |
556 | u32 link_id = 0; | ||
556 | 557 | ||
557 | if (likely(!node->action_flags)) { | 558 | if (likely(!flags)) { |
558 | spin_unlock_bh(&node->lock); | 559 | spin_unlock_bh(&node->lock); |
559 | return; | 560 | return; |
560 | } | 561 | } |
561 | 562 | ||
563 | addr = node->addr; | ||
564 | link_id = node->link_id; | ||
562 | __skb_queue_head_init(&waiting_sks); | 565 | __skb_queue_head_init(&waiting_sks); |
563 | if (node->action_flags & TIPC_WAKEUP_USERS) { | 566 | |
567 | if (flags & TIPC_WAKEUP_USERS) | ||
564 | skb_queue_splice_init(&node->waiting_sks, &waiting_sks); | 568 | skb_queue_splice_init(&node->waiting_sks, &waiting_sks); |
565 | node->action_flags &= ~TIPC_WAKEUP_USERS; | 569 | |
566 | } | 570 | if (flags & TIPC_NOTIFY_NODE_DOWN) { |
567 | if (node->action_flags & TIPC_NOTIFY_NODE_DOWN) { | ||
568 | list_replace_init(&node->nsub, &nsub_list); | 571 | list_replace_init(&node->nsub, &nsub_list); |
569 | list_replace_init(&node->conn_sks, &conn_sks); | 572 | list_replace_init(&node->conn_sks, &conn_sks); |
570 | node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN; | ||
571 | } | 573 | } |
572 | if (node->action_flags & TIPC_NOTIFY_NODE_UP) { | 574 | node->action_flags &= ~(TIPC_WAKEUP_USERS | TIPC_NOTIFY_NODE_DOWN | |
573 | node->action_flags &= ~TIPC_NOTIFY_NODE_UP; | 575 | TIPC_NOTIFY_NODE_UP | TIPC_NOTIFY_LINK_UP | |
574 | addr = node->addr; | 576 | TIPC_NOTIFY_LINK_DOWN | |
575 | } | 577 | TIPC_WAKEUP_BCAST_USERS); |
576 | node->action_flags &= ~TIPC_WAKEUP_BCAST_USERS; | 578 | |
577 | spin_unlock_bh(&node->lock); | 579 | spin_unlock_bh(&node->lock); |
578 | 580 | ||
579 | while (!skb_queue_empty(&waiting_sks)) | 581 | while (!skb_queue_empty(&waiting_sks)) |
@@ -588,6 +590,14 @@ void tipc_node_unlock(struct tipc_node *node) | |||
588 | if (flags & TIPC_WAKEUP_BCAST_USERS) | 590 | if (flags & TIPC_WAKEUP_BCAST_USERS) |
589 | tipc_bclink_wakeup_users(); | 591 | tipc_bclink_wakeup_users(); |
590 | 592 | ||
591 | if (addr) | 593 | if (flags & TIPC_NOTIFY_NODE_UP) |
592 | tipc_named_node_up(addr); | 594 | tipc_named_node_up(addr); |
595 | |||
596 | if (flags & TIPC_NOTIFY_LINK_UP) | ||
597 | tipc_nametbl_publish(TIPC_LINK_STATE, addr, addr, | ||
598 | TIPC_NODE_SCOPE, link_id, addr); | ||
599 | |||
600 | if (flags & TIPC_NOTIFY_LINK_DOWN) | ||
601 | tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, | ||
602 | link_id, addr); | ||
593 | } | 603 | } |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 67513c3c852c..04e91458bb29 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -53,6 +53,7 @@ | |||
53 | * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down | 53 | * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down |
54 | * TIPC_NOTIFY_NODE_DOWN: notify node is down | 54 | * TIPC_NOTIFY_NODE_DOWN: notify node is down |
55 | * TIPC_NOTIFY_NODE_UP: notify node is up | 55 | * TIPC_NOTIFY_NODE_UP: notify node is up |
56 | * TIPC_DISTRIBUTE_NAME: publish or withdraw link state name type | ||
56 | */ | 57 | */ |
57 | enum { | 58 | enum { |
58 | TIPC_WAIT_PEER_LINKS_DOWN = (1 << 1), | 59 | TIPC_WAIT_PEER_LINKS_DOWN = (1 << 1), |
@@ -60,7 +61,9 @@ enum { | |||
60 | TIPC_NOTIFY_NODE_DOWN = (1 << 3), | 61 | TIPC_NOTIFY_NODE_DOWN = (1 << 3), |
61 | TIPC_NOTIFY_NODE_UP = (1 << 4), | 62 | TIPC_NOTIFY_NODE_UP = (1 << 4), |
62 | TIPC_WAKEUP_USERS = (1 << 5), | 63 | TIPC_WAKEUP_USERS = (1 << 5), |
63 | TIPC_WAKEUP_BCAST_USERS = (1 << 6) | 64 | TIPC_WAKEUP_BCAST_USERS = (1 << 6), |
65 | TIPC_NOTIFY_LINK_UP = (1 << 7), | ||
66 | TIPC_NOTIFY_LINK_DOWN = (1 << 8) | ||
64 | }; | 67 | }; |
65 | 68 | ||
66 | /** | 69 | /** |
@@ -100,6 +103,7 @@ struct tipc_node_bclink { | |||
100 | * @working_links: number of working links to node (both active and standby) | 103 | * @working_links: number of working links to node (both active and standby) |
101 | * @link_cnt: number of links to node | 104 | * @link_cnt: number of links to node |
102 | * @signature: node instance identifier | 105 | * @signature: node instance identifier |
106 | * @link_id: local and remote bearer ids of changing link, if any | ||
103 | * @nsub: list of "node down" subscriptions monitoring node | 107 | * @nsub: list of "node down" subscriptions monitoring node |
104 | * @rcu: rcu struct for tipc_node | 108 | * @rcu: rcu struct for tipc_node |
105 | */ | 109 | */ |
@@ -116,6 +120,7 @@ struct tipc_node { | |||
116 | int link_cnt; | 120 | int link_cnt; |
117 | int working_links; | 121 | int working_links; |
118 | u32 signature; | 122 | u32 signature; |
123 | u32 link_id; | ||
119 | struct list_head nsub; | 124 | struct list_head nsub; |
120 | struct sk_buff_head waiting_sks; | 125 | struct sk_buff_head waiting_sks; |
121 | struct list_head conn_sks; | 126 | struct list_head conn_sks; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 75275c5cf929..51bddc236a15 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1776,7 +1776,7 @@ int tipc_sk_rcv(struct sk_buff *buf) | |||
1776 | sk = &tsk->sk; | 1776 | sk = &tsk->sk; |
1777 | 1777 | ||
1778 | /* Queue message */ | 1778 | /* Queue message */ |
1779 | bh_lock_sock(sk); | 1779 | spin_lock_bh(&sk->sk_lock.slock); |
1780 | 1780 | ||
1781 | if (!sock_owned_by_user(sk)) { | 1781 | if (!sock_owned_by_user(sk)) { |
1782 | rc = filter_rcv(sk, buf); | 1782 | rc = filter_rcv(sk, buf); |
@@ -1787,7 +1787,7 @@ int tipc_sk_rcv(struct sk_buff *buf) | |||
1787 | if (sk_add_backlog(sk, buf, limit)) | 1787 | if (sk_add_backlog(sk, buf, limit)) |
1788 | rc = -TIPC_ERR_OVERLOAD; | 1788 | rc = -TIPC_ERR_OVERLOAD; |
1789 | } | 1789 | } |
1790 | bh_unlock_sock(sk); | 1790 | spin_unlock_bh(&sk->sk_lock.slock); |
1791 | tipc_sk_put(tsk); | 1791 | tipc_sk_put(tsk); |
1792 | if (likely(!rc)) | 1792 | if (likely(!rc)) |
1793 | return 0; | 1793 | return 0; |
@@ -2673,7 +2673,7 @@ static int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) | |||
2673 | case SIOCGETLINKNAME: | 2673 | case SIOCGETLINKNAME: |
2674 | if (copy_from_user(&lnr, argp, sizeof(lnr))) | 2674 | if (copy_from_user(&lnr, argp, sizeof(lnr))) |
2675 | return -EFAULT; | 2675 | return -EFAULT; |
2676 | if (!tipc_node_get_linkname(lnr.bearer_id, lnr.peer, | 2676 | if (!tipc_node_get_linkname(lnr.bearer_id & 0xffff, lnr.peer, |
2677 | lnr.linkname, TIPC_MAX_LINK_NAME)) { | 2677 | lnr.linkname, TIPC_MAX_LINK_NAME)) { |
2678 | if (copy_to_user(argp, &lnr, sizeof(lnr))) | 2678 | if (copy_to_user(argp, &lnr, sizeof(lnr))) |
2679 | return -EFAULT; | 2679 | return -EFAULT; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cb9f5a44ffad..5839c85075f1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5927,6 +5927,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5927 | int err; | 5927 | int err; |
5928 | bool need_new_beacon = false; | 5928 | bool need_new_beacon = false; |
5929 | int len, i; | 5929 | int len, i; |
5930 | u32 cs_count; | ||
5930 | 5931 | ||
5931 | if (!rdev->ops->channel_switch || | 5932 | if (!rdev->ops->channel_switch || |
5932 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) | 5933 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) |
@@ -5963,7 +5964,14 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5963 | if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES]) | 5964 | if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES]) |
5964 | return -EINVAL; | 5965 | return -EINVAL; |
5965 | 5966 | ||
5966 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); | 5967 | /* Even though the attribute is u32, the specification says |
5968 | * u8, so let's make sure we don't overflow. | ||
5969 | */ | ||
5970 | cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); | ||
5971 | if (cs_count > 255) | ||
5972 | return -EINVAL; | ||
5973 | |||
5974 | params.count = cs_count; | ||
5967 | 5975 | ||
5968 | if (!need_new_beacon) | 5976 | if (!need_new_beacon) |
5969 | goto skip_beacons; | 5977 | goto skip_beacons; |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 499d6c18a8ce..7c532856b398 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -157,6 +157,8 @@ static int xfrm_output_gso(struct sk_buff *skb) | |||
157 | kfree_skb(skb); | 157 | kfree_skb(skb); |
158 | if (IS_ERR(segs)) | 158 | if (IS_ERR(segs)) |
159 | return PTR_ERR(segs); | 159 | return PTR_ERR(segs); |
160 | if (segs == NULL) | ||
161 | return -EINVAL; | ||
160 | 162 | ||
161 | do { | 163 | do { |
162 | struct sk_buff *nskb = segs->next; | 164 | struct sk_buff *nskb = segs->next; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4c4e457e7888..88bf289abdc9 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1962,7 +1962,7 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb) | |||
1962 | struct xfrm_policy *pol = xdst->pols[0]; | 1962 | struct xfrm_policy *pol = xdst->pols[0]; |
1963 | struct xfrm_policy_queue *pq = &pol->polq; | 1963 | struct xfrm_policy_queue *pq = &pol->polq; |
1964 | 1964 | ||
1965 | if (unlikely(skb_fclone_busy(skb))) { | 1965 | if (unlikely(skb_fclone_busy(sk, skb))) { |
1966 | kfree_skb(skb); | 1966 | kfree_skb(skb); |
1967 | return 0; | 1967 | return 0; |
1968 | } | 1968 | } |