diff options
Diffstat (limited to 'net')
58 files changed, 968 insertions, 386 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 9ee5787634e5..953b6728bd00 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -626,11 +626,18 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev, | |||
626 | { | 626 | { |
627 | struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; | 627 | struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; |
628 | netdev_features_t old_features = features; | 628 | netdev_features_t old_features = features; |
629 | netdev_features_t lower_features; | ||
629 | 630 | ||
630 | features = netdev_intersect_features(features, real_dev->vlan_features); | 631 | lower_features = netdev_intersect_features((real_dev->vlan_features | |
631 | features |= NETIF_F_RXCSUM; | 632 | NETIF_F_RXCSUM), |
632 | features = netdev_intersect_features(features, real_dev->features); | 633 | real_dev->features); |
633 | 634 | ||
635 | /* Add HW_CSUM setting to preserve user ability to control | ||
636 | * checksum offload on the vlan device. | ||
637 | */ | ||
638 | if (lower_features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)) | ||
639 | lower_features |= NETIF_F_HW_CSUM; | ||
640 | features = netdev_intersect_features(features, lower_features); | ||
634 | features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE); | 641 | features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE); |
635 | features |= NETIF_F_LLTX; | 642 | features |= NETIF_F_LLTX; |
636 | 643 | ||
diff --git a/net/9p/Kconfig b/net/9p/Kconfig index a75174a33723..e6014e0e51f7 100644 --- a/net/9p/Kconfig +++ b/net/9p/Kconfig | |||
@@ -22,6 +22,15 @@ config NET_9P_VIRTIO | |||
22 | This builds support for a transports between | 22 | This builds support for a transports between |
23 | guest partitions and a host partition. | 23 | guest partitions and a host partition. |
24 | 24 | ||
25 | config NET_9P_XEN | ||
26 | depends on XEN | ||
27 | select XEN_XENBUS_FRONTEND | ||
28 | tristate "9P Xen Transport" | ||
29 | help | ||
30 | This builds support for a transport for 9pfs between | ||
31 | two Xen domains. | ||
32 | |||
33 | |||
25 | config NET_9P_RDMA | 34 | config NET_9P_RDMA |
26 | depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS | 35 | depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS |
27 | tristate "9P RDMA Transport (Experimental)" | 36 | tristate "9P RDMA Transport (Experimental)" |
diff --git a/net/9p/Makefile b/net/9p/Makefile index a0874cc1f718..697ea7caf466 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | obj-$(CONFIG_NET_9P) := 9pnet.o | 1 | obj-$(CONFIG_NET_9P) := 9pnet.o |
2 | obj-$(CONFIG_NET_9P_XEN) += 9pnet_xen.o | ||
2 | obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o | 3 | obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o |
3 | obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o | 4 | obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o |
4 | 5 | ||
@@ -14,5 +15,8 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o | |||
14 | 9pnet_virtio-objs := \ | 15 | 9pnet_virtio-objs := \ |
15 | trans_virtio.o \ | 16 | trans_virtio.o \ |
16 | 17 | ||
18 | 9pnet_xen-objs := \ | ||
19 | trans_xen.o \ | ||
20 | |||
17 | 9pnet_rdma-objs := \ | 21 | 9pnet_rdma-objs := \ |
18 | trans_rdma.o \ | 22 | trans_rdma.o \ |
diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c new file mode 100644 index 000000000000..71e85643b3f9 --- /dev/null +++ b/net/9p/trans_xen.c | |||
@@ -0,0 +1,545 @@ | |||
1 | /* | ||
2 | * linux/fs/9p/trans_xen | ||
3 | * | ||
4 | * Xen transport layer. | ||
5 | * | ||
6 | * Copyright (C) 2017 by Stefano Stabellini <stefano@aporeto.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation; or, when distributed | ||
11 | * separately from the Linux kernel or incorporated into other | ||
12 | * software packages, subject to the following license: | ||
13 | * | ||
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
15 | * of this source file (the "Software"), to deal in the Software without | ||
16 | * restriction, including without limitation the rights to use, copy, modify, | ||
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
18 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
19 | * the following conditions: | ||
20 | * | ||
21 | * The above copyright notice and this permission notice shall be included in | ||
22 | * all copies or substantial portions of the Software. | ||
23 | * | ||
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
30 | * IN THE SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #include <xen/events.h> | ||
34 | #include <xen/grant_table.h> | ||
35 | #include <xen/xen.h> | ||
36 | #include <xen/xenbus.h> | ||
37 | #include <xen/interface/io/9pfs.h> | ||
38 | |||
39 | #include <linux/module.h> | ||
40 | #include <linux/spinlock.h> | ||
41 | #include <linux/rwlock.h> | ||
42 | #include <net/9p/9p.h> | ||
43 | #include <net/9p/client.h> | ||
44 | #include <net/9p/transport.h> | ||
45 | |||
46 | #define XEN_9PFS_NUM_RINGS 2 | ||
47 | #define XEN_9PFS_RING_ORDER 6 | ||
48 | #define XEN_9PFS_RING_SIZE XEN_FLEX_RING_SIZE(XEN_9PFS_RING_ORDER) | ||
49 | |||
50 | struct xen_9pfs_header { | ||
51 | uint32_t size; | ||
52 | uint8_t id; | ||
53 | uint16_t tag; | ||
54 | |||
55 | /* uint8_t sdata[]; */ | ||
56 | } __attribute__((packed)); | ||
57 | |||
58 | /* One per ring, more than one per 9pfs share */ | ||
59 | struct xen_9pfs_dataring { | ||
60 | struct xen_9pfs_front_priv *priv; | ||
61 | |||
62 | struct xen_9pfs_data_intf *intf; | ||
63 | grant_ref_t ref; | ||
64 | int evtchn; | ||
65 | int irq; | ||
66 | /* protect a ring from concurrent accesses */ | ||
67 | spinlock_t lock; | ||
68 | |||
69 | struct xen_9pfs_data data; | ||
70 | wait_queue_head_t wq; | ||
71 | struct work_struct work; | ||
72 | }; | ||
73 | |||
74 | /* One per 9pfs share */ | ||
75 | struct xen_9pfs_front_priv { | ||
76 | struct list_head list; | ||
77 | struct xenbus_device *dev; | ||
78 | char *tag; | ||
79 | struct p9_client *client; | ||
80 | |||
81 | int num_rings; | ||
82 | struct xen_9pfs_dataring *rings; | ||
83 | }; | ||
84 | |||
85 | static LIST_HEAD(xen_9pfs_devs); | ||
86 | static DEFINE_RWLOCK(xen_9pfs_lock); | ||
87 | |||
88 | /* We don't currently allow canceling of requests */ | ||
89 | static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req) | ||
90 | { | ||
91 | return 1; | ||
92 | } | ||
93 | |||
94 | static int p9_xen_create(struct p9_client *client, const char *addr, char *args) | ||
95 | { | ||
96 | struct xen_9pfs_front_priv *priv; | ||
97 | |||
98 | read_lock(&xen_9pfs_lock); | ||
99 | list_for_each_entry(priv, &xen_9pfs_devs, list) { | ||
100 | if (!strcmp(priv->tag, addr)) { | ||
101 | priv->client = client; | ||
102 | read_unlock(&xen_9pfs_lock); | ||
103 | return 0; | ||
104 | } | ||
105 | } | ||
106 | read_unlock(&xen_9pfs_lock); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
110 | static void p9_xen_close(struct p9_client *client) | ||
111 | { | ||
112 | struct xen_9pfs_front_priv *priv; | ||
113 | |||
114 | read_lock(&xen_9pfs_lock); | ||
115 | list_for_each_entry(priv, &xen_9pfs_devs, list) { | ||
116 | if (priv->client == client) { | ||
117 | priv->client = NULL; | ||
118 | read_unlock(&xen_9pfs_lock); | ||
119 | return; | ||
120 | } | ||
121 | } | ||
122 | read_unlock(&xen_9pfs_lock); | ||
123 | } | ||
124 | |||
125 | static bool p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX size) | ||
126 | { | ||
127 | RING_IDX cons, prod; | ||
128 | |||
129 | cons = ring->intf->out_cons; | ||
130 | prod = ring->intf->out_prod; | ||
131 | virt_mb(); | ||
132 | |||
133 | return XEN_9PFS_RING_SIZE - | ||
134 | xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) >= size; | ||
135 | } | ||
136 | |||
137 | static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) | ||
138 | { | ||
139 | struct xen_9pfs_front_priv *priv = NULL; | ||
140 | RING_IDX cons, prod, masked_cons, masked_prod; | ||
141 | unsigned long flags; | ||
142 | u32 size = p9_req->tc->size; | ||
143 | struct xen_9pfs_dataring *ring; | ||
144 | int num; | ||
145 | |||
146 | read_lock(&xen_9pfs_lock); | ||
147 | list_for_each_entry(priv, &xen_9pfs_devs, list) { | ||
148 | if (priv->client == client) | ||
149 | break; | ||
150 | } | ||
151 | read_unlock(&xen_9pfs_lock); | ||
152 | if (!priv || priv->client != client) | ||
153 | return -EINVAL; | ||
154 | |||
155 | num = p9_req->tc->tag % priv->num_rings; | ||
156 | ring = &priv->rings[num]; | ||
157 | |||
158 | again: | ||
159 | while (wait_event_interruptible(ring->wq, | ||
160 | p9_xen_write_todo(ring, size)) != 0) | ||
161 | ; | ||
162 | |||
163 | spin_lock_irqsave(&ring->lock, flags); | ||
164 | cons = ring->intf->out_cons; | ||
165 | prod = ring->intf->out_prod; | ||
166 | virt_mb(); | ||
167 | |||
168 | if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons, | ||
169 | XEN_9PFS_RING_SIZE) < size) { | ||
170 | spin_unlock_irqrestore(&ring->lock, flags); | ||
171 | goto again; | ||
172 | } | ||
173 | |||
174 | masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE); | ||
175 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); | ||
176 | |||
177 | xen_9pfs_write_packet(ring->data.out, p9_req->tc->sdata, size, | ||
178 | &masked_prod, masked_cons, XEN_9PFS_RING_SIZE); | ||
179 | |||
180 | p9_req->status = REQ_STATUS_SENT; | ||
181 | virt_wmb(); /* write ring before updating pointer */ | ||
182 | prod += size; | ||
183 | ring->intf->out_prod = prod; | ||
184 | spin_unlock_irqrestore(&ring->lock, flags); | ||
185 | notify_remote_via_irq(ring->irq); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void p9_xen_response(struct work_struct *work) | ||
191 | { | ||
192 | struct xen_9pfs_front_priv *priv; | ||
193 | struct xen_9pfs_dataring *ring; | ||
194 | RING_IDX cons, prod, masked_cons, masked_prod; | ||
195 | struct xen_9pfs_header h; | ||
196 | struct p9_req_t *req; | ||
197 | int status; | ||
198 | |||
199 | ring = container_of(work, struct xen_9pfs_dataring, work); | ||
200 | priv = ring->priv; | ||
201 | |||
202 | while (1) { | ||
203 | cons = ring->intf->in_cons; | ||
204 | prod = ring->intf->in_prod; | ||
205 | virt_rmb(); | ||
206 | |||
207 | if (xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) < | ||
208 | sizeof(h)) { | ||
209 | notify_remote_via_irq(ring->irq); | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE); | ||
214 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); | ||
215 | |||
216 | /* First, read just the header */ | ||
217 | xen_9pfs_read_packet(&h, ring->data.in, sizeof(h), | ||
218 | masked_prod, &masked_cons, | ||
219 | XEN_9PFS_RING_SIZE); | ||
220 | |||
221 | req = p9_tag_lookup(priv->client, h.tag); | ||
222 | if (!req || req->status != REQ_STATUS_SENT) { | ||
223 | dev_warn(&priv->dev->dev, "Wrong req tag=%x\n", h.tag); | ||
224 | cons += h.size; | ||
225 | virt_mb(); | ||
226 | ring->intf->in_cons = cons; | ||
227 | continue; | ||
228 | } | ||
229 | |||
230 | memcpy(req->rc, &h, sizeof(h)); | ||
231 | req->rc->offset = 0; | ||
232 | |||
233 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); | ||
234 | /* Then, read the whole packet (including the header) */ | ||
235 | xen_9pfs_read_packet(req->rc->sdata, ring->data.in, h.size, | ||
236 | masked_prod, &masked_cons, | ||
237 | XEN_9PFS_RING_SIZE); | ||
238 | |||
239 | virt_mb(); | ||
240 | cons += h.size; | ||
241 | ring->intf->in_cons = cons; | ||
242 | |||
243 | status = (req->status != REQ_STATUS_ERROR) ? | ||
244 | REQ_STATUS_RCVD : REQ_STATUS_ERROR; | ||
245 | |||
246 | p9_client_cb(priv->client, req, status); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r) | ||
251 | { | ||
252 | struct xen_9pfs_dataring *ring = r; | ||
253 | |||
254 | if (!ring || !ring->priv->client) { | ||
255 | /* ignore spurious interrupt */ | ||
256 | return IRQ_HANDLED; | ||
257 | } | ||
258 | |||
259 | wake_up_interruptible(&ring->wq); | ||
260 | schedule_work(&ring->work); | ||
261 | |||
262 | return IRQ_HANDLED; | ||
263 | } | ||
264 | |||
265 | static struct p9_trans_module p9_xen_trans = { | ||
266 | .name = "xen", | ||
267 | .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT), | ||
268 | .def = 1, | ||
269 | .create = p9_xen_create, | ||
270 | .close = p9_xen_close, | ||
271 | .request = p9_xen_request, | ||
272 | .cancel = p9_xen_cancel, | ||
273 | .owner = THIS_MODULE, | ||
274 | }; | ||
275 | |||
276 | static const struct xenbus_device_id xen_9pfs_front_ids[] = { | ||
277 | { "9pfs" }, | ||
278 | { "" } | ||
279 | }; | ||
280 | |||
281 | static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv) | ||
282 | { | ||
283 | int i, j; | ||
284 | |||
285 | write_lock(&xen_9pfs_lock); | ||
286 | list_del(&priv->list); | ||
287 | write_unlock(&xen_9pfs_lock); | ||
288 | |||
289 | for (i = 0; i < priv->num_rings; i++) { | ||
290 | if (!priv->rings[i].intf) | ||
291 | break; | ||
292 | if (priv->rings[i].irq > 0) | ||
293 | unbind_from_irqhandler(priv->rings[i].irq, priv->dev); | ||
294 | if (priv->rings[i].data.in) { | ||
295 | for (j = 0; j < (1 << XEN_9PFS_RING_ORDER); j++) { | ||
296 | grant_ref_t ref; | ||
297 | |||
298 | ref = priv->rings[i].intf->ref[j]; | ||
299 | gnttab_end_foreign_access(ref, 0, 0); | ||
300 | } | ||
301 | free_pages((unsigned long)priv->rings[i].data.in, | ||
302 | XEN_9PFS_RING_ORDER - | ||
303 | (PAGE_SHIFT - XEN_PAGE_SHIFT)); | ||
304 | } | ||
305 | gnttab_end_foreign_access(priv->rings[i].ref, 0, 0); | ||
306 | free_page((unsigned long)priv->rings[i].intf); | ||
307 | } | ||
308 | kfree(priv->rings); | ||
309 | kfree(priv->tag); | ||
310 | kfree(priv); | ||
311 | } | ||
312 | |||
313 | static int xen_9pfs_front_remove(struct xenbus_device *dev) | ||
314 | { | ||
315 | struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev); | ||
316 | |||
317 | dev_set_drvdata(&dev->dev, NULL); | ||
318 | xen_9pfs_front_free(priv); | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev, | ||
323 | struct xen_9pfs_dataring *ring) | ||
324 | { | ||
325 | int i = 0; | ||
326 | int ret = -ENOMEM; | ||
327 | void *bytes = NULL; | ||
328 | |||
329 | init_waitqueue_head(&ring->wq); | ||
330 | spin_lock_init(&ring->lock); | ||
331 | INIT_WORK(&ring->work, p9_xen_response); | ||
332 | |||
333 | ring->intf = (struct xen_9pfs_data_intf *)get_zeroed_page(GFP_KERNEL); | ||
334 | if (!ring->intf) | ||
335 | return ret; | ||
336 | ret = gnttab_grant_foreign_access(dev->otherend_id, | ||
337 | virt_to_gfn(ring->intf), 0); | ||
338 | if (ret < 0) | ||
339 | goto out; | ||
340 | ring->ref = ret; | ||
341 | bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | ||
342 | XEN_9PFS_RING_ORDER - (PAGE_SHIFT - XEN_PAGE_SHIFT)); | ||
343 | if (!bytes) { | ||
344 | ret = -ENOMEM; | ||
345 | goto out; | ||
346 | } | ||
347 | for (; i < (1 << XEN_9PFS_RING_ORDER); i++) { | ||
348 | ret = gnttab_grant_foreign_access( | ||
349 | dev->otherend_id, virt_to_gfn(bytes) + i, 0); | ||
350 | if (ret < 0) | ||
351 | goto out; | ||
352 | ring->intf->ref[i] = ret; | ||
353 | } | ||
354 | ring->intf->ring_order = XEN_9PFS_RING_ORDER; | ||
355 | ring->data.in = bytes; | ||
356 | ring->data.out = bytes + XEN_9PFS_RING_SIZE; | ||
357 | |||
358 | ret = xenbus_alloc_evtchn(dev, &ring->evtchn); | ||
359 | if (ret) | ||
360 | goto out; | ||
361 | ring->irq = bind_evtchn_to_irqhandler(ring->evtchn, | ||
362 | xen_9pfs_front_event_handler, | ||
363 | 0, "xen_9pfs-frontend", ring); | ||
364 | if (ring->irq >= 0) | ||
365 | return 0; | ||
366 | |||
367 | xenbus_free_evtchn(dev, ring->evtchn); | ||
368 | ret = ring->irq; | ||
369 | out: | ||
370 | if (bytes) { | ||
371 | for (i--; i >= 0; i--) | ||
372 | gnttab_end_foreign_access(ring->intf->ref[i], 0, 0); | ||
373 | free_pages((unsigned long)bytes, | ||
374 | XEN_9PFS_RING_ORDER - | ||
375 | (PAGE_SHIFT - XEN_PAGE_SHIFT)); | ||
376 | } | ||
377 | gnttab_end_foreign_access(ring->ref, 0, 0); | ||
378 | free_page((unsigned long)ring->intf); | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static int xen_9pfs_front_probe(struct xenbus_device *dev, | ||
383 | const struct xenbus_device_id *id) | ||
384 | { | ||
385 | int ret, i; | ||
386 | struct xenbus_transaction xbt; | ||
387 | struct xen_9pfs_front_priv *priv = NULL; | ||
388 | char *versions; | ||
389 | unsigned int max_rings, max_ring_order, len = 0; | ||
390 | |||
391 | versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len); | ||
392 | if (!len) | ||
393 | return -EINVAL; | ||
394 | if (strcmp(versions, "1")) { | ||
395 | kfree(versions); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | kfree(versions); | ||
399 | max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0); | ||
400 | if (max_rings < XEN_9PFS_NUM_RINGS) | ||
401 | return -EINVAL; | ||
402 | max_ring_order = xenbus_read_unsigned(dev->otherend, | ||
403 | "max-ring-page-order", 0); | ||
404 | if (max_ring_order < XEN_9PFS_RING_ORDER) | ||
405 | return -EINVAL; | ||
406 | |||
407 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
408 | if (!priv) | ||
409 | return -ENOMEM; | ||
410 | |||
411 | priv->dev = dev; | ||
412 | priv->num_rings = XEN_9PFS_NUM_RINGS; | ||
413 | priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings), | ||
414 | GFP_KERNEL); | ||
415 | if (!priv->rings) { | ||
416 | kfree(priv); | ||
417 | return -ENOMEM; | ||
418 | } | ||
419 | |||
420 | for (i = 0; i < priv->num_rings; i++) { | ||
421 | priv->rings[i].priv = priv; | ||
422 | ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i]); | ||
423 | if (ret < 0) | ||
424 | goto error; | ||
425 | } | ||
426 | |||
427 | again: | ||
428 | ret = xenbus_transaction_start(&xbt); | ||
429 | if (ret) { | ||
430 | xenbus_dev_fatal(dev, ret, "starting transaction"); | ||
431 | goto error; | ||
432 | } | ||
433 | ret = xenbus_printf(xbt, dev->nodename, "version", "%u", 1); | ||
434 | if (ret) | ||
435 | goto error_xenbus; | ||
436 | ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u", | ||
437 | priv->num_rings); | ||
438 | if (ret) | ||
439 | goto error_xenbus; | ||
440 | for (i = 0; i < priv->num_rings; i++) { | ||
441 | char str[16]; | ||
442 | |||
443 | BUILD_BUG_ON(XEN_9PFS_NUM_RINGS > 9); | ||
444 | sprintf(str, "ring-ref%u", i); | ||
445 | ret = xenbus_printf(xbt, dev->nodename, str, "%d", | ||
446 | priv->rings[i].ref); | ||
447 | if (ret) | ||
448 | goto error_xenbus; | ||
449 | |||
450 | sprintf(str, "event-channel-%u", i); | ||
451 | ret = xenbus_printf(xbt, dev->nodename, str, "%u", | ||
452 | priv->rings[i].evtchn); | ||
453 | if (ret) | ||
454 | goto error_xenbus; | ||
455 | } | ||
456 | priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL); | ||
457 | if (!priv->tag) { | ||
458 | ret = -EINVAL; | ||
459 | goto error_xenbus; | ||
460 | } | ||
461 | ret = xenbus_transaction_end(xbt, 0); | ||
462 | if (ret) { | ||
463 | if (ret == -EAGAIN) | ||
464 | goto again; | ||
465 | xenbus_dev_fatal(dev, ret, "completing transaction"); | ||
466 | goto error; | ||
467 | } | ||
468 | |||
469 | write_lock(&xen_9pfs_lock); | ||
470 | list_add_tail(&priv->list, &xen_9pfs_devs); | ||
471 | write_unlock(&xen_9pfs_lock); | ||
472 | dev_set_drvdata(&dev->dev, priv); | ||
473 | xenbus_switch_state(dev, XenbusStateInitialised); | ||
474 | |||
475 | return 0; | ||
476 | |||
477 | error_xenbus: | ||
478 | xenbus_transaction_end(xbt, 1); | ||
479 | xenbus_dev_fatal(dev, ret, "writing xenstore"); | ||
480 | error: | ||
481 | dev_set_drvdata(&dev->dev, NULL); | ||
482 | xen_9pfs_front_free(priv); | ||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | static int xen_9pfs_front_resume(struct xenbus_device *dev) | ||
487 | { | ||
488 | dev_warn(&dev->dev, "suspsend/resume unsupported\n"); | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static void xen_9pfs_front_changed(struct xenbus_device *dev, | ||
493 | enum xenbus_state backend_state) | ||
494 | { | ||
495 | switch (backend_state) { | ||
496 | case XenbusStateReconfiguring: | ||
497 | case XenbusStateReconfigured: | ||
498 | case XenbusStateInitialising: | ||
499 | case XenbusStateInitialised: | ||
500 | case XenbusStateUnknown: | ||
501 | break; | ||
502 | |||
503 | case XenbusStateInitWait: | ||
504 | break; | ||
505 | |||
506 | case XenbusStateConnected: | ||
507 | xenbus_switch_state(dev, XenbusStateConnected); | ||
508 | break; | ||
509 | |||
510 | case XenbusStateClosed: | ||
511 | if (dev->state == XenbusStateClosed) | ||
512 | break; | ||
513 | /* Missed the backend's CLOSING state -- fallthrough */ | ||
514 | case XenbusStateClosing: | ||
515 | xenbus_frontend_closed(dev); | ||
516 | break; | ||
517 | } | ||
518 | } | ||
519 | |||
520 | static struct xenbus_driver xen_9pfs_front_driver = { | ||
521 | .ids = xen_9pfs_front_ids, | ||
522 | .probe = xen_9pfs_front_probe, | ||
523 | .remove = xen_9pfs_front_remove, | ||
524 | .resume = xen_9pfs_front_resume, | ||
525 | .otherend_changed = xen_9pfs_front_changed, | ||
526 | }; | ||
527 | |||
528 | int p9_trans_xen_init(void) | ||
529 | { | ||
530 | if (!xen_domain()) | ||
531 | return -ENODEV; | ||
532 | |||
533 | pr_info("Initialising Xen transport for 9pfs\n"); | ||
534 | |||
535 | v9fs_register_trans(&p9_xen_trans); | ||
536 | return xenbus_register_frontend(&xen_9pfs_front_driver); | ||
537 | } | ||
538 | module_init(p9_trans_xen_init); | ||
539 | |||
540 | void p9_trans_xen_exit(void) | ||
541 | { | ||
542 | v9fs_unregister_trans(&p9_xen_trans); | ||
543 | return xenbus_unregister_driver(&xen_9pfs_front_driver); | ||
544 | } | ||
545 | module_exit(p9_trans_xen_exit); | ||
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index a572db710d4e..c5ce7745b230 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -133,6 +133,8 @@ static inline size_t br_port_info_size(void) | |||
133 | + nla_total_size(1) /* IFLA_BRPORT_MCAST_TO_UCAST */ | 133 | + nla_total_size(1) /* IFLA_BRPORT_MCAST_TO_UCAST */ |
134 | + nla_total_size(1) /* IFLA_BRPORT_LEARNING */ | 134 | + nla_total_size(1) /* IFLA_BRPORT_LEARNING */ |
135 | + nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */ | 135 | + nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */ |
136 | + nla_total_size(1) /* IFLA_BRPORT_MCAST_FLOOD */ | ||
137 | + nla_total_size(1) /* IFLA_BRPORT_BCAST_FLOOD */ | ||
136 | + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */ | 138 | + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */ |
137 | + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */ | 139 | + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */ |
138 | + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ | 140 | + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ |
@@ -633,6 +635,8 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = { | |||
633 | [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 }, | 635 | [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 }, |
634 | [IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 }, | 636 | [IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 }, |
635 | [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 }, | 637 | [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 }, |
638 | [IFLA_BRPORT_MCAST_FLOOD] = { .type = NLA_U8 }, | ||
639 | [IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 }, | ||
636 | }; | 640 | }; |
637 | 641 | ||
638 | /* Change the state of the port and notify spanning tree */ | 642 | /* Change the state of the port and notify spanning tree */ |
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index 4e0b0c359325..e0bb624c3845 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <net/sock.h> | 11 | #include <net/sock.h> |
12 | #include "../br_private.h" | ||
12 | #include <linux/netfilter.h> | 13 | #include <linux/netfilter.h> |
13 | #include <linux/netfilter/x_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
14 | #include <linux/netfilter_bridge/ebtables.h> | 15 | #include <linux/netfilter_bridge/ebtables.h> |
@@ -18,11 +19,30 @@ static unsigned int | |||
18 | ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par) | 19 | ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par) |
19 | { | 20 | { |
20 | const struct ebt_nat_info *info = par->targinfo; | 21 | const struct ebt_nat_info *info = par->targinfo; |
22 | struct net_device *dev; | ||
21 | 23 | ||
22 | if (!skb_make_writable(skb, 0)) | 24 | if (!skb_make_writable(skb, 0)) |
23 | return EBT_DROP; | 25 | return EBT_DROP; |
24 | 26 | ||
25 | ether_addr_copy(eth_hdr(skb)->h_dest, info->mac); | 27 | ether_addr_copy(eth_hdr(skb)->h_dest, info->mac); |
28 | |||
29 | if (is_multicast_ether_addr(info->mac)) { | ||
30 | if (is_broadcast_ether_addr(info->mac)) | ||
31 | skb->pkt_type = PACKET_BROADCAST; | ||
32 | else | ||
33 | skb->pkt_type = PACKET_MULTICAST; | ||
34 | } else { | ||
35 | if (xt_hooknum(par) != NF_BR_BROUTING) | ||
36 | dev = br_port_get_rcu(xt_in(par))->br->dev; | ||
37 | else | ||
38 | dev = xt_in(par); | ||
39 | |||
40 | if (ether_addr_equal(info->mac, dev->dev_addr)) | ||
41 | skb->pkt_type = PACKET_HOST; | ||
42 | else | ||
43 | skb->pkt_type = PACKET_OTHERHOST; | ||
44 | } | ||
45 | |||
26 | return info->target; | 46 | return info->target; |
27 | } | 47 | } |
28 | 48 | ||
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 108533859a53..4eb773ccce11 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -187,7 +187,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags) | |||
187 | return ptr; | 187 | return ptr; |
188 | } | 188 | } |
189 | 189 | ||
190 | return __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL); | 190 | return __vmalloc(size, flags, PAGE_KERNEL); |
191 | } | 191 | } |
192 | 192 | ||
193 | 193 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f76bb3332613..5766a6c896c4 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -1386,8 +1386,9 @@ static void prepare_write_keepalive(struct ceph_connection *con) | |||
1386 | dout("prepare_write_keepalive %p\n", con); | 1386 | dout("prepare_write_keepalive %p\n", con); |
1387 | con_out_kvec_reset(con); | 1387 | con_out_kvec_reset(con); |
1388 | if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) { | 1388 | if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) { |
1389 | struct timespec now = CURRENT_TIME; | 1389 | struct timespec now; |
1390 | 1390 | ||
1391 | ktime_get_real_ts(&now); | ||
1391 | con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2); | 1392 | con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2); |
1392 | ceph_encode_timespec(&con->out_temp_keepalive2, &now); | 1393 | ceph_encode_timespec(&con->out_temp_keepalive2, &now); |
1393 | con_out_kvec_add(con, sizeof(con->out_temp_keepalive2), | 1394 | con_out_kvec_add(con, sizeof(con->out_temp_keepalive2), |
@@ -3176,8 +3177,9 @@ bool ceph_con_keepalive_expired(struct ceph_connection *con, | |||
3176 | { | 3177 | { |
3177 | if (interval > 0 && | 3178 | if (interval > 0 && |
3178 | (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) { | 3179 | (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) { |
3179 | struct timespec now = CURRENT_TIME; | 3180 | struct timespec now; |
3180 | struct timespec ts; | 3181 | struct timespec ts; |
3182 | ktime_get_real_ts(&now); | ||
3181 | jiffies_to_timespec(interval, &ts); | 3183 | jiffies_to_timespec(interval, &ts); |
3182 | ts = timespec_add(con->last_keepalive_ack, ts); | 3184 | ts = timespec_add(con->last_keepalive_ack, ts); |
3183 | return timespec_compare(&now, &ts) >= 0; | 3185 | return timespec_compare(&now, &ts) >= 0; |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index e15ea9e4c495..242d7c0d92f8 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -3574,7 +3574,7 @@ ceph_osdc_watch(struct ceph_osd_client *osdc, | |||
3574 | ceph_oid_copy(&lreq->t.base_oid, oid); | 3574 | ceph_oid_copy(&lreq->t.base_oid, oid); |
3575 | ceph_oloc_copy(&lreq->t.base_oloc, oloc); | 3575 | ceph_oloc_copy(&lreq->t.base_oloc, oloc); |
3576 | lreq->t.flags = CEPH_OSD_FLAG_WRITE; | 3576 | lreq->t.flags = CEPH_OSD_FLAG_WRITE; |
3577 | lreq->mtime = CURRENT_TIME; | 3577 | ktime_get_real_ts(&lreq->mtime); |
3578 | 3578 | ||
3579 | lreq->reg_req = alloc_linger_request(lreq); | 3579 | lreq->reg_req = alloc_linger_request(lreq); |
3580 | if (!lreq->reg_req) { | 3580 | if (!lreq->reg_req) { |
@@ -3632,7 +3632,7 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc, | |||
3632 | ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid); | 3632 | ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid); |
3633 | ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc); | 3633 | ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc); |
3634 | req->r_flags = CEPH_OSD_FLAG_WRITE; | 3634 | req->r_flags = CEPH_OSD_FLAG_WRITE; |
3635 | req->r_mtime = CURRENT_TIME; | 3635 | ktime_get_real_ts(&req->r_mtime); |
3636 | osd_req_op_watch_init(req, 0, lreq->linger_id, | 3636 | osd_req_op_watch_init(req, 0, lreq->linger_id, |
3637 | CEPH_OSD_WATCH_OP_UNWATCH); | 3637 | CEPH_OSD_WATCH_OP_UNWATCH); |
3638 | 3638 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index d07aa5ffb511..96cf83da0d66 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/hash.h> | 81 | #include <linux/hash.h> |
82 | #include <linux/slab.h> | 82 | #include <linux/slab.h> |
83 | #include <linux/sched.h> | 83 | #include <linux/sched.h> |
84 | #include <linux/sched/mm.h> | ||
84 | #include <linux/mutex.h> | 85 | #include <linux/mutex.h> |
85 | #include <linux/string.h> | 86 | #include <linux/string.h> |
86 | #include <linux/mm.h> | 87 | #include <linux/mm.h> |
@@ -4235,7 +4236,7 @@ static int __netif_receive_skb(struct sk_buff *skb) | |||
4235 | int ret; | 4236 | int ret; |
4236 | 4237 | ||
4237 | if (sk_memalloc_socks() && skb_pfmemalloc(skb)) { | 4238 | if (sk_memalloc_socks() && skb_pfmemalloc(skb)) { |
4238 | unsigned long pflags = current->flags; | 4239 | unsigned int noreclaim_flag; |
4239 | 4240 | ||
4240 | /* | 4241 | /* |
4241 | * PFMEMALLOC skbs are special, they should | 4242 | * PFMEMALLOC skbs are special, they should |
@@ -4246,9 +4247,9 @@ static int __netif_receive_skb(struct sk_buff *skb) | |||
4246 | * Use PF_MEMALLOC as this saves us from propagating the allocation | 4247 | * Use PF_MEMALLOC as this saves us from propagating the allocation |
4247 | * context down to all allocation sites. | 4248 | * context down to all allocation sites. |
4248 | */ | 4249 | */ |
4249 | current->flags |= PF_MEMALLOC; | 4250 | noreclaim_flag = memalloc_noreclaim_save(); |
4250 | ret = __netif_receive_skb_core(skb, true); | 4251 | ret = __netif_receive_skb_core(skb, true); |
4251 | current_restore_flags(pflags, PF_MEMALLOC); | 4252 | memalloc_noreclaim_restore(noreclaim_flag); |
4252 | } else | 4253 | } else |
4253 | ret = __netif_receive_skb_core(skb, false); | 4254 | ret = __netif_receive_skb_core(skb, false); |
4254 | 4255 | ||
@@ -7264,12 +7265,10 @@ static int netif_alloc_rx_queues(struct net_device *dev) | |||
7264 | 7265 | ||
7265 | BUG_ON(count < 1); | 7266 | BUG_ON(count < 1); |
7266 | 7267 | ||
7267 | rx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); | 7268 | rx = kvzalloc(sz, GFP_KERNEL | __GFP_REPEAT); |
7268 | if (!rx) { | 7269 | if (!rx) |
7269 | rx = vzalloc(sz); | 7270 | return -ENOMEM; |
7270 | if (!rx) | 7271 | |
7271 | return -ENOMEM; | ||
7272 | } | ||
7273 | dev->_rx = rx; | 7272 | dev->_rx = rx; |
7274 | 7273 | ||
7275 | for (i = 0; i < count; i++) | 7274 | for (i = 0; i < count; i++) |
@@ -7306,12 +7305,10 @@ static int netif_alloc_netdev_queues(struct net_device *dev) | |||
7306 | if (count < 1 || count > 0xffff) | 7305 | if (count < 1 || count > 0xffff) |
7307 | return -EINVAL; | 7306 | return -EINVAL; |
7308 | 7307 | ||
7309 | tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); | 7308 | tx = kvzalloc(sz, GFP_KERNEL | __GFP_REPEAT); |
7310 | if (!tx) { | 7309 | if (!tx) |
7311 | tx = vzalloc(sz); | 7310 | return -ENOMEM; |
7312 | if (!tx) | 7311 | |
7313 | return -ENOMEM; | ||
7314 | } | ||
7315 | dev->_tx = tx; | 7312 | dev->_tx = tx; |
7316 | 7313 | ||
7317 | netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL); | 7314 | netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL); |
@@ -7845,9 +7842,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
7845 | /* ensure 32-byte alignment of whole construct */ | 7842 | /* ensure 32-byte alignment of whole construct */ |
7846 | alloc_size += NETDEV_ALIGN - 1; | 7843 | alloc_size += NETDEV_ALIGN - 1; |
7847 | 7844 | ||
7848 | p = kzalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); | 7845 | p = kvzalloc(alloc_size, GFP_KERNEL | __GFP_REPEAT); |
7849 | if (!p) | ||
7850 | p = vzalloc(alloc_size); | ||
7851 | if (!p) | 7846 | if (!p) |
7852 | return NULL; | 7847 | return NULL; |
7853 | 7848 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 6e67315ec368..bcb0f610ee42 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1054,7 +1054,7 @@ static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev) | |||
1054 | return err; | 1054 | return err; |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name)) | 1057 | if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name)) |
1058 | return -EMSGSIZE; | 1058 | return -EMSGSIZE; |
1059 | 1059 | ||
1060 | return 0; | 1060 | return 0; |
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 6bd2f8fb0476..ae35cce3a40d 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c | |||
@@ -24,9 +24,13 @@ static siphash_key_t ts_secret __read_mostly; | |||
24 | 24 | ||
25 | static __always_inline void net_secret_init(void) | 25 | static __always_inline void net_secret_init(void) |
26 | { | 26 | { |
27 | net_get_random_once(&ts_secret, sizeof(ts_secret)); | ||
28 | net_get_random_once(&net_secret, sizeof(net_secret)); | 27 | net_get_random_once(&net_secret, sizeof(net_secret)); |
29 | } | 28 | } |
29 | |||
30 | static __always_inline void ts_secret_init(void) | ||
31 | { | ||
32 | net_get_random_once(&ts_secret, sizeof(ts_secret)); | ||
33 | } | ||
30 | #endif | 34 | #endif |
31 | 35 | ||
32 | #ifdef CONFIG_INET | 36 | #ifdef CONFIG_INET |
@@ -47,7 +51,7 @@ static u32 seq_scale(u32 seq) | |||
47 | #endif | 51 | #endif |
48 | 52 | ||
49 | #if IS_ENABLED(CONFIG_IPV6) | 53 | #if IS_ENABLED(CONFIG_IPV6) |
50 | static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr) | 54 | u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr) |
51 | { | 55 | { |
52 | const struct { | 56 | const struct { |
53 | struct in6_addr saddr; | 57 | struct in6_addr saddr; |
@@ -60,12 +64,14 @@ static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr) | |||
60 | if (sysctl_tcp_timestamps != 1) | 64 | if (sysctl_tcp_timestamps != 1) |
61 | return 0; | 65 | return 0; |
62 | 66 | ||
67 | ts_secret_init(); | ||
63 | return siphash(&combined, offsetofend(typeof(combined), daddr), | 68 | return siphash(&combined, offsetofend(typeof(combined), daddr), |
64 | &ts_secret); | 69 | &ts_secret); |
65 | } | 70 | } |
71 | EXPORT_SYMBOL(secure_tcpv6_ts_off); | ||
66 | 72 | ||
67 | u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr, | 73 | u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr, |
68 | __be16 sport, __be16 dport, u32 *tsoff) | 74 | __be16 sport, __be16 dport) |
69 | { | 75 | { |
70 | const struct { | 76 | const struct { |
71 | struct in6_addr saddr; | 77 | struct in6_addr saddr; |
@@ -78,14 +84,14 @@ u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr, | |||
78 | .sport = sport, | 84 | .sport = sport, |
79 | .dport = dport | 85 | .dport = dport |
80 | }; | 86 | }; |
81 | u64 hash; | 87 | u32 hash; |
88 | |||
82 | net_secret_init(); | 89 | net_secret_init(); |
83 | hash = siphash(&combined, offsetofend(typeof(combined), dport), | 90 | hash = siphash(&combined, offsetofend(typeof(combined), dport), |
84 | &net_secret); | 91 | &net_secret); |
85 | *tsoff = secure_tcpv6_ts_off(saddr, daddr); | ||
86 | return seq_scale(hash); | 92 | return seq_scale(hash); |
87 | } | 93 | } |
88 | EXPORT_SYMBOL(secure_tcpv6_seq_and_tsoff); | 94 | EXPORT_SYMBOL(secure_tcpv6_seq); |
89 | 95 | ||
90 | u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, | 96 | u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, |
91 | __be16 dport) | 97 | __be16 dport) |
@@ -107,11 +113,12 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral); | |||
107 | #endif | 113 | #endif |
108 | 114 | ||
109 | #ifdef CONFIG_INET | 115 | #ifdef CONFIG_INET |
110 | static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr) | 116 | u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr) |
111 | { | 117 | { |
112 | if (sysctl_tcp_timestamps != 1) | 118 | if (sysctl_tcp_timestamps != 1) |
113 | return 0; | 119 | return 0; |
114 | 120 | ||
121 | ts_secret_init(); | ||
115 | return siphash_2u32((__force u32)saddr, (__force u32)daddr, | 122 | return siphash_2u32((__force u32)saddr, (__force u32)daddr, |
116 | &ts_secret); | 123 | &ts_secret); |
117 | } | 124 | } |
@@ -121,15 +128,15 @@ static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr) | |||
121 | * it would be easy enough to have the former function use siphash_4u32, passing | 128 | * it would be easy enough to have the former function use siphash_4u32, passing |
122 | * the arguments as separate u32. | 129 | * the arguments as separate u32. |
123 | */ | 130 | */ |
124 | u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr, | 131 | u32 secure_tcp_seq(__be32 saddr, __be32 daddr, |
125 | __be16 sport, __be16 dport, u32 *tsoff) | 132 | __be16 sport, __be16 dport) |
126 | { | 133 | { |
127 | u64 hash; | 134 | u32 hash; |
135 | |||
128 | net_secret_init(); | 136 | net_secret_init(); |
129 | hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, | 137 | hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, |
130 | (__force u32)sport << 16 | (__force u32)dport, | 138 | (__force u32)sport << 16 | (__force u32)dport, |
131 | &net_secret); | 139 | &net_secret); |
132 | *tsoff = secure_tcp_ts_off(saddr, daddr); | ||
133 | return seq_scale(hash); | 140 | return seq_scale(hash); |
134 | } | 141 | } |
135 | 142 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index b5baeb9cb0fb..79c6aee6af9b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -102,6 +102,7 @@ | |||
102 | #include <linux/proc_fs.h> | 102 | #include <linux/proc_fs.h> |
103 | #include <linux/seq_file.h> | 103 | #include <linux/seq_file.h> |
104 | #include <linux/sched.h> | 104 | #include <linux/sched.h> |
105 | #include <linux/sched/mm.h> | ||
105 | #include <linux/timer.h> | 106 | #include <linux/timer.h> |
106 | #include <linux/string.h> | 107 | #include <linux/string.h> |
107 | #include <linux/sockios.h> | 108 | #include <linux/sockios.h> |
@@ -372,14 +373,14 @@ EXPORT_SYMBOL_GPL(sk_clear_memalloc); | |||
372 | int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) | 373 | int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) |
373 | { | 374 | { |
374 | int ret; | 375 | int ret; |
375 | unsigned long pflags = current->flags; | 376 | unsigned int noreclaim_flag; |
376 | 377 | ||
377 | /* these should have been dropped before queueing */ | 378 | /* these should have been dropped before queueing */ |
378 | BUG_ON(!sock_flag(sk, SOCK_MEMALLOC)); | 379 | BUG_ON(!sock_flag(sk, SOCK_MEMALLOC)); |
379 | 380 | ||
380 | current->flags |= PF_MEMALLOC; | 381 | noreclaim_flag = memalloc_noreclaim_save(); |
381 | ret = sk->sk_backlog_rcv(sk, skb); | 382 | ret = sk->sk_backlog_rcv(sk, skb); |
382 | current_restore_flags(pflags, PF_MEMALLOC); | 383 | memalloc_noreclaim_restore(noreclaim_flag); |
383 | 384 | ||
384 | return ret; | 385 | return ret; |
385 | } | 386 | } |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 9afa2a5030b2..405483a07efc 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -2361,7 +2361,8 @@ MODULE_AUTHOR("Linux DECnet Project Team"); | |||
2361 | MODULE_LICENSE("GPL"); | 2361 | MODULE_LICENSE("GPL"); |
2362 | MODULE_ALIAS_NETPROTO(PF_DECnet); | 2362 | MODULE_ALIAS_NETPROTO(PF_DECnet); |
2363 | 2363 | ||
2364 | static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n"; | 2364 | static const char banner[] __initconst = KERN_INFO |
2365 | "NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n"; | ||
2365 | 2366 | ||
2366 | static int __init decnet_init(void) | 2367 | static int __init decnet_init(void) |
2367 | { | 2368 | { |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 482730cd8a56..eeb5fc561f80 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -110,7 +110,7 @@ struct neigh_table dn_neigh_table = { | |||
110 | static int dn_neigh_construct(struct neighbour *neigh) | 110 | static int dn_neigh_construct(struct neighbour *neigh) |
111 | { | 111 | { |
112 | struct net_device *dev = neigh->dev; | 112 | struct net_device *dev = neigh->dev; |
113 | struct dn_neigh *dn = (struct dn_neigh *)neigh; | 113 | struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n); |
114 | struct dn_dev *dn_db; | 114 | struct dn_dev *dn_db; |
115 | struct neigh_parms *parms; | 115 | struct neigh_parms *parms; |
116 | 116 | ||
@@ -339,7 +339,7 @@ int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
339 | struct dst_entry *dst = skb_dst(skb); | 339 | struct dst_entry *dst = skb_dst(skb); |
340 | struct dn_route *rt = (struct dn_route *) dst; | 340 | struct dn_route *rt = (struct dn_route *) dst; |
341 | struct neighbour *neigh = rt->n; | 341 | struct neighbour *neigh = rt->n; |
342 | struct dn_neigh *dn = (struct dn_neigh *)neigh; | 342 | struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n); |
343 | struct dn_dev *dn_db; | 343 | struct dn_dev *dn_db; |
344 | bool use_long; | 344 | bool use_long; |
345 | 345 | ||
@@ -391,7 +391,7 @@ int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
391 | 391 | ||
392 | neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); | 392 | neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); |
393 | 393 | ||
394 | dn = (struct dn_neigh *)neigh; | 394 | dn = container_of(neigh, struct dn_neigh, n); |
395 | 395 | ||
396 | if (neigh) { | 396 | if (neigh) { |
397 | write_lock(&neigh->lock); | 397 | write_lock(&neigh->lock); |
@@ -451,7 +451,7 @@ int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb | |||
451 | 451 | ||
452 | neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); | 452 | neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); |
453 | 453 | ||
454 | dn = (struct dn_neigh *)neigh; | 454 | dn = container_of(neigh, struct dn_neigh, n); |
455 | 455 | ||
456 | if (neigh) { | 456 | if (neigh) { |
457 | write_lock(&neigh->lock); | 457 | write_lock(&neigh->lock); |
@@ -510,7 +510,7 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info) | |||
510 | if (neigh->dev != s->dev) | 510 | if (neigh->dev != s->dev) |
511 | return; | 511 | return; |
512 | 512 | ||
513 | dn = (struct dn_neigh *) neigh; | 513 | dn = container_of(neigh, struct dn_neigh, n); |
514 | if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2))) | 514 | if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2))) |
515 | return; | 515 | return; |
516 | 516 | ||
@@ -549,7 +549,7 @@ int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n) | |||
549 | static inline void dn_neigh_format_entry(struct seq_file *seq, | 549 | static inline void dn_neigh_format_entry(struct seq_file *seq, |
550 | struct neighbour *n) | 550 | struct neighbour *n) |
551 | { | 551 | { |
552 | struct dn_neigh *dn = (struct dn_neigh *) n; | 552 | struct dn_neigh *dn = container_of(n, struct dn_neigh, n); |
553 | char buf[DN_ASCBUF_LEN]; | 553 | char buf[DN_ASCBUF_LEN]; |
554 | 554 | ||
555 | read_lock(&n->lock); | 555 | read_lock(&n->lock); |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 5e313c1ac94f..1054d330bf9d 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -794,6 +794,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk, | |||
794 | /* listeners have SOCK_RCU_FREE, not the children */ | 794 | /* listeners have SOCK_RCU_FREE, not the children */ |
795 | sock_reset_flag(newsk, SOCK_RCU_FREE); | 795 | sock_reset_flag(newsk, SOCK_RCU_FREE); |
796 | 796 | ||
797 | inet_sk(newsk)->mc_list = NULL; | ||
798 | |||
797 | newsk->sk_mark = inet_rsk(req)->ir_mark; | 799 | newsk->sk_mark = inet_rsk(req)->ir_mark; |
798 | atomic64_set(&newsk->sk_cookie, | 800 | atomic64_set(&newsk->sk_cookie, |
799 | atomic64_read(&inet_rsk(req)->ir_cookie)); | 801 | atomic64_read(&inet_rsk(req)->ir_cookie)); |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 8bea74298173..e9a59d2d91d4 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -678,11 +678,7 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) | |||
678 | /* no more locks than number of hash buckets */ | 678 | /* no more locks than number of hash buckets */ |
679 | nblocks = min(nblocks, hashinfo->ehash_mask + 1); | 679 | nblocks = min(nblocks, hashinfo->ehash_mask + 1); |
680 | 680 | ||
681 | hashinfo->ehash_locks = kmalloc_array(nblocks, locksz, | 681 | hashinfo->ehash_locks = kvmalloc_array(nblocks, locksz, GFP_KERNEL); |
682 | GFP_KERNEL | __GFP_NOWARN); | ||
683 | if (!hashinfo->ehash_locks) | ||
684 | hashinfo->ehash_locks = vmalloc(nblocks * locksz); | ||
685 | |||
686 | if (!hashinfo->ehash_locks) | 682 | if (!hashinfo->ehash_locks) |
687 | return -ENOMEM; | 683 | return -ENOMEM; |
688 | 684 | ||
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 40977413fd48..4ec9affb2252 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -546,12 +546,13 @@ static int vti_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
546 | struct ip_tunnel *t = netdev_priv(dev); | 546 | struct ip_tunnel *t = netdev_priv(dev); |
547 | struct ip_tunnel_parm *p = &t->parms; | 547 | struct ip_tunnel_parm *p = &t->parms; |
548 | 548 | ||
549 | nla_put_u32(skb, IFLA_VTI_LINK, p->link); | 549 | if (nla_put_u32(skb, IFLA_VTI_LINK, p->link) || |
550 | nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key); | 550 | nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key) || |
551 | nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key); | 551 | nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key) || |
552 | nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr); | 552 | nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr) || |
553 | nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr); | 553 | nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr) || |
554 | nla_put_u32(skb, IFLA_VTI_FWMARK, t->fwmark); | 554 | nla_put_u32(skb, IFLA_VTI_FWMARK, t->fwmark)) |
555 | return -EMSGSIZE; | ||
555 | 556 | ||
556 | return 0; | 557 | return 0; |
557 | } | 558 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 9d943974de2b..bdffad875691 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -358,6 +358,9 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, | |||
358 | rt->dst.dev->mtu); | 358 | rt->dst.dev->mtu); |
359 | return -EMSGSIZE; | 359 | return -EMSGSIZE; |
360 | } | 360 | } |
361 | if (length < sizeof(struct iphdr)) | ||
362 | return -EINVAL; | ||
363 | |||
361 | if (flags&MSG_PROBE) | 364 | if (flags&MSG_PROBE) |
362 | goto out; | 365 | goto out; |
363 | 366 | ||
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 496b97e17aaf..0257d965f111 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/siphash.h> | 16 | #include <linux/siphash.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/export.h> | 18 | #include <linux/export.h> |
19 | #include <net/secure_seq.h> | ||
19 | #include <net/tcp.h> | 20 | #include <net/tcp.h> |
20 | #include <net/route.h> | 21 | #include <net/route.h> |
21 | 22 | ||
@@ -203,7 +204,7 @@ EXPORT_SYMBOL_GPL(__cookie_v4_check); | |||
203 | 204 | ||
204 | struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, | 205 | struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, |
205 | struct request_sock *req, | 206 | struct request_sock *req, |
206 | struct dst_entry *dst) | 207 | struct dst_entry *dst, u32 tsoff) |
207 | { | 208 | { |
208 | struct inet_connection_sock *icsk = inet_csk(sk); | 209 | struct inet_connection_sock *icsk = inet_csk(sk); |
209 | struct sock *child; | 210 | struct sock *child; |
@@ -213,6 +214,7 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
213 | NULL, &own_req); | 214 | NULL, &own_req); |
214 | if (child) { | 215 | if (child) { |
215 | atomic_set(&req->rsk_refcnt, 1); | 216 | atomic_set(&req->rsk_refcnt, 1); |
217 | tcp_sk(child)->tsoffset = tsoff; | ||
216 | sock_rps_save_rxhash(child, skb); | 218 | sock_rps_save_rxhash(child, skb); |
217 | inet_csk_reqsk_queue_add(sk, req, child); | 219 | inet_csk_reqsk_queue_add(sk, req, child); |
218 | } else { | 220 | } else { |
@@ -292,6 +294,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
292 | struct rtable *rt; | 294 | struct rtable *rt; |
293 | __u8 rcv_wscale; | 295 | __u8 rcv_wscale; |
294 | struct flowi4 fl4; | 296 | struct flowi4 fl4; |
297 | u32 tsoff = 0; | ||
295 | 298 | ||
296 | if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) | 299 | if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) |
297 | goto out; | 300 | goto out; |
@@ -311,6 +314,11 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
311 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 314 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
312 | tcp_parse_options(skb, &tcp_opt, 0, NULL); | 315 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
313 | 316 | ||
317 | if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) { | ||
318 | tsoff = secure_tcp_ts_off(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr); | ||
319 | tcp_opt.rcv_tsecr -= tsoff; | ||
320 | } | ||
321 | |||
314 | if (!cookie_timestamp_decode(&tcp_opt)) | 322 | if (!cookie_timestamp_decode(&tcp_opt)) |
315 | goto out; | 323 | goto out; |
316 | 324 | ||
@@ -381,7 +389,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
381 | ireq->rcv_wscale = rcv_wscale; | 389 | ireq->rcv_wscale = rcv_wscale; |
382 | ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst); | 390 | ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst); |
383 | 391 | ||
384 | ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst); | 392 | ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst, tsoff); |
385 | /* ip_queue_xmit() depends on our flow being setup | 393 | /* ip_queue_xmit() depends on our flow being setup |
386 | * Normal sockets get it right from inet_csk_route_child_sock() | 394 | * Normal sockets get it right from inet_csk_route_child_sock() |
387 | */ | 395 | */ |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9739962bfb3f..5a3ad09e2786 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -85,7 +85,6 @@ int sysctl_tcp_dsack __read_mostly = 1; | |||
85 | int sysctl_tcp_app_win __read_mostly = 31; | 85 | int sysctl_tcp_app_win __read_mostly = 31; |
86 | int sysctl_tcp_adv_win_scale __read_mostly = 1; | 86 | int sysctl_tcp_adv_win_scale __read_mostly = 1; |
87 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); | 87 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); |
88 | EXPORT_SYMBOL(sysctl_tcp_timestamps); | ||
89 | 88 | ||
90 | /* rfc5961 challenge ack rate limiting */ | 89 | /* rfc5961 challenge ack rate limiting */ |
91 | int sysctl_tcp_challenge_ack_limit = 1000; | 90 | int sysctl_tcp_challenge_ack_limit = 1000; |
@@ -6347,8 +6346,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, | |||
6347 | if (security_inet_conn_request(sk, skb, req)) | 6346 | if (security_inet_conn_request(sk, skb, req)) |
6348 | goto drop_and_free; | 6347 | goto drop_and_free; |
6349 | 6348 | ||
6350 | if (isn && tmp_opt.tstamp_ok) | 6349 | if (tmp_opt.tstamp_ok) |
6351 | af_ops->init_seq_tsoff(skb, &tcp_rsk(req)->ts_off); | 6350 | tcp_rsk(req)->ts_off = af_ops->init_ts_off(skb); |
6352 | 6351 | ||
6353 | if (!want_cookie && !isn) { | 6352 | if (!want_cookie && !isn) { |
6354 | /* Kill the following clause, if you dislike this way. */ | 6353 | /* Kill the following clause, if you dislike this way. */ |
@@ -6368,7 +6367,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, | |||
6368 | goto drop_and_release; | 6367 | goto drop_and_release; |
6369 | } | 6368 | } |
6370 | 6369 | ||
6371 | isn = af_ops->init_seq_tsoff(skb, &tcp_rsk(req)->ts_off); | 6370 | isn = af_ops->init_seq(skb); |
6372 | } | 6371 | } |
6373 | if (!dst) { | 6372 | if (!dst) { |
6374 | dst = af_ops->route_req(sk, &fl, req); | 6373 | dst = af_ops->route_req(sk, &fl, req); |
@@ -6380,7 +6379,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, | |||
6380 | 6379 | ||
6381 | if (want_cookie) { | 6380 | if (want_cookie) { |
6382 | isn = cookie_init_sequence(af_ops, sk, skb, &req->mss); | 6381 | isn = cookie_init_sequence(af_ops, sk, skb, &req->mss); |
6383 | tcp_rsk(req)->ts_off = 0; | ||
6384 | req->cookie_ts = tmp_opt.tstamp_ok; | 6382 | req->cookie_ts = tmp_opt.tstamp_ok; |
6385 | if (!tmp_opt.tstamp_ok) | 6383 | if (!tmp_opt.tstamp_ok) |
6386 | inet_rsk(req)->ecn_ok = 0; | 6384 | inet_rsk(req)->ecn_ok = 0; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index cbbafe546c0f..3a51582bef55 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -94,12 +94,18 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, | |||
94 | struct inet_hashinfo tcp_hashinfo; | 94 | struct inet_hashinfo tcp_hashinfo; |
95 | EXPORT_SYMBOL(tcp_hashinfo); | 95 | EXPORT_SYMBOL(tcp_hashinfo); |
96 | 96 | ||
97 | static u32 tcp_v4_init_seq_and_tsoff(const struct sk_buff *skb, u32 *tsoff) | 97 | static u32 tcp_v4_init_seq(const struct sk_buff *skb) |
98 | { | 98 | { |
99 | return secure_tcp_seq_and_tsoff(ip_hdr(skb)->daddr, | 99 | return secure_tcp_seq(ip_hdr(skb)->daddr, |
100 | ip_hdr(skb)->saddr, | 100 | ip_hdr(skb)->saddr, |
101 | tcp_hdr(skb)->dest, | 101 | tcp_hdr(skb)->dest, |
102 | tcp_hdr(skb)->source, tsoff); | 102 | tcp_hdr(skb)->source); |
103 | } | ||
104 | |||
105 | static u32 tcp_v4_init_ts_off(const struct sk_buff *skb) | ||
106 | { | ||
107 | return secure_tcp_ts_off(ip_hdr(skb)->daddr, | ||
108 | ip_hdr(skb)->saddr); | ||
103 | } | 109 | } |
104 | 110 | ||
105 | int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) | 111 | int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) |
@@ -145,7 +151,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
145 | struct flowi4 *fl4; | 151 | struct flowi4 *fl4; |
146 | struct rtable *rt; | 152 | struct rtable *rt; |
147 | int err; | 153 | int err; |
148 | u32 seq; | ||
149 | struct ip_options_rcu *inet_opt; | 154 | struct ip_options_rcu *inet_opt; |
150 | struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; | 155 | struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; |
151 | 156 | ||
@@ -232,13 +237,13 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
232 | rt = NULL; | 237 | rt = NULL; |
233 | 238 | ||
234 | if (likely(!tp->repair)) { | 239 | if (likely(!tp->repair)) { |
235 | seq = secure_tcp_seq_and_tsoff(inet->inet_saddr, | ||
236 | inet->inet_daddr, | ||
237 | inet->inet_sport, | ||
238 | usin->sin_port, | ||
239 | &tp->tsoffset); | ||
240 | if (!tp->write_seq) | 240 | if (!tp->write_seq) |
241 | tp->write_seq = seq; | 241 | tp->write_seq = secure_tcp_seq(inet->inet_saddr, |
242 | inet->inet_daddr, | ||
243 | inet->inet_sport, | ||
244 | usin->sin_port); | ||
245 | tp->tsoffset = secure_tcp_ts_off(inet->inet_saddr, | ||
246 | inet->inet_daddr); | ||
242 | } | 247 | } |
243 | 248 | ||
244 | inet->inet_id = tp->write_seq ^ jiffies; | 249 | inet->inet_id = tp->write_seq ^ jiffies; |
@@ -1239,7 +1244,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | |||
1239 | .cookie_init_seq = cookie_v4_init_sequence, | 1244 | .cookie_init_seq = cookie_v4_init_sequence, |
1240 | #endif | 1245 | #endif |
1241 | .route_req = tcp_v4_route_req, | 1246 | .route_req = tcp_v4_route_req, |
1242 | .init_seq_tsoff = tcp_v4_init_seq_and_tsoff, | 1247 | .init_seq = tcp_v4_init_seq, |
1248 | .init_ts_off = tcp_v4_init_ts_off, | ||
1243 | .send_synack = tcp_v4_send_synack, | 1249 | .send_synack = tcp_v4_send_synack, |
1244 | }; | 1250 | }; |
1245 | 1251 | ||
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 9d0d4f39e42b..653bbd67e3a3 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -1011,10 +1011,7 @@ static int __net_init tcp_net_metrics_init(struct net *net) | |||
1011 | tcp_metrics_hash_log = order_base_2(slots); | 1011 | tcp_metrics_hash_log = order_base_2(slots); |
1012 | size = sizeof(struct tcpm_hash_bucket) << tcp_metrics_hash_log; | 1012 | size = sizeof(struct tcpm_hash_bucket) << tcp_metrics_hash_log; |
1013 | 1013 | ||
1014 | tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); | 1014 | tcp_metrics_hash = kvzalloc(size, GFP_KERNEL); |
1015 | if (!tcp_metrics_hash) | ||
1016 | tcp_metrics_hash = vzalloc(size); | ||
1017 | |||
1018 | if (!tcp_metrics_hash) | 1015 | if (!tcp_metrics_hash) |
1019 | return -ENOMEM; | 1016 | return -ENOMEM; |
1020 | 1017 | ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 8f6373b0cd77..717be4de5324 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -523,6 +523,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, | |||
523 | newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; | 523 | newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; |
524 | newtp->rx_opt.mss_clamp = req->mss; | 524 | newtp->rx_opt.mss_clamp = req->mss; |
525 | tcp_ecn_openreq_child(newtp, req); | 525 | tcp_ecn_openreq_child(newtp, req); |
526 | newtp->fastopen_req = NULL; | ||
526 | newtp->fastopen_rsk = NULL; | 527 | newtp->fastopen_rsk = NULL; |
527 | newtp->syn_data_acked = 0; | 528 | newtp->syn_data_acked = 0; |
528 | newtp->rack.mstamp.v64 = 0; | 529 | newtp->rack.mstamp.v64 = 0; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 60111a0fc201..4858e190f6ac 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1514,6 +1514,7 @@ static void tcp_cwnd_application_limited(struct sock *sk) | |||
1514 | 1514 | ||
1515 | static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited) | 1515 | static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited) |
1516 | { | 1516 | { |
1517 | const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; | ||
1517 | struct tcp_sock *tp = tcp_sk(sk); | 1518 | struct tcp_sock *tp = tcp_sk(sk); |
1518 | 1519 | ||
1519 | /* Track the maximum number of outstanding packets in each | 1520 | /* Track the maximum number of outstanding packets in each |
@@ -1536,7 +1537,8 @@ static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited) | |||
1536 | tp->snd_cwnd_used = tp->packets_out; | 1537 | tp->snd_cwnd_used = tp->packets_out; |
1537 | 1538 | ||
1538 | if (sysctl_tcp_slow_start_after_idle && | 1539 | if (sysctl_tcp_slow_start_after_idle && |
1539 | (s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto) | 1540 | (s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto && |
1541 | !ca_ops->cong_control) | ||
1540 | tcp_cwnd_application_limited(sk); | 1542 | tcp_cwnd_application_limited(sk); |
1541 | 1543 | ||
1542 | /* The following conditions together indicate the starvation | 1544 | /* The following conditions together indicate the starvation |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b09ac38d8dc4..8d297a79b568 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3328,7 +3328,8 @@ static int fixup_permanent_addr(struct inet6_dev *idev, | |||
3328 | idev->dev, 0, 0); | 3328 | idev->dev, 0, 0); |
3329 | } | 3329 | } |
3330 | 3330 | ||
3331 | addrconf_dad_start(ifp); | 3331 | if (ifp->state == INET6_IFADDR_STATE_PREDAD) |
3332 | addrconf_dad_start(ifp); | ||
3332 | 3333 | ||
3333 | return 0; | 3334 | return 0; |
3334 | } | 3335 | } |
@@ -3547,6 +3548,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
3547 | */ | 3548 | */ |
3548 | static struct notifier_block ipv6_dev_notf = { | 3549 | static struct notifier_block ipv6_dev_notf = { |
3549 | .notifier_call = addrconf_notify, | 3550 | .notifier_call = addrconf_notify, |
3551 | .priority = ADDRCONF_NOTIFY_PRIORITY, | ||
3550 | }; | 3552 | }; |
3551 | 3553 | ||
3552 | static void addrconf_type_change(struct net_device *dev, unsigned long event) | 3554 | static void addrconf_type_change(struct net_device *dev, unsigned long event) |
@@ -3683,7 +3685,7 @@ restart: | |||
3683 | if (keep) { | 3685 | if (keep) { |
3684 | /* set state to skip the notifier below */ | 3686 | /* set state to skip the notifier below */ |
3685 | state = INET6_IFADDR_STATE_DEAD; | 3687 | state = INET6_IFADDR_STATE_DEAD; |
3686 | ifa->state = 0; | 3688 | ifa->state = INET6_IFADDR_STATE_PREDAD; |
3687 | if (!(ifa->flags & IFA_F_NODAD)) | 3689 | if (!(ifa->flags & IFA_F_NODAD)) |
3688 | ifa->flags |= IFA_F_TENTATIVE; | 3690 | ifa->flags |= IFA_F_TENTATIVE; |
3689 | 3691 | ||
@@ -6572,6 +6574,8 @@ int __init addrconf_init(void) | |||
6572 | goto errlo; | 6574 | goto errlo; |
6573 | } | 6575 | } |
6574 | 6576 | ||
6577 | ip6_route_init_special_entries(); | ||
6578 | |||
6575 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | 6579 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
6576 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | 6580 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); |
6577 | 6581 | ||
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index af8f52ee7180..2fd5ca151dcf 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c | |||
@@ -41,13 +41,7 @@ static int alloc_ila_locks(struct ila_net *ilan) | |||
41 | size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU); | 41 | size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU); |
42 | 42 | ||
43 | if (sizeof(spinlock_t) != 0) { | 43 | if (sizeof(spinlock_t) != 0) { |
44 | #ifdef CONFIG_NUMA | 44 | ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL); |
45 | if (size * sizeof(spinlock_t) > PAGE_SIZE) | ||
46 | ilan->locks = vmalloc(size * sizeof(spinlock_t)); | ||
47 | else | ||
48 | #endif | ||
49 | ilan->locks = kmalloc_array(size, sizeof(spinlock_t), | ||
50 | GFP_KERNEL); | ||
51 | if (!ilan->locks) | 45 | if (!ilan->locks) |
52 | return -ENOMEM; | 46 | return -ENOMEM; |
53 | for (i = 0; i < size; i++) | 47 | for (i = 0; i < size; i++) |
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index bf3ad3e7b647..b2b4f031b3a1 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | |||
@@ -235,7 +235,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, | |||
235 | inside->icmp6.icmp6_cksum = | 235 | inside->icmp6.icmp6_cksum = |
236 | csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | 236 | csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, |
237 | skb->len - hdrlen, IPPROTO_ICMPV6, | 237 | skb->len - hdrlen, IPPROTO_ICMPV6, |
238 | csum_partial(&inside->icmp6, | 238 | skb_checksum(skb, hdrlen, |
239 | skb->len - hdrlen, 0)); | 239 | skb->len - hdrlen, 0)); |
240 | } | 240 | } |
241 | 241 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 0da6a12b5472..1f992d9e261d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -632,6 +632,8 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, | |||
632 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); | 632 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); |
633 | return -EMSGSIZE; | 633 | return -EMSGSIZE; |
634 | } | 634 | } |
635 | if (length < sizeof(struct ipv6hdr)) | ||
636 | return -EINVAL; | ||
635 | if (flags&MSG_PROBE) | 637 | if (flags&MSG_PROBE) |
636 | goto out; | 638 | goto out; |
637 | 639 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a1bf426c959b..dc61b0b5e64e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -3709,7 +3709,10 @@ static int ip6_route_dev_notify(struct notifier_block *this, | |||
3709 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 3709 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
3710 | struct net *net = dev_net(dev); | 3710 | struct net *net = dev_net(dev); |
3711 | 3711 | ||
3712 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | 3712 | if (!(dev->flags & IFF_LOOPBACK)) |
3713 | return NOTIFY_OK; | ||
3714 | |||
3715 | if (event == NETDEV_REGISTER) { | ||
3713 | net->ipv6.ip6_null_entry->dst.dev = dev; | 3716 | net->ipv6.ip6_null_entry->dst.dev = dev; |
3714 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | 3717 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); |
3715 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 3718 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
@@ -3718,6 +3721,12 @@ static int ip6_route_dev_notify(struct notifier_block *this, | |||
3718 | net->ipv6.ip6_blk_hole_entry->dst.dev = dev; | 3721 | net->ipv6.ip6_blk_hole_entry->dst.dev = dev; |
3719 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | 3722 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); |
3720 | #endif | 3723 | #endif |
3724 | } else if (event == NETDEV_UNREGISTER) { | ||
3725 | in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev); | ||
3726 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
3727 | in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev); | ||
3728 | in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev); | ||
3729 | #endif | ||
3721 | } | 3730 | } |
3722 | 3731 | ||
3723 | return NOTIFY_OK; | 3732 | return NOTIFY_OK; |
@@ -4024,9 +4033,24 @@ static struct pernet_operations ip6_route_net_late_ops = { | |||
4024 | 4033 | ||
4025 | static struct notifier_block ip6_route_dev_notifier = { | 4034 | static struct notifier_block ip6_route_dev_notifier = { |
4026 | .notifier_call = ip6_route_dev_notify, | 4035 | .notifier_call = ip6_route_dev_notify, |
4027 | .priority = 0, | 4036 | .priority = ADDRCONF_NOTIFY_PRIORITY - 10, |
4028 | }; | 4037 | }; |
4029 | 4038 | ||
4039 | void __init ip6_route_init_special_entries(void) | ||
4040 | { | ||
4041 | /* Registering of the loopback is done before this portion of code, | ||
4042 | * the loopback reference in rt6_info will not be taken, do it | ||
4043 | * manually for init_net */ | ||
4044 | init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; | ||
4045 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4046 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
4047 | init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; | ||
4048 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4049 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; | ||
4050 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4051 | #endif | ||
4052 | } | ||
4053 | |||
4030 | int __init ip6_route_init(void) | 4054 | int __init ip6_route_init(void) |
4031 | { | 4055 | { |
4032 | int ret; | 4056 | int ret; |
@@ -4053,17 +4077,6 @@ int __init ip6_route_init(void) | |||
4053 | 4077 | ||
4054 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; | 4078 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; |
4055 | 4079 | ||
4056 | /* Registering of the loopback is done before this portion of code, | ||
4057 | * the loopback reference in rt6_info will not be taken, do it | ||
4058 | * manually for init_net */ | ||
4059 | init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; | ||
4060 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4061 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
4062 | init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; | ||
4063 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4064 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; | ||
4065 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4066 | #endif | ||
4067 | ret = fib6_init(); | 4080 | ret = fib6_init(); |
4068 | if (ret) | 4081 | if (ret) |
4069 | goto out_register_subsys; | 4082 | goto out_register_subsys; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 895ff650db43..5abc3692b901 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/random.h> | 18 | #include <linux/random.h> |
19 | #include <linux/siphash.h> | 19 | #include <linux/siphash.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <net/secure_seq.h> | ||
21 | #include <net/ipv6.h> | 22 | #include <net/ipv6.h> |
22 | #include <net/tcp.h> | 23 | #include <net/tcp.h> |
23 | 24 | ||
@@ -143,6 +144,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
143 | int mss; | 144 | int mss; |
144 | struct dst_entry *dst; | 145 | struct dst_entry *dst; |
145 | __u8 rcv_wscale; | 146 | __u8 rcv_wscale; |
147 | u32 tsoff = 0; | ||
146 | 148 | ||
147 | if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) | 149 | if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) |
148 | goto out; | 150 | goto out; |
@@ -162,6 +164,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
162 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 164 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
163 | tcp_parse_options(skb, &tcp_opt, 0, NULL); | 165 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
164 | 166 | ||
167 | if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) { | ||
168 | tsoff = secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32, | ||
169 | ipv6_hdr(skb)->saddr.s6_addr32); | ||
170 | tcp_opt.rcv_tsecr -= tsoff; | ||
171 | } | ||
172 | |||
165 | if (!cookie_timestamp_decode(&tcp_opt)) | 173 | if (!cookie_timestamp_decode(&tcp_opt)) |
166 | goto out; | 174 | goto out; |
167 | 175 | ||
@@ -242,7 +250,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
242 | ireq->rcv_wscale = rcv_wscale; | 250 | ireq->rcv_wscale = rcv_wscale; |
243 | ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst); | 251 | ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst); |
244 | 252 | ||
245 | ret = tcp_get_cookie_sock(sk, skb, req, dst); | 253 | ret = tcp_get_cookie_sock(sk, skb, req, dst, tsoff); |
246 | out: | 254 | out: |
247 | return ret; | 255 | return ret; |
248 | out_free: | 256 | out_free: |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8e42e8f54b70..aeb9497b5bb7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -101,12 +101,18 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | |||
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | static u32 tcp_v6_init_seq_and_tsoff(const struct sk_buff *skb, u32 *tsoff) | 104 | static u32 tcp_v6_init_seq(const struct sk_buff *skb) |
105 | { | 105 | { |
106 | return secure_tcpv6_seq_and_tsoff(ipv6_hdr(skb)->daddr.s6_addr32, | 106 | return secure_tcpv6_seq(ipv6_hdr(skb)->daddr.s6_addr32, |
107 | ipv6_hdr(skb)->saddr.s6_addr32, | 107 | ipv6_hdr(skb)->saddr.s6_addr32, |
108 | tcp_hdr(skb)->dest, | 108 | tcp_hdr(skb)->dest, |
109 | tcp_hdr(skb)->source, tsoff); | 109 | tcp_hdr(skb)->source); |
110 | } | ||
111 | |||
112 | static u32 tcp_v6_init_ts_off(const struct sk_buff *skb) | ||
113 | { | ||
114 | return secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32, | ||
115 | ipv6_hdr(skb)->saddr.s6_addr32); | ||
110 | } | 116 | } |
111 | 117 | ||
112 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | 118 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, |
@@ -122,7 +128,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
122 | struct flowi6 fl6; | 128 | struct flowi6 fl6; |
123 | struct dst_entry *dst; | 129 | struct dst_entry *dst; |
124 | int addr_type; | 130 | int addr_type; |
125 | u32 seq; | ||
126 | int err; | 131 | int err; |
127 | struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; | 132 | struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; |
128 | 133 | ||
@@ -282,13 +287,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
282 | sk_set_txhash(sk); | 287 | sk_set_txhash(sk); |
283 | 288 | ||
284 | if (likely(!tp->repair)) { | 289 | if (likely(!tp->repair)) { |
285 | seq = secure_tcpv6_seq_and_tsoff(np->saddr.s6_addr32, | ||
286 | sk->sk_v6_daddr.s6_addr32, | ||
287 | inet->inet_sport, | ||
288 | inet->inet_dport, | ||
289 | &tp->tsoffset); | ||
290 | if (!tp->write_seq) | 290 | if (!tp->write_seq) |
291 | tp->write_seq = seq; | 291 | tp->write_seq = secure_tcpv6_seq(np->saddr.s6_addr32, |
292 | sk->sk_v6_daddr.s6_addr32, | ||
293 | inet->inet_sport, | ||
294 | inet->inet_dport); | ||
295 | tp->tsoffset = secure_tcpv6_ts_off(np->saddr.s6_addr32, | ||
296 | sk->sk_v6_daddr.s6_addr32); | ||
292 | } | 297 | } |
293 | 298 | ||
294 | if (tcp_fastopen_defer_connect(sk, &err)) | 299 | if (tcp_fastopen_defer_connect(sk, &err)) |
@@ -749,7 +754,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
749 | .cookie_init_seq = cookie_v6_init_sequence, | 754 | .cookie_init_seq = cookie_v6_init_sequence, |
750 | #endif | 755 | #endif |
751 | .route_req = tcp_v6_route_req, | 756 | .route_req = tcp_v6_route_req, |
752 | .init_seq_tsoff = tcp_v6_init_seq_and_tsoff, | 757 | .init_seq = tcp_v6_init_seq, |
758 | .init_ts_off = tcp_v6_init_ts_off, | ||
753 | .send_synack = tcp_v6_send_synack, | 759 | .send_synack = tcp_v6_send_synack, |
754 | }; | 760 | }; |
755 | 761 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6db09fa18269..364d4e137649 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -66,6 +66,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
66 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | 66 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + |
67 | 2 + sizeof(struct ieee80211_ht_cap) + | 67 | 2 + sizeof(struct ieee80211_ht_cap) + |
68 | 2 + sizeof(struct ieee80211_ht_operation) + | 68 | 2 + sizeof(struct ieee80211_ht_operation) + |
69 | 2 + sizeof(struct ieee80211_vht_cap) + | ||
70 | 2 + sizeof(struct ieee80211_vht_operation) + | ||
69 | ifibss->ie_len; | 71 | ifibss->ie_len; |
70 | presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); | 72 | presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); |
71 | if (!presp) | 73 | if (!presp) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 89dff563b1ec..0ea9712bd99e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -4382,6 +4382,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
4382 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | 4382 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) |
4383 | return -EINVAL; | 4383 | return -EINVAL; |
4384 | 4384 | ||
4385 | /* If a reconfig is happening, bail out */ | ||
4386 | if (local->in_reconfig) | ||
4387 | return -EBUSY; | ||
4388 | |||
4385 | if (assoc) { | 4389 | if (assoc) { |
4386 | rcu_read_lock(); | 4390 | rcu_read_lock(); |
4387 | have_sta = sta_info_get(sdata, cbss->bssid); | 4391 | have_sta = sta_info_get(sdata, cbss->bssid); |
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 088e2b459d0f..257ec66009da 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -2005,10 +2005,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
2005 | unsigned index; | 2005 | unsigned index; |
2006 | 2006 | ||
2007 | if (size) { | 2007 | if (size) { |
2008 | labels = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); | 2008 | labels = kvzalloc(size, GFP_KERNEL); |
2009 | if (!labels) | ||
2010 | labels = vzalloc(size); | ||
2011 | |||
2012 | if (!labels) | 2009 | if (!labels) |
2013 | goto nolabels; | 2010 | goto nolabels; |
2014 | } | 2011 | } |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 668d9643f0cc..1fa3c2307b6e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -3078,6 +3078,17 @@ nla_put_failure: | |||
3078 | return skb->len; | 3078 | return skb->len; |
3079 | } | 3079 | } |
3080 | 3080 | ||
3081 | static bool ip_vs_is_af_valid(int af) | ||
3082 | { | ||
3083 | if (af == AF_INET) | ||
3084 | return true; | ||
3085 | #ifdef CONFIG_IP_VS_IPV6 | ||
3086 | if (af == AF_INET6 && ipv6_mod_enabled()) | ||
3087 | return true; | ||
3088 | #endif | ||
3089 | return false; | ||
3090 | } | ||
3091 | |||
3081 | static int ip_vs_genl_parse_service(struct netns_ipvs *ipvs, | 3092 | static int ip_vs_genl_parse_service(struct netns_ipvs *ipvs, |
3082 | struct ip_vs_service_user_kern *usvc, | 3093 | struct ip_vs_service_user_kern *usvc, |
3083 | struct nlattr *nla, int full_entry, | 3094 | struct nlattr *nla, int full_entry, |
@@ -3105,11 +3116,7 @@ static int ip_vs_genl_parse_service(struct netns_ipvs *ipvs, | |||
3105 | memset(usvc, 0, sizeof(*usvc)); | 3116 | memset(usvc, 0, sizeof(*usvc)); |
3106 | 3117 | ||
3107 | usvc->af = nla_get_u16(nla_af); | 3118 | usvc->af = nla_get_u16(nla_af); |
3108 | #ifdef CONFIG_IP_VS_IPV6 | 3119 | if (!ip_vs_is_af_valid(usvc->af)) |
3109 | if (usvc->af != AF_INET && usvc->af != AF_INET6) | ||
3110 | #else | ||
3111 | if (usvc->af != AF_INET) | ||
3112 | #endif | ||
3113 | return -EAFNOSUPPORT; | 3120 | return -EAFNOSUPPORT; |
3114 | 3121 | ||
3115 | if (nla_fwmark) { | 3122 | if (nla_fwmark) { |
@@ -3612,6 +3619,11 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3612 | if (udest.af == 0) | 3619 | if (udest.af == 0) |
3613 | udest.af = svc->af; | 3620 | udest.af = svc->af; |
3614 | 3621 | ||
3622 | if (!ip_vs_is_af_valid(udest.af)) { | ||
3623 | ret = -EAFNOSUPPORT; | ||
3624 | goto out; | ||
3625 | } | ||
3626 | |||
3615 | if (udest.af != svc->af && cmd != IPVS_CMD_DEL_DEST) { | 3627 | if (udest.af != svc->af && cmd != IPVS_CMD_DEL_DEST) { |
3616 | /* The synchronization protocol is incompatible | 3628 | /* The synchronization protocol is incompatible |
3617 | * with mixed family services | 3629 | * with mixed family services |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index f9245dbfe435..3c8f1ed2f555 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -1853,7 +1853,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize); | |||
1853 | module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, | 1853 | module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, |
1854 | &nf_conntrack_htable_size, 0600); | 1854 | &nf_conntrack_htable_size, 0600); |
1855 | 1855 | ||
1856 | static unsigned int total_extension_size(void) | 1856 | static __always_inline unsigned int total_extension_size(void) |
1857 | { | 1857 | { |
1858 | /* remember to add new extensions below */ | 1858 | /* remember to add new extensions below */ |
1859 | BUILD_BUG_ON(NF_CT_EXT_NUM > 9); | 1859 | BUILD_BUG_ON(NF_CT_EXT_NUM > 9); |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 4b9dfe3eef62..3a60efa7799b 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -385,7 +385,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) | |||
385 | struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; | 385 | struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; |
386 | unsigned int h = helper_hash(&me->tuple); | 386 | unsigned int h = helper_hash(&me->tuple); |
387 | struct nf_conntrack_helper *cur; | 387 | struct nf_conntrack_helper *cur; |
388 | int ret = 0; | 388 | int ret = 0, i; |
389 | 389 | ||
390 | BUG_ON(me->expect_policy == NULL); | 390 | BUG_ON(me->expect_policy == NULL); |
391 | BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); | 391 | BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); |
@@ -395,10 +395,26 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) | |||
395 | return -EINVAL; | 395 | return -EINVAL; |
396 | 396 | ||
397 | mutex_lock(&nf_ct_helper_mutex); | 397 | mutex_lock(&nf_ct_helper_mutex); |
398 | hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) { | 398 | for (i = 0; i < nf_ct_helper_hsize; i++) { |
399 | if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, &mask)) { | 399 | hlist_for_each_entry(cur, &nf_ct_helper_hash[i], hnode) { |
400 | ret = -EEXIST; | 400 | if (!strcmp(cur->name, me->name) && |
401 | goto out; | 401 | (cur->tuple.src.l3num == NFPROTO_UNSPEC || |
402 | cur->tuple.src.l3num == me->tuple.src.l3num) && | ||
403 | cur->tuple.dst.protonum == me->tuple.dst.protonum) { | ||
404 | ret = -EEXIST; | ||
405 | goto out; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | |||
410 | /* avoid unpredictable behaviour for auto_assign_helper */ | ||
411 | if (!(me->flags & NF_CT_HELPER_F_USERSPACE)) { | ||
412 | hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) { | ||
413 | if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, | ||
414 | &mask)) { | ||
415 | ret = -EEXIST; | ||
416 | goto out; | ||
417 | } | ||
402 | } | 418 | } |
403 | } | 419 | } |
404 | hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); | 420 | hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 5f6f2f388928..dcf561b5c97a 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -417,8 +417,7 @@ nla_put_failure: | |||
417 | return -1; | 417 | return -1; |
418 | } | 418 | } |
419 | 419 | ||
420 | static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, | 420 | static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, struct nf_conn *ct) |
421 | const struct nf_conn *ct) | ||
422 | { | 421 | { |
423 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); | 422 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); |
424 | struct nf_ct_seqadj *seq; | 423 | struct nf_ct_seqadj *seq; |
@@ -426,15 +425,20 @@ static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, | |||
426 | if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj) | 425 | if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj) |
427 | return 0; | 426 | return 0; |
428 | 427 | ||
428 | spin_lock_bh(&ct->lock); | ||
429 | seq = &seqadj->seq[IP_CT_DIR_ORIGINAL]; | 429 | seq = &seqadj->seq[IP_CT_DIR_ORIGINAL]; |
430 | if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1) | 430 | if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1) |
431 | return -1; | 431 | goto err; |
432 | 432 | ||
433 | seq = &seqadj->seq[IP_CT_DIR_REPLY]; | 433 | seq = &seqadj->seq[IP_CT_DIR_REPLY]; |
434 | if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1) | 434 | if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1) |
435 | return -1; | 435 | goto err; |
436 | 436 | ||
437 | spin_unlock_bh(&ct->lock); | ||
437 | return 0; | 438 | return 0; |
439 | err: | ||
440 | spin_unlock_bh(&ct->lock); | ||
441 | return -1; | ||
438 | } | 442 | } |
439 | 443 | ||
440 | static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) | 444 | static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) |
@@ -1417,6 +1421,24 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, | |||
1417 | } | 1421 | } |
1418 | #endif | 1422 | #endif |
1419 | 1423 | ||
1424 | static void | ||
1425 | __ctnetlink_change_status(struct nf_conn *ct, unsigned long on, | ||
1426 | unsigned long off) | ||
1427 | { | ||
1428 | unsigned int bit; | ||
1429 | |||
1430 | /* Ignore these unchangable bits */ | ||
1431 | on &= ~IPS_UNCHANGEABLE_MASK; | ||
1432 | off &= ~IPS_UNCHANGEABLE_MASK; | ||
1433 | |||
1434 | for (bit = 0; bit < __IPS_MAX_BIT; bit++) { | ||
1435 | if (on & (1 << bit)) | ||
1436 | set_bit(bit, &ct->status); | ||
1437 | else if (off & (1 << bit)) | ||
1438 | clear_bit(bit, &ct->status); | ||
1439 | } | ||
1440 | } | ||
1441 | |||
1420 | static int | 1442 | static int |
1421 | ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) | 1443 | ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) |
1422 | { | 1444 | { |
@@ -1436,10 +1458,7 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
1436 | /* ASSURED bit can only be set */ | 1458 | /* ASSURED bit can only be set */ |
1437 | return -EBUSY; | 1459 | return -EBUSY; |
1438 | 1460 | ||
1439 | /* Be careful here, modifying NAT bits can screw up things, | 1461 | __ctnetlink_change_status(ct, status, 0); |
1440 | * so don't let users modify them directly if they don't pass | ||
1441 | * nf_nat_range. */ | ||
1442 | ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK); | ||
1443 | return 0; | 1462 | return 0; |
1444 | } | 1463 | } |
1445 | 1464 | ||
@@ -1508,23 +1527,11 @@ static int ctnetlink_change_helper(struct nf_conn *ct, | |||
1508 | return 0; | 1527 | return 0; |
1509 | } | 1528 | } |
1510 | 1529 | ||
1530 | rcu_read_lock(); | ||
1511 | helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), | 1531 | helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), |
1512 | nf_ct_protonum(ct)); | 1532 | nf_ct_protonum(ct)); |
1513 | if (helper == NULL) { | 1533 | if (helper == NULL) { |
1514 | #ifdef CONFIG_MODULES | 1534 | rcu_read_unlock(); |
1515 | spin_unlock_bh(&nf_conntrack_expect_lock); | ||
1516 | |||
1517 | if (request_module("nfct-helper-%s", helpname) < 0) { | ||
1518 | spin_lock_bh(&nf_conntrack_expect_lock); | ||
1519 | return -EOPNOTSUPP; | ||
1520 | } | ||
1521 | |||
1522 | spin_lock_bh(&nf_conntrack_expect_lock); | ||
1523 | helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), | ||
1524 | nf_ct_protonum(ct)); | ||
1525 | if (helper) | ||
1526 | return -EAGAIN; | ||
1527 | #endif | ||
1528 | return -EOPNOTSUPP; | 1535 | return -EOPNOTSUPP; |
1529 | } | 1536 | } |
1530 | 1537 | ||
@@ -1533,13 +1540,16 @@ static int ctnetlink_change_helper(struct nf_conn *ct, | |||
1533 | /* update private helper data if allowed. */ | 1540 | /* update private helper data if allowed. */ |
1534 | if (helper->from_nlattr) | 1541 | if (helper->from_nlattr) |
1535 | helper->from_nlattr(helpinfo, ct); | 1542 | helper->from_nlattr(helpinfo, ct); |
1536 | return 0; | 1543 | err = 0; |
1537 | } else | 1544 | } else |
1538 | return -EBUSY; | 1545 | err = -EBUSY; |
1546 | } else { | ||
1547 | /* we cannot set a helper for an existing conntrack */ | ||
1548 | err = -EOPNOTSUPP; | ||
1539 | } | 1549 | } |
1540 | 1550 | ||
1541 | /* we cannot set a helper for an existing conntrack */ | 1551 | rcu_read_unlock(); |
1542 | return -EOPNOTSUPP; | 1552 | return err; |
1543 | } | 1553 | } |
1544 | 1554 | ||
1545 | static int ctnetlink_change_timeout(struct nf_conn *ct, | 1555 | static int ctnetlink_change_timeout(struct nf_conn *ct, |
@@ -1630,25 +1640,30 @@ ctnetlink_change_seq_adj(struct nf_conn *ct, | |||
1630 | if (!seqadj) | 1640 | if (!seqadj) |
1631 | return 0; | 1641 | return 0; |
1632 | 1642 | ||
1643 | spin_lock_bh(&ct->lock); | ||
1633 | if (cda[CTA_SEQ_ADJ_ORIG]) { | 1644 | if (cda[CTA_SEQ_ADJ_ORIG]) { |
1634 | ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL], | 1645 | ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL], |
1635 | cda[CTA_SEQ_ADJ_ORIG]); | 1646 | cda[CTA_SEQ_ADJ_ORIG]); |
1636 | if (ret < 0) | 1647 | if (ret < 0) |
1637 | return ret; | 1648 | goto err; |
1638 | 1649 | ||
1639 | ct->status |= IPS_SEQ_ADJUST; | 1650 | set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); |
1640 | } | 1651 | } |
1641 | 1652 | ||
1642 | if (cda[CTA_SEQ_ADJ_REPLY]) { | 1653 | if (cda[CTA_SEQ_ADJ_REPLY]) { |
1643 | ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY], | 1654 | ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY], |
1644 | cda[CTA_SEQ_ADJ_REPLY]); | 1655 | cda[CTA_SEQ_ADJ_REPLY]); |
1645 | if (ret < 0) | 1656 | if (ret < 0) |
1646 | return ret; | 1657 | goto err; |
1647 | 1658 | ||
1648 | ct->status |= IPS_SEQ_ADJUST; | 1659 | set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); |
1649 | } | 1660 | } |
1650 | 1661 | ||
1662 | spin_unlock_bh(&ct->lock); | ||
1651 | return 0; | 1663 | return 0; |
1664 | err: | ||
1665 | spin_unlock_bh(&ct->lock); | ||
1666 | return ret; | ||
1652 | } | 1667 | } |
1653 | 1668 | ||
1654 | static int | 1669 | static int |
@@ -1959,9 +1974,7 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl, | |||
1959 | err = -EEXIST; | 1974 | err = -EEXIST; |
1960 | ct = nf_ct_tuplehash_to_ctrack(h); | 1975 | ct = nf_ct_tuplehash_to_ctrack(h); |
1961 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { | 1976 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { |
1962 | spin_lock_bh(&nf_conntrack_expect_lock); | ||
1963 | err = ctnetlink_change_conntrack(ct, cda); | 1977 | err = ctnetlink_change_conntrack(ct, cda); |
1964 | spin_unlock_bh(&nf_conntrack_expect_lock); | ||
1965 | if (err == 0) { | 1978 | if (err == 0) { |
1966 | nf_conntrack_eventmask_report((1 << IPCT_REPLY) | | 1979 | nf_conntrack_eventmask_report((1 << IPCT_REPLY) | |
1967 | (1 << IPCT_ASSURED) | | 1980 | (1 << IPCT_ASSURED) | |
@@ -2294,10 +2307,10 @@ ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
2294 | /* This check is less strict than ctnetlink_change_status() | 2307 | /* This check is less strict than ctnetlink_change_status() |
2295 | * because callers often flip IPS_EXPECTED bits when sending | 2308 | * because callers often flip IPS_EXPECTED bits when sending |
2296 | * an NFQA_CT attribute to the kernel. So ignore the | 2309 | * an NFQA_CT attribute to the kernel. So ignore the |
2297 | * unchangeable bits but do not error out. | 2310 | * unchangeable bits but do not error out. Also user programs |
2311 | * are allowed to clear the bits that they are allowed to change. | ||
2298 | */ | 2312 | */ |
2299 | ct->status = (status & ~IPS_UNCHANGEABLE_MASK) | | 2313 | __ctnetlink_change_status(ct, status, ~status); |
2300 | (ct->status & IPS_UNCHANGEABLE_MASK); | ||
2301 | return 0; | 2314 | return 0; |
2302 | } | 2315 | } |
2303 | 2316 | ||
@@ -2351,11 +2364,7 @@ ctnetlink_glue_parse(const struct nlattr *attr, struct nf_conn *ct) | |||
2351 | if (ret < 0) | 2364 | if (ret < 0) |
2352 | return ret; | 2365 | return ret; |
2353 | 2366 | ||
2354 | spin_lock_bh(&nf_conntrack_expect_lock); | 2367 | return ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct); |
2355 | ret = ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct); | ||
2356 | spin_unlock_bh(&nf_conntrack_expect_lock); | ||
2357 | |||
2358 | return ret; | ||
2359 | } | 2368 | } |
2360 | 2369 | ||
2361 | static int ctnetlink_glue_exp_parse(const struct nlattr * const *cda, | 2370 | static int ctnetlink_glue_exp_parse(const struct nlattr * const *cda, |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1c6482d2c4dc..559225029740 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -3778,6 +3778,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3778 | err = set->ops->insert(ctx->net, set, &elem, &ext2); | 3778 | err = set->ops->insert(ctx->net, set, &elem, &ext2); |
3779 | if (err) { | 3779 | if (err) { |
3780 | if (err == -EEXIST) { | 3780 | if (err == -EEXIST) { |
3781 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^ | ||
3782 | nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) || | ||
3783 | nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^ | ||
3784 | nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) | ||
3785 | return -EBUSY; | ||
3781 | if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && | 3786 | if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && |
3782 | nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && | 3787 | nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && |
3783 | memcmp(nft_set_ext_data(ext), | 3788 | memcmp(nft_set_ext_data(ext), |
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 3948da380259..66221ad891a9 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c | |||
@@ -82,8 +82,7 @@ static void nft_dynset_eval(const struct nft_expr *expr, | |||
82 | nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { | 82 | nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { |
83 | timeout = priv->timeout ? : set->timeout; | 83 | timeout = priv->timeout ? : set->timeout; |
84 | *nft_set_ext_expiration(ext) = jiffies + timeout; | 84 | *nft_set_ext_expiration(ext) = jiffies + timeout; |
85 | } else if (sexpr == NULL) | 85 | } |
86 | goto out; | ||
87 | 86 | ||
88 | if (sexpr != NULL) | 87 | if (sexpr != NULL) |
89 | sexpr->ops->eval(sexpr, regs, pkt); | 88 | sexpr->ops->eval(sexpr, regs, pkt); |
@@ -92,7 +91,7 @@ static void nft_dynset_eval(const struct nft_expr *expr, | |||
92 | regs->verdict.code = NFT_BREAK; | 91 | regs->verdict.code = NFT_BREAK; |
93 | return; | 92 | return; |
94 | } | 93 | } |
95 | out: | 94 | |
96 | if (!priv->invert) | 95 | if (!priv->invert) |
97 | regs->verdict.code = NFT_BREAK; | 96 | regs->verdict.code = NFT_BREAK; |
98 | } | 97 | } |
diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c index 8ebbc2940f4c..b988162b5b15 100644 --- a/net/netfilter/nft_set_bitmap.c +++ b/net/netfilter/nft_set_bitmap.c | |||
@@ -257,6 +257,11 @@ static int nft_bitmap_init(const struct nft_set *set, | |||
257 | 257 | ||
258 | static void nft_bitmap_destroy(const struct nft_set *set) | 258 | static void nft_bitmap_destroy(const struct nft_set *set) |
259 | { | 259 | { |
260 | struct nft_bitmap *priv = nft_set_priv(set); | ||
261 | struct nft_bitmap_elem *be, *n; | ||
262 | |||
263 | list_for_each_entry_safe(be, n, &priv->list, head) | ||
264 | nft_set_elem_destroy(set, be, true); | ||
260 | } | 265 | } |
261 | 266 | ||
262 | static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features, | 267 | static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features, |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 14857afc9937..8876b7da6884 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -763,17 +763,8 @@ EXPORT_SYMBOL(xt_check_entry_offsets); | |||
763 | */ | 763 | */ |
764 | unsigned int *xt_alloc_entry_offsets(unsigned int size) | 764 | unsigned int *xt_alloc_entry_offsets(unsigned int size) |
765 | { | 765 | { |
766 | unsigned int *off; | 766 | return kvmalloc_array(size, sizeof(unsigned int), GFP_KERNEL | __GFP_ZERO); |
767 | 767 | ||
768 | off = kcalloc(size, sizeof(unsigned int), GFP_KERNEL | __GFP_NOWARN); | ||
769 | |||
770 | if (off) | ||
771 | return off; | ||
772 | |||
773 | if (size < (SIZE_MAX / sizeof(unsigned int))) | ||
774 | off = vmalloc(size * sizeof(unsigned int)); | ||
775 | |||
776 | return off; | ||
777 | } | 768 | } |
778 | EXPORT_SYMBOL(xt_alloc_entry_offsets); | 769 | EXPORT_SYMBOL(xt_alloc_entry_offsets); |
779 | 770 | ||
@@ -1007,8 +998,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) | |||
1007 | if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) | 998 | if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) |
1008 | info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); | 999 | info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); |
1009 | if (!info) { | 1000 | if (!info) { |
1010 | info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN | | 1001 | info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY, |
1011 | __GFP_NORETRY | __GFP_HIGHMEM, | ||
1012 | PAGE_KERNEL); | 1002 | PAGE_KERNEL); |
1013 | if (!info) | 1003 | if (!info) |
1014 | return NULL; | 1004 | return NULL; |
@@ -1051,8 +1041,10 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, | |||
1051 | list_for_each_entry(t, &init_net.xt.tables[af], list) { | 1041 | list_for_each_entry(t, &init_net.xt.tables[af], list) { |
1052 | if (strcmp(t->name, name)) | 1042 | if (strcmp(t->name, name)) |
1053 | continue; | 1043 | continue; |
1054 | if (!try_module_get(t->me)) | 1044 | if (!try_module_get(t->me)) { |
1045 | mutex_unlock(&xt[af].mutex); | ||
1055 | return NULL; | 1046 | return NULL; |
1047 | } | ||
1056 | 1048 | ||
1057 | mutex_unlock(&xt[af].mutex); | 1049 | mutex_unlock(&xt[af].mutex); |
1058 | if (t->table_init(net) != 0) { | 1050 | if (t->table_init(net) != 0) { |
@@ -1114,7 +1106,7 @@ static int xt_jumpstack_alloc(struct xt_table_info *i) | |||
1114 | 1106 | ||
1115 | size = sizeof(void **) * nr_cpu_ids; | 1107 | size = sizeof(void **) * nr_cpu_ids; |
1116 | if (size > PAGE_SIZE) | 1108 | if (size > PAGE_SIZE) |
1117 | i->jumpstack = vzalloc(size); | 1109 | i->jumpstack = kvzalloc(size, GFP_KERNEL); |
1118 | else | 1110 | else |
1119 | i->jumpstack = kzalloc(size, GFP_KERNEL); | 1111 | i->jumpstack = kzalloc(size, GFP_KERNEL); |
1120 | if (i->jumpstack == NULL) | 1112 | if (i->jumpstack == NULL) |
@@ -1136,12 +1128,8 @@ static int xt_jumpstack_alloc(struct xt_table_info *i) | |||
1136 | */ | 1128 | */ |
1137 | size = sizeof(void *) * i->stacksize * 2u; | 1129 | size = sizeof(void *) * i->stacksize * 2u; |
1138 | for_each_possible_cpu(cpu) { | 1130 | for_each_possible_cpu(cpu) { |
1139 | if (size > PAGE_SIZE) | 1131 | i->jumpstack[cpu] = kvmalloc_node(size, GFP_KERNEL, |
1140 | i->jumpstack[cpu] = vmalloc_node(size, | 1132 | cpu_to_node(cpu)); |
1141 | cpu_to_node(cpu)); | ||
1142 | else | ||
1143 | i->jumpstack[cpu] = kmalloc_node(size, | ||
1144 | GFP_KERNEL, cpu_to_node(cpu)); | ||
1145 | if (i->jumpstack[cpu] == NULL) | 1133 | if (i->jumpstack[cpu] == NULL) |
1146 | /* | 1134 | /* |
1147 | * Freeing will be done later on by the callers. The | 1135 | * Freeing will be done later on by the callers. The |
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c index 19247a17e511..c502419d6306 100644 --- a/net/netfilter/xt_AUDIT.c +++ b/net/netfilter/xt_AUDIT.c | |||
@@ -31,146 +31,76 @@ MODULE_ALIAS("ip6t_AUDIT"); | |||
31 | MODULE_ALIAS("ebt_AUDIT"); | 31 | MODULE_ALIAS("ebt_AUDIT"); |
32 | MODULE_ALIAS("arpt_AUDIT"); | 32 | MODULE_ALIAS("arpt_AUDIT"); |
33 | 33 | ||
34 | static void audit_proto(struct audit_buffer *ab, struct sk_buff *skb, | 34 | static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb) |
35 | unsigned int proto, unsigned int offset) | ||
36 | { | ||
37 | switch (proto) { | ||
38 | case IPPROTO_TCP: | ||
39 | case IPPROTO_UDP: | ||
40 | case IPPROTO_UDPLITE: { | ||
41 | const __be16 *pptr; | ||
42 | __be16 _ports[2]; | ||
43 | |||
44 | pptr = skb_header_pointer(skb, offset, sizeof(_ports), _ports); | ||
45 | if (pptr == NULL) { | ||
46 | audit_log_format(ab, " truncated=1"); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | audit_log_format(ab, " sport=%hu dport=%hu", | ||
51 | ntohs(pptr[0]), ntohs(pptr[1])); | ||
52 | } | ||
53 | break; | ||
54 | |||
55 | case IPPROTO_ICMP: | ||
56 | case IPPROTO_ICMPV6: { | ||
57 | const u8 *iptr; | ||
58 | u8 _ih[2]; | ||
59 | |||
60 | iptr = skb_header_pointer(skb, offset, sizeof(_ih), &_ih); | ||
61 | if (iptr == NULL) { | ||
62 | audit_log_format(ab, " truncated=1"); | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | audit_log_format(ab, " icmptype=%hhu icmpcode=%hhu", | ||
67 | iptr[0], iptr[1]); | ||
68 | |||
69 | } | ||
70 | break; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static void audit_ip4(struct audit_buffer *ab, struct sk_buff *skb) | ||
75 | { | 35 | { |
76 | struct iphdr _iph; | 36 | struct iphdr _iph; |
77 | const struct iphdr *ih; | 37 | const struct iphdr *ih; |
78 | 38 | ||
79 | ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); | 39 | ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph); |
80 | if (!ih) { | 40 | if (!ih) |
81 | audit_log_format(ab, " truncated=1"); | 41 | return false; |
82 | return; | ||
83 | } | ||
84 | 42 | ||
85 | audit_log_format(ab, " saddr=%pI4 daddr=%pI4 ipid=%hu proto=%hhu", | 43 | audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu", |
86 | &ih->saddr, &ih->daddr, ntohs(ih->id), ih->protocol); | 44 | &ih->saddr, &ih->daddr, ih->protocol); |
87 | 45 | ||
88 | if (ntohs(ih->frag_off) & IP_OFFSET) { | 46 | return true; |
89 | audit_log_format(ab, " frag=1"); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | audit_proto(ab, skb, ih->protocol, ih->ihl * 4); | ||
94 | } | 47 | } |
95 | 48 | ||
96 | static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) | 49 | static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) |
97 | { | 50 | { |
98 | struct ipv6hdr _ip6h; | 51 | struct ipv6hdr _ip6h; |
99 | const struct ipv6hdr *ih; | 52 | const struct ipv6hdr *ih; |
100 | u8 nexthdr; | 53 | u8 nexthdr; |
101 | __be16 frag_off; | 54 | __be16 frag_off; |
102 | int offset; | ||
103 | 55 | ||
104 | ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); | 56 | ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); |
105 | if (!ih) { | 57 | if (!ih) |
106 | audit_log_format(ab, " truncated=1"); | 58 | return false; |
107 | return; | ||
108 | } | ||
109 | 59 | ||
110 | nexthdr = ih->nexthdr; | 60 | nexthdr = ih->nexthdr; |
111 | offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), | 61 | ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off); |
112 | &nexthdr, &frag_off); | ||
113 | 62 | ||
114 | audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", | 63 | audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", |
115 | &ih->saddr, &ih->daddr, nexthdr); | 64 | &ih->saddr, &ih->daddr, nexthdr); |
116 | 65 | ||
117 | if (offset) | 66 | return true; |
118 | audit_proto(ab, skb, nexthdr, offset); | ||
119 | } | 67 | } |
120 | 68 | ||
121 | static unsigned int | 69 | static unsigned int |
122 | audit_tg(struct sk_buff *skb, const struct xt_action_param *par) | 70 | audit_tg(struct sk_buff *skb, const struct xt_action_param *par) |
123 | { | 71 | { |
124 | const struct xt_audit_info *info = par->targinfo; | ||
125 | struct audit_buffer *ab; | 72 | struct audit_buffer *ab; |
73 | int fam = -1; | ||
126 | 74 | ||
127 | if (audit_enabled == 0) | 75 | if (audit_enabled == 0) |
128 | goto errout; | 76 | goto errout; |
129 | |||
130 | ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); | 77 | ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); |
131 | if (ab == NULL) | 78 | if (ab == NULL) |
132 | goto errout; | 79 | goto errout; |
133 | 80 | ||
134 | audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s", | 81 | audit_log_format(ab, "mark=%#x", skb->mark); |
135 | info->type, xt_hooknum(par), skb->len, | ||
136 | xt_in(par) ? xt_inname(par) : "?", | ||
137 | xt_out(par) ? xt_outname(par) : "?"); | ||
138 | |||
139 | if (skb->mark) | ||
140 | audit_log_format(ab, " mark=%#x", skb->mark); | ||
141 | |||
142 | if (skb->dev && skb->dev->type == ARPHRD_ETHER) { | ||
143 | audit_log_format(ab, " smac=%pM dmac=%pM macproto=0x%04x", | ||
144 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
145 | ntohs(eth_hdr(skb)->h_proto)); | ||
146 | |||
147 | if (xt_family(par) == NFPROTO_BRIDGE) { | ||
148 | switch (eth_hdr(skb)->h_proto) { | ||
149 | case htons(ETH_P_IP): | ||
150 | audit_ip4(ab, skb); | ||
151 | break; | ||
152 | |||
153 | case htons(ETH_P_IPV6): | ||
154 | audit_ip6(ab, skb); | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | 82 | ||
160 | switch (xt_family(par)) { | 83 | switch (xt_family(par)) { |
84 | case NFPROTO_BRIDGE: | ||
85 | switch (eth_hdr(skb)->h_proto) { | ||
86 | case htons(ETH_P_IP): | ||
87 | fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; | ||
88 | break; | ||
89 | case htons(ETH_P_IPV6): | ||
90 | fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; | ||
91 | break; | ||
92 | } | ||
93 | break; | ||
161 | case NFPROTO_IPV4: | 94 | case NFPROTO_IPV4: |
162 | audit_ip4(ab, skb); | 95 | fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; |
163 | break; | 96 | break; |
164 | |||
165 | case NFPROTO_IPV6: | 97 | case NFPROTO_IPV6: |
166 | audit_ip6(ab, skb); | 98 | fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; |
167 | break; | 99 | break; |
168 | } | 100 | } |
169 | 101 | ||
170 | #ifdef CONFIG_NETWORK_SECMARK | 102 | if (fam == -1) |
171 | if (skb->secmark) | 103 | audit_log_format(ab, " saddr=? daddr=? proto=-1"); |
172 | audit_log_secctx(ab, skb->secmark); | ||
173 | #endif | ||
174 | 104 | ||
175 | audit_log_end(ab); | 105 | audit_log_end(ab); |
176 | 106 | ||
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 3cbe1bcf6a74..bb7ad82dcd56 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -168,8 +168,10 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
168 | goto err_put_timeout; | 168 | goto err_put_timeout; |
169 | } | 169 | } |
170 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); | 170 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); |
171 | if (timeout_ext == NULL) | 171 | if (!timeout_ext) { |
172 | ret = -ENOMEM; | 172 | ret = -ENOMEM; |
173 | goto err_put_timeout; | ||
174 | } | ||
173 | 175 | ||
174 | rcu_read_unlock(); | 176 | rcu_read_unlock(); |
175 | return ret; | 177 | return ret; |
@@ -201,6 +203,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, | |||
201 | struct xt_ct_target_info_v1 *info) | 203 | struct xt_ct_target_info_v1 *info) |
202 | { | 204 | { |
203 | struct nf_conntrack_zone zone; | 205 | struct nf_conntrack_zone zone; |
206 | struct nf_conn_help *help; | ||
204 | struct nf_conn *ct; | 207 | struct nf_conn *ct; |
205 | int ret = -EOPNOTSUPP; | 208 | int ret = -EOPNOTSUPP; |
206 | 209 | ||
@@ -249,7 +252,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, | |||
249 | if (info->timeout[0]) { | 252 | if (info->timeout[0]) { |
250 | ret = xt_ct_set_timeout(ct, par, info->timeout); | 253 | ret = xt_ct_set_timeout(ct, par, info->timeout); |
251 | if (ret < 0) | 254 | if (ret < 0) |
252 | goto err3; | 255 | goto err4; |
253 | } | 256 | } |
254 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | 257 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); |
255 | nf_conntrack_get(&ct->ct_general); | 258 | nf_conntrack_get(&ct->ct_general); |
@@ -257,6 +260,10 @@ out: | |||
257 | info->ct = ct; | 260 | info->ct = ct; |
258 | return 0; | 261 | return 0; |
259 | 262 | ||
263 | err4: | ||
264 | help = nfct_help(ct); | ||
265 | if (help) | ||
266 | module_put(help->helper->me); | ||
260 | err3: | 267 | err3: |
261 | nf_ct_tmpl_free(ct); | 268 | nf_ct_tmpl_free(ct); |
262 | err2: | 269 | err2: |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 37d581a31cff..3f6c4fa78bdb 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -388,10 +388,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
388 | } | 388 | } |
389 | 389 | ||
390 | sz = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size; | 390 | sz = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size; |
391 | if (sz <= PAGE_SIZE) | 391 | t = kvzalloc(sz, GFP_KERNEL); |
392 | t = kzalloc(sz, GFP_KERNEL); | ||
393 | else | ||
394 | t = vzalloc(sz); | ||
395 | if (t == NULL) { | 392 | if (t == NULL) { |
396 | ret = -ENOMEM; | 393 | ret = -ENOMEM; |
397 | goto out; | 394 | goto out; |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 770bbec878f1..e75ef39669c5 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -152,7 +152,7 @@ static int socket_mt_enable_defrag(struct net *net, int family) | |||
152 | switch (family) { | 152 | switch (family) { |
153 | case NFPROTO_IPV4: | 153 | case NFPROTO_IPV4: |
154 | return nf_defrag_ipv4_enable(net); | 154 | return nf_defrag_ipv4_enable(net); |
155 | #ifdef XT_SOCKET_HAVE_IPV6 | 155 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
156 | case NFPROTO_IPV6: | 156 | case NFPROTO_IPV6: |
157 | return nf_defrag_ipv6_enable(net); | 157 | return nf_defrag_ipv6_enable(net); |
158 | #endif | 158 | #endif |
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 42a95919df09..bf602e33c40a 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c | |||
@@ -516,10 +516,38 @@ ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone, | |||
516 | u16 proto, const struct sk_buff *skb) | 516 | u16 proto, const struct sk_buff *skb) |
517 | { | 517 | { |
518 | struct nf_conntrack_tuple tuple; | 518 | struct nf_conntrack_tuple tuple; |
519 | struct nf_conntrack_expect *exp; | ||
519 | 520 | ||
520 | if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple)) | 521 | if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple)) |
521 | return NULL; | 522 | return NULL; |
522 | return __nf_ct_expect_find(net, zone, &tuple); | 523 | |
524 | exp = __nf_ct_expect_find(net, zone, &tuple); | ||
525 | if (exp) { | ||
526 | struct nf_conntrack_tuple_hash *h; | ||
527 | |||
528 | /* Delete existing conntrack entry, if it clashes with the | ||
529 | * expectation. This can happen since conntrack ALGs do not | ||
530 | * check for clashes between (new) expectations and existing | ||
531 | * conntrack entries. nf_conntrack_in() will check the | ||
532 | * expectations only if a conntrack entry can not be found, | ||
533 | * which can lead to OVS finding the expectation (here) in the | ||
534 | * init direction, but which will not be removed by the | ||
535 | * nf_conntrack_in() call, if a matching conntrack entry is | ||
536 | * found instead. In this case all init direction packets | ||
537 | * would be reported as new related packets, while reply | ||
538 | * direction packets would be reported as un-related | ||
539 | * established packets. | ||
540 | */ | ||
541 | h = nf_conntrack_find_get(net, zone, &tuple); | ||
542 | if (h) { | ||
543 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | ||
544 | |||
545 | nf_ct_delete(ct, 0, 0); | ||
546 | nf_conntrack_put(&ct->ct_general); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | return exp; | ||
523 | } | 551 | } |
524 | 552 | ||
525 | /* This replicates logic from nf_conntrack_core.c that is not exported. */ | 553 | /* This replicates logic from nf_conntrack_core.c that is not exported. */ |
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c index 2efb36c08f2a..dee469fed967 100644 --- a/net/sched/cls_matchall.c +++ b/net/sched/cls_matchall.c | |||
@@ -203,8 +203,7 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, | |||
203 | 203 | ||
204 | *arg = (unsigned long) head; | 204 | *arg = (unsigned long) head; |
205 | rcu_assign_pointer(tp->root, new); | 205 | rcu_assign_pointer(tp->root, new); |
206 | if (head) | 206 | call_rcu(&head->rcu, mall_destroy_rcu); |
207 | call_rcu(&head->rcu, mall_destroy_rcu); | ||
208 | return 0; | 207 | return 0; |
209 | 208 | ||
210 | err_replace_hw_filter: | 209 | err_replace_hw_filter: |
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index d00f4c7c2f3a..b30a2c70bd48 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c | |||
@@ -376,10 +376,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) | |||
376 | if (mask != q->tab_mask) { | 376 | if (mask != q->tab_mask) { |
377 | struct sk_buff **ntab; | 377 | struct sk_buff **ntab; |
378 | 378 | ||
379 | ntab = kcalloc(mask + 1, sizeof(struct sk_buff *), | 379 | ntab = kvmalloc_array((mask + 1), sizeof(struct sk_buff *), GFP_KERNEL | __GFP_ZERO); |
380 | GFP_KERNEL | __GFP_NOWARN); | ||
381 | if (!ntab) | ||
382 | ntab = vzalloc((mask + 1) * sizeof(struct sk_buff *)); | ||
383 | if (!ntab) | 380 | if (!ntab) |
384 | return -ENOMEM; | 381 | return -ENOMEM; |
385 | 382 | ||
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index da4f67bda0ee..b488721a0059 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
@@ -624,16 +624,6 @@ static void fq_rehash(struct fq_sched_data *q, | |||
624 | q->stat_gc_flows += fcnt; | 624 | q->stat_gc_flows += fcnt; |
625 | } | 625 | } |
626 | 626 | ||
627 | static void *fq_alloc_node(size_t sz, int node) | ||
628 | { | ||
629 | void *ptr; | ||
630 | |||
631 | ptr = kmalloc_node(sz, GFP_KERNEL | __GFP_REPEAT | __GFP_NOWARN, node); | ||
632 | if (!ptr) | ||
633 | ptr = vmalloc_node(sz, node); | ||
634 | return ptr; | ||
635 | } | ||
636 | |||
637 | static void fq_free(void *addr) | 627 | static void fq_free(void *addr) |
638 | { | 628 | { |
639 | kvfree(addr); | 629 | kvfree(addr); |
@@ -650,7 +640,7 @@ static int fq_resize(struct Qdisc *sch, u32 log) | |||
650 | return 0; | 640 | return 0; |
651 | 641 | ||
652 | /* If XPS was setup, we can allocate memory on right NUMA node */ | 642 | /* If XPS was setup, we can allocate memory on right NUMA node */ |
653 | array = fq_alloc_node(sizeof(struct rb_root) << log, | 643 | array = kvmalloc_node(sizeof(struct rb_root) << log, GFP_KERNEL | __GFP_REPEAT, |
654 | netdev_queue_numa_node_read(sch->dev_queue)); | 644 | netdev_queue_numa_node_read(sch->dev_queue)); |
655 | if (!array) | 645 | if (!array) |
656 | return -ENOMEM; | 646 | return -ENOMEM; |
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 18bbb5476c83..9201abce928c 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
@@ -446,27 +446,13 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt) | |||
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | static void *fq_codel_zalloc(size_t sz) | ||
450 | { | ||
451 | void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN); | ||
452 | |||
453 | if (!ptr) | ||
454 | ptr = vzalloc(sz); | ||
455 | return ptr; | ||
456 | } | ||
457 | |||
458 | static void fq_codel_free(void *addr) | ||
459 | { | ||
460 | kvfree(addr); | ||
461 | } | ||
462 | |||
463 | static void fq_codel_destroy(struct Qdisc *sch) | 449 | static void fq_codel_destroy(struct Qdisc *sch) |
464 | { | 450 | { |
465 | struct fq_codel_sched_data *q = qdisc_priv(sch); | 451 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
466 | 452 | ||
467 | tcf_destroy_chain(&q->filter_list); | 453 | tcf_destroy_chain(&q->filter_list); |
468 | fq_codel_free(q->backlogs); | 454 | kvfree(q->backlogs); |
469 | fq_codel_free(q->flows); | 455 | kvfree(q->flows); |
470 | } | 456 | } |
471 | 457 | ||
472 | static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) | 458 | static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) |
@@ -493,13 +479,13 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) | |||
493 | } | 479 | } |
494 | 480 | ||
495 | if (!q->flows) { | 481 | if (!q->flows) { |
496 | q->flows = fq_codel_zalloc(q->flows_cnt * | 482 | q->flows = kvzalloc(q->flows_cnt * |
497 | sizeof(struct fq_codel_flow)); | 483 | sizeof(struct fq_codel_flow), GFP_KERNEL); |
498 | if (!q->flows) | 484 | if (!q->flows) |
499 | return -ENOMEM; | 485 | return -ENOMEM; |
500 | q->backlogs = fq_codel_zalloc(q->flows_cnt * sizeof(u32)); | 486 | q->backlogs = kvzalloc(q->flows_cnt * sizeof(u32), GFP_KERNEL); |
501 | if (!q->backlogs) { | 487 | if (!q->backlogs) { |
502 | fq_codel_free(q->flows); | 488 | kvfree(q->flows); |
503 | return -ENOMEM; | 489 | return -ENOMEM; |
504 | } | 490 | } |
505 | for (i = 0; i < q->flows_cnt; i++) { | 491 | for (i = 0; i < q->flows_cnt; i++) { |
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index c19d346e6c5a..51d3ba682af9 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c | |||
@@ -467,29 +467,14 @@ static void hhf_reset(struct Qdisc *sch) | |||
467 | rtnl_kfree_skbs(skb, skb); | 467 | rtnl_kfree_skbs(skb, skb); |
468 | } | 468 | } |
469 | 469 | ||
470 | static void *hhf_zalloc(size_t sz) | ||
471 | { | ||
472 | void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN); | ||
473 | |||
474 | if (!ptr) | ||
475 | ptr = vzalloc(sz); | ||
476 | |||
477 | return ptr; | ||
478 | } | ||
479 | |||
480 | static void hhf_free(void *addr) | ||
481 | { | ||
482 | kvfree(addr); | ||
483 | } | ||
484 | |||
485 | static void hhf_destroy(struct Qdisc *sch) | 470 | static void hhf_destroy(struct Qdisc *sch) |
486 | { | 471 | { |
487 | int i; | 472 | int i; |
488 | struct hhf_sched_data *q = qdisc_priv(sch); | 473 | struct hhf_sched_data *q = qdisc_priv(sch); |
489 | 474 | ||
490 | for (i = 0; i < HHF_ARRAYS_CNT; i++) { | 475 | for (i = 0; i < HHF_ARRAYS_CNT; i++) { |
491 | hhf_free(q->hhf_arrays[i]); | 476 | kvfree(q->hhf_arrays[i]); |
492 | hhf_free(q->hhf_valid_bits[i]); | 477 | kvfree(q->hhf_valid_bits[i]); |
493 | } | 478 | } |
494 | 479 | ||
495 | for (i = 0; i < HH_FLOWS_CNT; i++) { | 480 | for (i = 0; i < HH_FLOWS_CNT; i++) { |
@@ -503,7 +488,7 @@ static void hhf_destroy(struct Qdisc *sch) | |||
503 | kfree(flow); | 488 | kfree(flow); |
504 | } | 489 | } |
505 | } | 490 | } |
506 | hhf_free(q->hh_flows); | 491 | kvfree(q->hh_flows); |
507 | } | 492 | } |
508 | 493 | ||
509 | static const struct nla_policy hhf_policy[TCA_HHF_MAX + 1] = { | 494 | static const struct nla_policy hhf_policy[TCA_HHF_MAX + 1] = { |
@@ -609,8 +594,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) | |||
609 | 594 | ||
610 | if (!q->hh_flows) { | 595 | if (!q->hh_flows) { |
611 | /* Initialize heavy-hitter flow table. */ | 596 | /* Initialize heavy-hitter flow table. */ |
612 | q->hh_flows = hhf_zalloc(HH_FLOWS_CNT * | 597 | q->hh_flows = kvzalloc(HH_FLOWS_CNT * |
613 | sizeof(struct list_head)); | 598 | sizeof(struct list_head), GFP_KERNEL); |
614 | if (!q->hh_flows) | 599 | if (!q->hh_flows) |
615 | return -ENOMEM; | 600 | return -ENOMEM; |
616 | for (i = 0; i < HH_FLOWS_CNT; i++) | 601 | for (i = 0; i < HH_FLOWS_CNT; i++) |
@@ -624,8 +609,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) | |||
624 | 609 | ||
625 | /* Initialize heavy-hitter filter arrays. */ | 610 | /* Initialize heavy-hitter filter arrays. */ |
626 | for (i = 0; i < HHF_ARRAYS_CNT; i++) { | 611 | for (i = 0; i < HHF_ARRAYS_CNT; i++) { |
627 | q->hhf_arrays[i] = hhf_zalloc(HHF_ARRAYS_LEN * | 612 | q->hhf_arrays[i] = kvzalloc(HHF_ARRAYS_LEN * |
628 | sizeof(u32)); | 613 | sizeof(u32), GFP_KERNEL); |
629 | if (!q->hhf_arrays[i]) { | 614 | if (!q->hhf_arrays[i]) { |
630 | /* Note: hhf_destroy() will be called | 615 | /* Note: hhf_destroy() will be called |
631 | * by our caller. | 616 | * by our caller. |
@@ -637,8 +622,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) | |||
637 | 622 | ||
638 | /* Initialize valid bits of heavy-hitter filter arrays. */ | 623 | /* Initialize valid bits of heavy-hitter filter arrays. */ |
639 | for (i = 0; i < HHF_ARRAYS_CNT; i++) { | 624 | for (i = 0; i < HHF_ARRAYS_CNT; i++) { |
640 | q->hhf_valid_bits[i] = hhf_zalloc(HHF_ARRAYS_LEN / | 625 | q->hhf_valid_bits[i] = kvzalloc(HHF_ARRAYS_LEN / |
641 | BITS_PER_BYTE); | 626 | BITS_PER_BYTE, GFP_KERNEL); |
642 | if (!q->hhf_valid_bits[i]) { | 627 | if (!q->hhf_valid_bits[i]) { |
643 | /* Note: hhf_destroy() will be called | 628 | /* Note: hhf_destroy() will be called |
644 | * by our caller. | 629 | * by our caller. |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index f0ce4780f395..1b3dd6190e93 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -702,15 +702,11 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) | |||
702 | spinlock_t *root_lock; | 702 | spinlock_t *root_lock; |
703 | struct disttable *d; | 703 | struct disttable *d; |
704 | int i; | 704 | int i; |
705 | size_t s; | ||
706 | 705 | ||
707 | if (n > NETEM_DIST_MAX) | 706 | if (n > NETEM_DIST_MAX) |
708 | return -EINVAL; | 707 | return -EINVAL; |
709 | 708 | ||
710 | s = sizeof(struct disttable) + n * sizeof(s16); | 709 | d = kvmalloc(sizeof(struct disttable) + n * sizeof(s16), GFP_KERNEL); |
711 | d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN); | ||
712 | if (!d) | ||
713 | d = vmalloc(s); | ||
714 | if (!d) | 710 | if (!d) |
715 | return -ENOMEM; | 711 | return -ENOMEM; |
716 | 712 | ||
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index b00e02c139de..332d94be6e1c 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -685,11 +685,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) | |||
685 | 685 | ||
686 | static void *sfq_alloc(size_t sz) | 686 | static void *sfq_alloc(size_t sz) |
687 | { | 687 | { |
688 | void *ptr = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN); | 688 | return kvmalloc(sz, GFP_KERNEL); |
689 | |||
690 | if (!ptr) | ||
691 | ptr = vmalloc(sz); | ||
692 | return ptr; | ||
693 | } | 689 | } |
694 | 690 | ||
695 | static void sfq_free(void *addr) | 691 | static void sfq_free(void *addr) |
diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c index 16b7c801f8b6..cb69ab977cd7 100644 --- a/net/smc/smc_ib.c +++ b/net/smc/smc_ib.c | |||
@@ -80,12 +80,11 @@ static int smc_ib_modify_qp_rtr(struct smc_link *lnk) | |||
80 | memset(&qp_attr, 0, sizeof(qp_attr)); | 80 | memset(&qp_attr, 0, sizeof(qp_attr)); |
81 | qp_attr.qp_state = IB_QPS_RTR; | 81 | qp_attr.qp_state = IB_QPS_RTR; |
82 | qp_attr.path_mtu = min(lnk->path_mtu, lnk->peer_mtu); | 82 | qp_attr.path_mtu = min(lnk->path_mtu, lnk->peer_mtu); |
83 | qp_attr.ah_attr.port_num = lnk->ibport; | 83 | qp_attr.ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE; |
84 | qp_attr.ah_attr.ah_flags = IB_AH_GRH; | 84 | rdma_ah_set_port_num(&qp_attr.ah_attr, lnk->ibport); |
85 | qp_attr.ah_attr.grh.hop_limit = 1; | 85 | rdma_ah_set_grh(&qp_attr.ah_attr, NULL, 0, 0, 1, 0); |
86 | memcpy(&qp_attr.ah_attr.grh.dgid, lnk->peer_gid, | 86 | rdma_ah_set_dgid_raw(&qp_attr.ah_attr, lnk->peer_gid); |
87 | sizeof(lnk->peer_gid)); | 87 | memcpy(&qp_attr.ah_attr.roce.dmac, lnk->peer_mac, |
88 | memcpy(&qp_attr.ah_attr.dmac, lnk->peer_mac, | ||
89 | sizeof(lnk->peer_mac)); | 88 | sizeof(lnk->peer_mac)); |
90 | qp_attr.dest_qp_num = lnk->peer_qpn; | 89 | qp_attr.dest_qp_num = lnk->peer_qpn; |
91 | qp_attr.rq_psn = lnk->peer_psn; /* starting receive packet seq # */ | 90 | qp_attr.rq_psn = lnk->peer_psn; /* starting receive packet seq # */ |
diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 919981324171..9aed6fe1bf1a 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c | |||
@@ -106,7 +106,6 @@ __init int net_sysctl_init(void) | |||
106 | ret = register_pernet_subsys(&sysctl_pernet_ops); | 106 | ret = register_pernet_subsys(&sysctl_pernet_ops); |
107 | if (ret) | 107 | if (ret) |
108 | goto out1; | 108 | goto out1; |
109 | register_sysctl_root(&net_sysctl_root); | ||
110 | out: | 109 | out: |
111 | return ret; | 110 | return ret; |
112 | out1: | 111 | out1: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 570fc95dc507..c3bc9da30cff 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2764,8 +2764,8 @@ static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev, | |||
2764 | nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]); | 2764 | nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]); |
2765 | 2765 | ||
2766 | /* bits 0 and 63 are reserved and must be zero */ | 2766 | /* bits 0 and 63 are reserved and must be zero */ |
2767 | if ((mumimo_groups[0] & BIT(7)) || | 2767 | if ((mumimo_groups[0] & BIT(0)) || |
2768 | (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0))) | 2768 | (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7))) |
2769 | return -EINVAL; | 2769 | return -EINVAL; |
2770 | 2770 | ||
2771 | params->vht_mumimo_groups = mumimo_groups; | 2771 | params->vht_mumimo_groups = mumimo_groups; |