diff options
author | David S. Miller <davem@davemloft.net> | 2014-11-01 14:53:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-01 14:53:27 -0400 |
commit | 55b42b5ca2dcf143465968697fe6c6503b05fca1 (patch) | |
tree | 91878cd53efc44ba67244d4d3897020828c87c01 /net | |
parent | 10738eeaf4ab3de092586cefcc082e7d43ca0044 (diff) | |
parent | ec1f1276022e4e3ca40871810217d513e39ff250 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/phy/marvell.c
Simple overlapping changes in drivers/net/phy/marvell.c
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
33 files changed, 594 insertions, 212 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 1510b54e6a2e..f96933a823e3 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_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..654c9018e3e7 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -16,6 +16,238 @@ | |||
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 <linux/netfilter_bridge.h> | ||
22 | #include "../br_private.h" | ||
23 | |||
24 | static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, | ||
25 | struct sk_buff *nskb) | ||
26 | { | ||
27 | struct ethhdr *eth; | ||
28 | |||
29 | eth = (struct ethhdr *)skb_push(nskb, ETH_HLEN); | ||
30 | skb_reset_mac_header(nskb); | ||
31 | ether_addr_copy(eth->h_source, eth_hdr(oldskb)->h_dest); | ||
32 | ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source); | ||
33 | eth->h_proto = eth_hdr(oldskb)->h_proto; | ||
34 | skb_pull(nskb, ETH_HLEN); | ||
35 | } | ||
36 | |||
37 | static int nft_reject_iphdr_validate(struct sk_buff *oldskb) | ||
38 | { | ||
39 | struct iphdr *iph; | ||
40 | u32 len; | ||
41 | |||
42 | if (!pskb_may_pull(oldskb, sizeof(struct iphdr))) | ||
43 | return 0; | ||
44 | |||
45 | iph = ip_hdr(oldskb); | ||
46 | if (iph->ihl < 5 || iph->version != 4) | ||
47 | return 0; | ||
48 | |||
49 | len = ntohs(iph->tot_len); | ||
50 | if (oldskb->len < len) | ||
51 | return 0; | ||
52 | else if (len < (iph->ihl*4)) | ||
53 | return 0; | ||
54 | |||
55 | if (!pskb_may_pull(oldskb, iph->ihl*4)) | ||
56 | return 0; | ||
57 | |||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | ||
62 | { | ||
63 | struct sk_buff *nskb; | ||
64 | struct iphdr *niph; | ||
65 | const struct tcphdr *oth; | ||
66 | struct tcphdr _oth; | ||
67 | |||
68 | if (!nft_reject_iphdr_validate(oldskb)) | ||
69 | return; | ||
70 | |||
71 | oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); | ||
72 | if (!oth) | ||
73 | return; | ||
74 | |||
75 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | ||
76 | LL_MAX_HEADER, GFP_ATOMIC); | ||
77 | if (!nskb) | ||
78 | return; | ||
79 | |||
80 | skb_reserve(nskb, LL_MAX_HEADER); | ||
81 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, | ||
82 | sysctl_ip_default_ttl); | ||
83 | nf_reject_ip_tcphdr_put(nskb, oldskb, oth); | ||
84 | niph->ttl = sysctl_ip_default_ttl; | ||
85 | niph->tot_len = htons(nskb->len); | ||
86 | ip_send_check(niph); | ||
87 | |||
88 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
89 | |||
90 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
91 | } | ||
92 | |||
93 | static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | ||
94 | u8 code) | ||
95 | { | ||
96 | struct sk_buff *nskb; | ||
97 | struct iphdr *niph; | ||
98 | struct icmphdr *icmph; | ||
99 | unsigned int len; | ||
100 | void *payload; | ||
101 | __wsum csum; | ||
102 | |||
103 | if (!nft_reject_iphdr_validate(oldskb)) | ||
104 | return; | ||
105 | |||
106 | /* IP header checks: fragment. */ | ||
107 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | ||
108 | return; | ||
109 | |||
110 | /* RFC says return as much as we can without exceeding 576 bytes. */ | ||
111 | len = min_t(unsigned int, 536, oldskb->len); | ||
112 | |||
113 | if (!pskb_may_pull(oldskb, len)) | ||
114 | return; | ||
115 | |||
116 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), 0)) | ||
117 | return; | ||
118 | |||
119 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) + | ||
120 | LL_MAX_HEADER + len, GFP_ATOMIC); | ||
121 | if (!nskb) | ||
122 | return; | ||
123 | |||
124 | skb_reserve(nskb, LL_MAX_HEADER); | ||
125 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP, | ||
126 | sysctl_ip_default_ttl); | ||
127 | |||
128 | skb_reset_transport_header(nskb); | ||
129 | icmph = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr)); | ||
130 | memset(icmph, 0, sizeof(*icmph)); | ||
131 | icmph->type = ICMP_DEST_UNREACH; | ||
132 | icmph->code = code; | ||
133 | |||
134 | payload = skb_put(nskb, len); | ||
135 | memcpy(payload, skb_network_header(oldskb), len); | ||
136 | |||
137 | csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0); | ||
138 | icmph->checksum = csum_fold(csum); | ||
139 | |||
140 | niph->tot_len = htons(nskb->len); | ||
141 | ip_send_check(niph); | ||
142 | |||
143 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
144 | |||
145 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
146 | } | ||
147 | |||
148 | static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb) | ||
149 | { | ||
150 | struct ipv6hdr *hdr; | ||
151 | u32 pkt_len; | ||
152 | |||
153 | if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr))) | ||
154 | return 0; | ||
155 | |||
156 | hdr = ipv6_hdr(oldskb); | ||
157 | if (hdr->version != 6) | ||
158 | return 0; | ||
159 | |||
160 | pkt_len = ntohs(hdr->payload_len); | ||
161 | if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len) | ||
162 | return 0; | ||
163 | |||
164 | return 1; | ||
165 | } | ||
166 | |||
167 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, | ||
168 | struct sk_buff *oldskb, int hook) | ||
169 | { | ||
170 | struct sk_buff *nskb; | ||
171 | const struct tcphdr *oth; | ||
172 | struct tcphdr _oth; | ||
173 | unsigned int otcplen; | ||
174 | struct ipv6hdr *nip6h; | ||
175 | |||
176 | if (!nft_reject_ip6hdr_validate(oldskb)) | ||
177 | return; | ||
178 | |||
179 | oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); | ||
180 | if (!oth) | ||
181 | return; | ||
182 | |||
183 | nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + | ||
184 | LL_MAX_HEADER, GFP_ATOMIC); | ||
185 | if (!nskb) | ||
186 | return; | ||
187 | |||
188 | skb_reserve(nskb, LL_MAX_HEADER); | ||
189 | nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, | ||
190 | net->ipv6.devconf_all->hop_limit); | ||
191 | nf_reject_ip6_tcphdr_put(nskb, oldskb, oth, otcplen); | ||
192 | nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); | ||
193 | |||
194 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
195 | |||
196 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
197 | } | ||
198 | |||
199 | static void nft_reject_br_send_v6_unreach(struct net *net, | ||
200 | struct sk_buff *oldskb, int hook, | ||
201 | u8 code) | ||
202 | { | ||
203 | struct sk_buff *nskb; | ||
204 | struct ipv6hdr *nip6h; | ||
205 | struct icmp6hdr *icmp6h; | ||
206 | unsigned int len; | ||
207 | void *payload; | ||
208 | |||
209 | if (!nft_reject_ip6hdr_validate(oldskb)) | ||
210 | return; | ||
211 | |||
212 | /* Include "As much of invoking packet as possible without the ICMPv6 | ||
213 | * packet exceeding the minimum IPv6 MTU" in the ICMP payload. | ||
214 | */ | ||
215 | len = min_t(unsigned int, 1220, oldskb->len); | ||
216 | |||
217 | if (!pskb_may_pull(oldskb, len)) | ||
218 | return; | ||
219 | |||
220 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) + | ||
221 | LL_MAX_HEADER + len, GFP_ATOMIC); | ||
222 | if (!nskb) | ||
223 | return; | ||
224 | |||
225 | skb_reserve(nskb, LL_MAX_HEADER); | ||
226 | nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_ICMPV6, | ||
227 | net->ipv6.devconf_all->hop_limit); | ||
228 | |||
229 | skb_reset_transport_header(nskb); | ||
230 | icmp6h = (struct icmp6hdr *)skb_put(nskb, sizeof(struct icmp6hdr)); | ||
231 | memset(icmp6h, 0, sizeof(*icmp6h)); | ||
232 | icmp6h->icmp6_type = ICMPV6_DEST_UNREACH; | ||
233 | icmp6h->icmp6_code = code; | ||
234 | |||
235 | payload = skb_put(nskb, len); | ||
236 | memcpy(payload, skb_network_header(oldskb), len); | ||
237 | nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); | ||
238 | |||
239 | icmp6h->icmp6_cksum = | ||
240 | csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, | ||
241 | nskb->len - sizeof(struct ipv6hdr), | ||
242 | IPPROTO_ICMPV6, | ||
243 | csum_partial(icmp6h, | ||
244 | nskb->len - sizeof(struct ipv6hdr), | ||
245 | 0)); | ||
246 | |||
247 | nft_reject_br_push_etherhdr(oldskb, nskb); | ||
248 | |||
249 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | ||
250 | } | ||
19 | 251 | ||
20 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | 252 | static void nft_reject_bridge_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 253 | struct nft_data data[NFT_REG_MAX + 1], |
@@ -23,35 +255,46 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
23 | { | 255 | { |
24 | struct nft_reject *priv = nft_expr_priv(expr); | 256 | struct nft_reject *priv = nft_expr_priv(expr); |
25 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | 257 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); |
258 | const unsigned char *dest = eth_hdr(pkt->skb)->h_dest; | ||
259 | |||
260 | if (is_broadcast_ether_addr(dest) || | ||
261 | is_multicast_ether_addr(dest)) | ||
262 | goto out; | ||
26 | 263 | ||
27 | switch (eth_hdr(pkt->skb)->h_proto) { | 264 | switch (eth_hdr(pkt->skb)->h_proto) { |
28 | case htons(ETH_P_IP): | 265 | case htons(ETH_P_IP): |
29 | switch (priv->type) { | 266 | switch (priv->type) { |
30 | case NFT_REJECT_ICMP_UNREACH: | 267 | case NFT_REJECT_ICMP_UNREACH: |
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | 268 | nft_reject_br_send_v4_unreach(pkt->skb, |
269 | pkt->ops->hooknum, | ||
270 | priv->icmp_code); | ||
32 | break; | 271 | break; |
33 | case NFT_REJECT_TCP_RST: | 272 | case NFT_REJECT_TCP_RST: |
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | 273 | nft_reject_br_send_v4_tcp_reset(pkt->skb, |
274 | pkt->ops->hooknum); | ||
35 | break; | 275 | break; |
36 | case NFT_REJECT_ICMPX_UNREACH: | 276 | case NFT_REJECT_ICMPX_UNREACH: |
37 | nf_send_unreach(pkt->skb, | 277 | nft_reject_br_send_v4_unreach(pkt->skb, |
38 | nft_reject_icmp_code(priv->icmp_code)); | 278 | pkt->ops->hooknum, |
279 | nft_reject_icmp_code(priv->icmp_code)); | ||
39 | break; | 280 | break; |
40 | } | 281 | } |
41 | break; | 282 | break; |
42 | case htons(ETH_P_IPV6): | 283 | case htons(ETH_P_IPV6): |
43 | switch (priv->type) { | 284 | switch (priv->type) { |
44 | case NFT_REJECT_ICMP_UNREACH: | 285 | case NFT_REJECT_ICMP_UNREACH: |
45 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | 286 | nft_reject_br_send_v6_unreach(net, pkt->skb, |
46 | pkt->ops->hooknum); | 287 | pkt->ops->hooknum, |
288 | priv->icmp_code); | ||
47 | break; | 289 | break; |
48 | case NFT_REJECT_TCP_RST: | 290 | case NFT_REJECT_TCP_RST: |
49 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | 291 | nft_reject_br_send_v6_tcp_reset(net, pkt->skb, |
292 | pkt->ops->hooknum); | ||
50 | break; | 293 | break; |
51 | case NFT_REJECT_ICMPX_UNREACH: | 294 | case NFT_REJECT_ICMPX_UNREACH: |
52 | nf_send_unreach6(net, pkt->skb, | 295 | nft_reject_br_send_v6_unreach(net, pkt->skb, |
53 | nft_reject_icmpv6_code(priv->icmp_code), | 296 | pkt->ops->hooknum, |
54 | pkt->ops->hooknum); | 297 | nft_reject_icmpv6_code(priv->icmp_code)); |
55 | break; | 298 | break; |
56 | } | 299 | } |
57 | break; | 300 | break; |
@@ -59,15 +302,38 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
59 | /* No explicit way to reject this protocol, drop it. */ | 302 | /* No explicit way to reject this protocol, drop it. */ |
60 | break; | 303 | break; |
61 | } | 304 | } |
305 | out: | ||
62 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 306 | data[NFT_REG_VERDICT].verdict = NF_DROP; |
63 | } | 307 | } |
64 | 308 | ||
309 | static int nft_reject_bridge_validate_hooks(const struct nft_chain *chain) | ||
310 | { | ||
311 | struct nft_base_chain *basechain; | ||
312 | |||
313 | if (chain->flags & NFT_BASE_CHAIN) { | ||
314 | basechain = nft_base_chain(chain); | ||
315 | |||
316 | switch (basechain->ops[0].hooknum) { | ||
317 | case NF_BR_PRE_ROUTING: | ||
318 | case NF_BR_LOCAL_IN: | ||
319 | break; | ||
320 | default: | ||
321 | return -EOPNOTSUPP; | ||
322 | } | ||
323 | } | ||
324 | return 0; | ||
325 | } | ||
326 | |||
65 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, | 327 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, |
66 | const struct nft_expr *expr, | 328 | const struct nft_expr *expr, |
67 | const struct nlattr * const tb[]) | 329 | const struct nlattr * const tb[]) |
68 | { | 330 | { |
69 | struct nft_reject *priv = nft_expr_priv(expr); | 331 | struct nft_reject *priv = nft_expr_priv(expr); |
70 | int icmp_code; | 332 | int icmp_code, err; |
333 | |||
334 | err = nft_reject_bridge_validate_hooks(ctx->chain); | ||
335 | if (err < 0) | ||
336 | return err; | ||
71 | 337 | ||
72 | if (tb[NFTA_REJECT_TYPE] == NULL) | 338 | if (tb[NFTA_REJECT_TYPE] == NULL) |
73 | return -EINVAL; | 339 | return -EINVAL; |
@@ -116,6 +382,13 @@ nla_put_failure: | |||
116 | return -1; | 382 | return -1; |
117 | } | 383 | } |
118 | 384 | ||
385 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, | ||
386 | const struct nft_expr *expr, | ||
387 | const struct nft_data **data) | ||
388 | { | ||
389 | return nft_reject_bridge_validate_hooks(ctx->chain); | ||
390 | } | ||
391 | |||
119 | static struct nft_expr_type nft_reject_bridge_type; | 392 | static struct nft_expr_type nft_reject_bridge_type; |
120 | static const struct nft_expr_ops nft_reject_bridge_ops = { | 393 | static const struct nft_expr_ops nft_reject_bridge_ops = { |
121 | .type = &nft_reject_bridge_type, | 394 | .type = &nft_reject_bridge_type, |
@@ -123,6 +396,7 @@ static const struct nft_expr_ops nft_reject_bridge_ops = { | |||
123 | .eval = nft_reject_bridge_eval, | 396 | .eval = nft_reject_bridge_eval, |
124 | .init = nft_reject_bridge_init, | 397 | .init = nft_reject_bridge_init, |
125 | .dump = nft_reject_bridge_dump, | 398 | .dump = nft_reject_bridge_dump, |
399 | .validate = nft_reject_bridge_validate, | ||
126 | }; | 400 | }; |
127 | 401 | ||
128 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { | 402 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { |
diff --git a/net/core/dev.c b/net/core/dev.c index 759940cdf896..ebf778df58cd 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/dsa/dsa.c b/net/dsa/dsa.c index b51ef592f0a2..dd646a8025cb 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -276,8 +276,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, | |||
276 | dst->rcv = brcm_netdev_ops.rcv; | 276 | dst->rcv = brcm_netdev_ops.rcv; |
277 | break; | 277 | break; |
278 | #endif | 278 | #endif |
279 | default: | 279 | case DSA_TAG_PROTO_NONE: |
280 | break; | 280 | break; |
281 | default: | ||
282 | ret = -ENOPROTOOPT; | ||
283 | goto out; | ||
281 | } | 284 | } |
282 | 285 | ||
283 | dst->tag_protocol = drv->tag_protocol; | 286 | dst->tag_protocol = drv->tag_protocol; |
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index f6e345c0bc23..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 | ||
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/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index 92b303dbd5fc..1baaa83dfe5c 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c | |||
@@ -12,43 +12,39 @@ | |||
12 | #include <net/route.h> | 12 | #include <net/route.h> |
13 | #include <net/dst.h> | 13 | #include <net/dst.h> |
14 | #include <linux/netfilter_ipv4.h> | 14 | #include <linux/netfilter_ipv4.h> |
15 | #include <net/netfilter/ipv4/nf_reject.h> | ||
15 | 16 | ||
16 | /* Send RST reply */ | 17 | const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, |
17 | void nf_send_reset(struct sk_buff *oldskb, int hook) | 18 | struct tcphdr *_oth, int hook) |
18 | { | 19 | { |
19 | struct sk_buff *nskb; | ||
20 | const struct iphdr *oiph; | ||
21 | struct iphdr *niph; | ||
22 | const struct tcphdr *oth; | 20 | const struct tcphdr *oth; |
23 | struct tcphdr _otcph, *tcph; | ||
24 | 21 | ||
25 | /* IP header checks: fragment. */ | 22 | /* IP header checks: fragment. */ |
26 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | 23 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) |
27 | return; | 24 | return NULL; |
28 | 25 | ||
29 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), | 26 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), |
30 | sizeof(_otcph), &_otcph); | 27 | sizeof(struct tcphdr), _oth); |
31 | if (oth == NULL) | 28 | if (oth == NULL) |
32 | return; | 29 | return NULL; |
33 | 30 | ||
34 | /* No RST for RST. */ | 31 | /* No RST for RST. */ |
35 | if (oth->rst) | 32 | if (oth->rst) |
36 | return; | 33 | return NULL; |
37 | |||
38 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
39 | return; | ||
40 | 34 | ||
41 | /* Check checksum */ | 35 | /* Check checksum */ |
42 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | 36 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) |
43 | return; | 37 | return NULL; |
44 | oiph = ip_hdr(oldskb); | ||
45 | 38 | ||
46 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | 39 | return oth; |
47 | LL_MAX_HEADER, GFP_ATOMIC); | 40 | } |
48 | if (!nskb) | 41 | EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_get); |
49 | return; | ||
50 | 42 | ||
51 | 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); | ||
52 | 48 | ||
53 | skb_reset_network_header(nskb); | 49 | skb_reset_network_header(nskb); |
54 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); | 50 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); |
@@ -57,10 +53,23 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
57 | niph->tos = 0; | 53 | niph->tos = 0; |
58 | niph->id = 0; | 54 | niph->id = 0; |
59 | niph->frag_off = htons(IP_DF); | 55 | niph->frag_off = htons(IP_DF); |
60 | niph->protocol = IPPROTO_TCP; | 56 | niph->protocol = protocol; |
61 | niph->check = 0; | 57 | niph->check = 0; |
62 | niph->saddr = oiph->daddr; | 58 | niph->saddr = oiph->daddr; |
63 | 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; | ||
64 | 73 | ||
65 | skb_reset_transport_header(nskb); | 74 | skb_reset_transport_header(nskb); |
66 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | 75 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); |
@@ -69,9 +78,9 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
69 | tcph->dest = oth->source; | 78 | tcph->dest = oth->source; |
70 | tcph->doff = sizeof(struct tcphdr) / 4; | 79 | tcph->doff = sizeof(struct tcphdr) / 4; |
71 | 80 | ||
72 | if (oth->ack) | 81 | if (oth->ack) { |
73 | tcph->seq = oth->ack_seq; | 82 | tcph->seq = oth->ack_seq; |
74 | else { | 83 | } else { |
75 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + | 84 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + |
76 | oldskb->len - ip_hdrlen(oldskb) - | 85 | oldskb->len - ip_hdrlen(oldskb) - |
77 | (oth->doff << 2)); | 86 | (oth->doff << 2)); |
@@ -84,16 +93,43 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
84 | nskb->ip_summed = CHECKSUM_PARTIAL; | 93 | nskb->ip_summed = CHECKSUM_PARTIAL; |
85 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | 94 | nskb->csum_start = (unsigned char *)tcph - nskb->head; |
86 | 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; | ||
87 | 121 | ||
88 | /* ip_route_me_harder expects skb->dst to be set */ | 122 | /* ip_route_me_harder expects skb->dst to be set */ |
89 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | 123 | skb_dst_set_noref(nskb, skb_dst(oldskb)); |
90 | 124 | ||
91 | 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 | |||
92 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) | 130 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) |
93 | goto free_nskb; | 131 | goto free_nskb; |
94 | 132 | ||
95 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | ||
96 | |||
97 | /* "Never happens" */ | 133 | /* "Never happens" */ |
98 | if (nskb->len > dst_mtu(skb_dst(nskb))) | 134 | if (nskb->len > dst_mtu(skb_dst(nskb))) |
99 | goto free_nskb; | 135 | goto free_nskb; |
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_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/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8d12b7c7018f..06e897832a7a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -4565,6 +4565,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4565 | } | 4565 | } |
4566 | 4566 | ||
4567 | write_unlock_bh(&idev->lock); | 4567 | write_unlock_bh(&idev->lock); |
4568 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | ||
4568 | addrconf_verify_rtnl(); | 4569 | addrconf_verify_rtnl(); |
4569 | return 0; | 4570 | return 0; |
4570 | } | 4571 | } |
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 20d9defc6c59..015eb8a80766 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c | |||
@@ -12,116 +12,102 @@ | |||
12 | #include <net/ip6_fib.h> | 12 | #include <net/ip6_fib.h> |
13 | #include <net/ip6_checksum.h> | 13 | #include <net/ip6_checksum.h> |
14 | #include <linux/netfilter_ipv6.h> | 14 | #include <linux/netfilter_ipv6.h> |
15 | #include <net/netfilter/ipv6/nf_reject.h> | ||
15 | 16 | ||
16 | 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) | ||
17 | { | 20 | { |
18 | struct sk_buff *nskb; | ||
19 | struct tcphdr otcph, *tcph; | ||
20 | unsigned int otcplen, hh_len; | ||
21 | int tcphoff, needs_ack; | ||
22 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | 21 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
23 | struct ipv6hdr *ip6h; | ||
24 | #define DEFAULT_TOS_VALUE 0x0U | ||
25 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
26 | struct dst_entry *dst = NULL; | ||
27 | u8 proto; | 22 | u8 proto; |
28 | __be16 frag_off; | 23 | __be16 frag_off; |
29 | struct flowi6 fl6; | 24 | int tcphoff; |
30 | |||
31 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
32 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
33 | pr_debug("addr is not unicast.\n"); | ||
34 | return; | ||
35 | } | ||
36 | 25 | ||
37 | proto = oip6h->nexthdr; | 26 | proto = oip6h->nexthdr; |
38 | 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); | ||
39 | 29 | ||
40 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 30 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
41 | pr_debug("Cannot get TCP header.\n"); | 31 | pr_debug("Cannot get TCP header.\n"); |
42 | return; | 32 | return NULL; |
43 | } | 33 | } |
44 | 34 | ||
45 | otcplen = oldskb->len - tcphoff; | 35 | *otcplen = oldskb->len - tcphoff; |
46 | 36 | ||
47 | /* IP header checks: fragment, too short. */ | 37 | /* IP header checks: fragment, too short. */ |
48 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { | 38 | if (proto != IPPROTO_TCP || *otcplen < sizeof(struct tcphdr)) { |
49 | pr_debug("proto(%d) != IPPROTO_TCP, " | 39 | pr_debug("proto(%d) != IPPROTO_TCP or too short (len = %d)\n", |
50 | "or too short. otcplen = %d\n", | 40 | proto, *otcplen); |
51 | proto, otcplen); | 41 | return NULL; |
52 | return; | ||
53 | } | 42 | } |
54 | 43 | ||
55 | if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) | 44 | otcph = skb_header_pointer(oldskb, tcphoff, sizeof(struct tcphdr), |
56 | BUG(); | 45 | otcph); |
46 | if (otcph == NULL) | ||
47 | return NULL; | ||
57 | 48 | ||
58 | /* No RST for RST. */ | 49 | /* No RST for RST. */ |
59 | if (otcph.rst) { | 50 | if (otcph->rst) { |
60 | pr_debug("RST is set\n"); | 51 | pr_debug("RST is set\n"); |
61 | return; | 52 | return NULL; |
62 | } | 53 | } |
63 | 54 | ||
64 | /* Check checksum. */ | 55 | /* Check checksum. */ |
65 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { | 56 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { |
66 | pr_debug("TCP checksum is invalid\n"); | 57 | pr_debug("TCP checksum is invalid\n"); |
67 | return; | 58 | return NULL; |
68 | } | ||
69 | |||
70 | memset(&fl6, 0, sizeof(fl6)); | ||
71 | fl6.flowi6_proto = IPPROTO_TCP; | ||
72 | fl6.saddr = oip6h->daddr; | ||
73 | fl6.daddr = oip6h->saddr; | ||
74 | fl6.fl6_sport = otcph.dest; | ||
75 | fl6.fl6_dport = otcph.source; | ||
76 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | ||
77 | dst = ip6_route_output(net, NULL, &fl6); | ||
78 | if (dst == NULL || dst->error) { | ||
79 | dst_release(dst); | ||
80 | return; | ||
81 | } | ||
82 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
83 | if (IS_ERR(dst)) | ||
84 | return; | ||
85 | |||
86 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
87 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
88 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
89 | GFP_ATOMIC); | ||
90 | |||
91 | if (!nskb) { | ||
92 | net_dbg_ratelimited("cannot alloc skb\n"); | ||
93 | dst_release(dst); | ||
94 | return; | ||
95 | } | 59 | } |
96 | 60 | ||
97 | skb_dst_set(nskb, dst); | 61 | return otcph; |
62 | } | ||
63 | EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_get); | ||
98 | 64 | ||
99 | 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; | ||
100 | 73 | ||
101 | skb_put(nskb, sizeof(struct ipv6hdr)); | 74 | skb_put(nskb, sizeof(struct ipv6hdr)); |
102 | skb_reset_network_header(nskb); | 75 | skb_reset_network_header(nskb); |
103 | ip6h = ipv6_hdr(nskb); | 76 | ip6h = ipv6_hdr(nskb); |
104 | ip6_flow_hdr(ip6h, tclass, 0); | 77 | ip6_flow_hdr(ip6h, tclass, 0); |
105 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 78 | ip6h->hop_limit = hoplimit; |
106 | ip6h->nexthdr = IPPROTO_TCP; | 79 | ip6h->nexthdr = protocol; |
107 | ip6h->saddr = oip6h->daddr; | 80 | ip6h->saddr = oip6h->daddr; |
108 | ip6h->daddr = oip6h->saddr; | 81 | ip6h->daddr = oip6h->saddr; |
109 | 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 | |||
110 | skb_reset_transport_header(nskb); | 96 | skb_reset_transport_header(nskb); |
111 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | 97 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); |
112 | /* Truncate to length (no data) */ | 98 | /* Truncate to length (no data) */ |
113 | tcph->doff = sizeof(struct tcphdr)/4; | 99 | tcph->doff = sizeof(struct tcphdr)/4; |
114 | tcph->source = otcph.dest; | 100 | tcph->source = oth->dest; |
115 | tcph->dest = otcph.source; | 101 | tcph->dest = oth->source; |
116 | 102 | ||
117 | if (otcph.ack) { | 103 | if (oth->ack) { |
118 | needs_ack = 0; | 104 | needs_ack = 0; |
119 | tcph->seq = otcph.ack_seq; | 105 | tcph->seq = oth->ack_seq; |
120 | tcph->ack_seq = 0; | 106 | tcph->ack_seq = 0; |
121 | } else { | 107 | } else { |
122 | needs_ack = 1; | 108 | needs_ack = 1; |
123 | tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin | 109 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + |
124 | + otcplen - (otcph.doff<<2)); | 110 | otcplen - (oth->doff<<2)); |
125 | tcph->seq = 0; | 111 | tcph->seq = 0; |
126 | } | 112 | } |
127 | 113 | ||
@@ -139,6 +125,63 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | |||
139 | sizeof(struct tcphdr), IPPROTO_TCP, | 125 | sizeof(struct tcphdr), IPPROTO_TCP, |
140 | csum_partial(tcph, | 126 | csum_partial(tcph, |
141 | 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); | ||
142 | 185 | ||
143 | nf_ct_attach(nskb, oldskb); | 186 | nf_ct_attach(nskb, oldskb); |
144 | 187 | ||
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/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/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_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/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 f0f5309a2d72..e3545f21a099 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c | |||
@@ -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..86f9d76b1464 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); |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 91f17c1eb8a2..437a3663ad03 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 | ||
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 44d1ea32570a..d87b6423ffb2 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 65eb2a1160d5..11ab4b078f3b 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 | } |
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/nft_compat.c b/net/netfilter/nft_compat.c index 0480f57a4eb6..9d6d6f60a80f 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -672,7 +672,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
672 | family = ctx->afi->family; | 672 | family = ctx->afi->family; |
673 | 673 | ||
674 | /* Re-use the existing target if it's already loaded. */ | 674 | /* Re-use the existing target if it's already loaded. */ |
675 | list_for_each_entry(nft_target, &nft_match_list, head) { | 675 | list_for_each_entry(nft_target, &nft_target_list, head) { |
676 | struct xt_target *target = nft_target->ops.data; | 676 | struct xt_target *target = nft_target->ops.data; |
677 | 677 | ||
678 | if (strcmp(target->name, tg_name) == 0 && | 678 | if (strcmp(target->name, tg_name) == 0 && |
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/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_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 | } |