diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 12:25:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 12:25:34 -0400 |
commit | c62b3898636072de4bf9af36b6cd5a920ebfe896 (patch) | |
tree | 5fcccbf7cb2c690f43aa9ee20577fafe0b0bcdac | |
parent | eddecbb601c9ea3fab7e67d7892010fc9426d1e6 (diff) | |
parent | 736561a01f11114146b1b7f82d486fa9c95828ef (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (33 commits)
IPVS: Use global mutex in ip_vs_app.c
ipvs: fix a typo in __ip_vs_control_init()
veth: Fix the byte counters
net ipv6: Fix duplicate /proc/sys/net/ipv6/neigh directory entries.
macvlan: Fix use after free of struct macvlan_port.
net: fix incorrect spelling in drop monitor protocol
can: c_can: Do basic c_can configuration _before_ enabling the interrupts
net/appletalk: fix atalk_release use after free
ipx: fix ipx_release()
snmp: SNMP_UPD_PO_STATS_BH() always called from softirq
l2tp: fix possible oops on l2tp_eth module unload
xfrm: Fix initialize repl field of struct xfrm_state
netfilter: ipt_CLUSTERIP: fix buffer overflow
netfilter: xtables: fix reentrancy
netfilter: ipset: fix checking the type revision at create command
netfilter: ipset: fix address ranges at hash:*port* types
niu: Rename NIU parent platform device name to fix conflict.
r8169: fix a bug in rtl8169_init_phy()
bonding: fix a typo in a comment
ftmac100: use resource_size()
...
42 files changed, 381 insertions, 322 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1a6e9eb7af43..338bea147c64 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -2130,7 +2130,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
2130 | } | 2130 | } |
2131 | 2131 | ||
2132 | /* | 2132 | /* |
2133 | * First release a slave and than destroy the bond if no more slaves are left. | 2133 | * First release a slave and then destroy the bond if no more slaves are left. |
2134 | * Must be under rtnl_lock when this function is called. | 2134 | * Must be under rtnl_lock when this function is called. |
2135 | */ | 2135 | */ |
2136 | static int bond_release_and_destroy(struct net_device *bond_dev, | 2136 | static int bond_release_and_destroy(struct net_device *bond_dev, |
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 14050786218a..110eda01843c 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c | |||
@@ -633,9 +633,6 @@ static void c_can_start(struct net_device *dev) | |||
633 | { | 633 | { |
634 | struct c_can_priv *priv = netdev_priv(dev); | 634 | struct c_can_priv *priv = netdev_priv(dev); |
635 | 635 | ||
636 | /* enable status change, error and module interrupts */ | ||
637 | c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); | ||
638 | |||
639 | /* basic c_can configuration */ | 636 | /* basic c_can configuration */ |
640 | c_can_chip_config(dev); | 637 | c_can_chip_config(dev); |
641 | 638 | ||
@@ -643,6 +640,9 @@ static void c_can_start(struct net_device *dev) | |||
643 | 640 | ||
644 | /* reset tx helper pointers */ | 641 | /* reset tx helper pointers */ |
645 | priv->tx_next = priv->tx_echo = 0; | 642 | priv->tx_next = priv->tx_echo = 0; |
643 | |||
644 | /* enable status change, error and module interrupts */ | ||
645 | c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); | ||
646 | } | 646 | } |
647 | 647 | ||
648 | static void c_can_stop(struct net_device *dev) | 648 | static void c_can_stop(struct net_device *dev) |
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c index 1d6f4b8d393a..a31661948c42 100644 --- a/drivers/net/ftmac100.c +++ b/drivers/net/ftmac100.c | |||
@@ -1102,7 +1102,7 @@ static int ftmac100_probe(struct platform_device *pdev) | |||
1102 | goto err_req_mem; | 1102 | goto err_req_mem; |
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | priv->base = ioremap(res->start, res->end - res->start); | 1105 | priv->base = ioremap(res->start, resource_size(res)); |
1106 | if (!priv->base) { | 1106 | if (!priv->base) { |
1107 | dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n"); | 1107 | dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n"); |
1108 | err = -EIO; | 1108 | err = -EIO; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ccb231c4d933..2a0ad9a501bb 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -949,6 +949,11 @@ static void gfar_detect_errata(struct gfar_private *priv) | |||
949 | (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) | 949 | (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) |
950 | priv->errata |= GFAR_ERRATA_A002; | 950 | priv->errata |= GFAR_ERRATA_A002; |
951 | 951 | ||
952 | /* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */ | ||
953 | if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) || | ||
954 | (pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020)) | ||
955 | priv->errata |= GFAR_ERRATA_12; | ||
956 | |||
952 | if (priv->errata) | 957 | if (priv->errata) |
953 | dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", | 958 | dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", |
954 | priv->errata); | 959 | priv->errata); |
@@ -2154,8 +2159,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2154 | /* Set up checksumming */ | 2159 | /* Set up checksumming */ |
2155 | if (CHECKSUM_PARTIAL == skb->ip_summed) { | 2160 | if (CHECKSUM_PARTIAL == skb->ip_summed) { |
2156 | fcb = gfar_add_fcb(skb); | 2161 | fcb = gfar_add_fcb(skb); |
2157 | lstatus |= BD_LFLAG(TXBD_TOE); | 2162 | /* as specified by errata */ |
2158 | gfar_tx_checksum(skb, fcb); | 2163 | if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12) |
2164 | && ((unsigned long)fcb % 0x20) > 0x18)) { | ||
2165 | __skb_pull(skb, GMAC_FCB_LEN); | ||
2166 | skb_checksum_help(skb); | ||
2167 | } else { | ||
2168 | lstatus |= BD_LFLAG(TXBD_TOE); | ||
2169 | gfar_tx_checksum(skb, fcb); | ||
2170 | } | ||
2159 | } | 2171 | } |
2160 | 2172 | ||
2161 | if (vlan_tx_tag_present(skb)) { | 2173 | if (vlan_tx_tag_present(skb)) { |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 54de4135e932..ec5d595ce2e2 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -1039,6 +1039,7 @@ enum gfar_errata { | |||
1039 | GFAR_ERRATA_74 = 0x01, | 1039 | GFAR_ERRATA_74 = 0x01, |
1040 | GFAR_ERRATA_76 = 0x02, | 1040 | GFAR_ERRATA_76 = 0x02, |
1041 | GFAR_ERRATA_A002 = 0x04, | 1041 | GFAR_ERRATA_A002 = 0x04, |
1042 | GFAR_ERRATA_12 = 0x08, /* a.k.a errata eTSEC49 */ | ||
1042 | }; | 1043 | }; |
1043 | 1044 | ||
1044 | /* Struct stolen almost completely (and shamelessly) from the FCC enet source | 1045 | /* Struct stolen almost completely (and shamelessly) from the FCC enet source |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 5b37d3c191e4..78e34e9e4f00 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -39,8 +39,11 @@ struct macvlan_port { | |||
39 | struct list_head vlans; | 39 | struct list_head vlans; |
40 | struct rcu_head rcu; | 40 | struct rcu_head rcu; |
41 | bool passthru; | 41 | bool passthru; |
42 | int count; | ||
42 | }; | 43 | }; |
43 | 44 | ||
45 | static void macvlan_port_destroy(struct net_device *dev); | ||
46 | |||
44 | #define macvlan_port_get_rcu(dev) \ | 47 | #define macvlan_port_get_rcu(dev) \ |
45 | ((struct macvlan_port *) rcu_dereference(dev->rx_handler_data)) | 48 | ((struct macvlan_port *) rcu_dereference(dev->rx_handler_data)) |
46 | #define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data) | 49 | #define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data) |
@@ -457,8 +460,13 @@ static int macvlan_init(struct net_device *dev) | |||
457 | static void macvlan_uninit(struct net_device *dev) | 460 | static void macvlan_uninit(struct net_device *dev) |
458 | { | 461 | { |
459 | struct macvlan_dev *vlan = netdev_priv(dev); | 462 | struct macvlan_dev *vlan = netdev_priv(dev); |
463 | struct macvlan_port *port = vlan->port; | ||
460 | 464 | ||
461 | free_percpu(vlan->pcpu_stats); | 465 | free_percpu(vlan->pcpu_stats); |
466 | |||
467 | port->count -= 1; | ||
468 | if (!port->count) | ||
469 | macvlan_port_destroy(port->dev); | ||
462 | } | 470 | } |
463 | 471 | ||
464 | static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, | 472 | static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, |
@@ -691,12 +699,13 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
691 | vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); | 699 | vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); |
692 | 700 | ||
693 | if (vlan->mode == MACVLAN_MODE_PASSTHRU) { | 701 | if (vlan->mode == MACVLAN_MODE_PASSTHRU) { |
694 | if (!list_empty(&port->vlans)) | 702 | if (port->count) |
695 | return -EINVAL; | 703 | return -EINVAL; |
696 | port->passthru = true; | 704 | port->passthru = true; |
697 | memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN); | 705 | memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN); |
698 | } | 706 | } |
699 | 707 | ||
708 | port->count += 1; | ||
700 | err = register_netdevice(dev); | 709 | err = register_netdevice(dev); |
701 | if (err < 0) | 710 | if (err < 0) |
702 | goto destroy_port; | 711 | goto destroy_port; |
@@ -707,7 +716,8 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
707 | return 0; | 716 | return 0; |
708 | 717 | ||
709 | destroy_port: | 718 | destroy_port: |
710 | if (list_empty(&port->vlans)) | 719 | port->count -= 1; |
720 | if (!port->count) | ||
711 | macvlan_port_destroy(lowerdev); | 721 | macvlan_port_destroy(lowerdev); |
712 | 722 | ||
713 | return err; | 723 | return err; |
@@ -725,13 +735,9 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev, | |||
725 | void macvlan_dellink(struct net_device *dev, struct list_head *head) | 735 | void macvlan_dellink(struct net_device *dev, struct list_head *head) |
726 | { | 736 | { |
727 | struct macvlan_dev *vlan = netdev_priv(dev); | 737 | struct macvlan_dev *vlan = netdev_priv(dev); |
728 | struct macvlan_port *port = vlan->port; | ||
729 | 738 | ||
730 | list_del(&vlan->list); | 739 | list_del(&vlan->list); |
731 | unregister_netdevice_queue(dev, head); | 740 | unregister_netdevice_queue(dev, head); |
732 | |||
733 | if (list_empty(&port->vlans)) | ||
734 | macvlan_port_destroy(port->dev); | ||
735 | } | 741 | } |
736 | EXPORT_SYMBOL_GPL(macvlan_dellink); | 742 | EXPORT_SYMBOL_GPL(macvlan_dellink); |
737 | 743 | ||
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 40fa59e2fd5c..32678b6c6b39 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -9501,7 +9501,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np, | |||
9501 | struct niu_parent *p; | 9501 | struct niu_parent *p; |
9502 | int i; | 9502 | int i; |
9503 | 9503 | ||
9504 | plat_dev = platform_device_register_simple("niu", niu_parent_index, | 9504 | plat_dev = platform_device_register_simple("niu-board", niu_parent_index, |
9505 | NULL, 0); | 9505 | NULL, 0); |
9506 | if (IS_ERR(plat_dev)) | 9506 | if (IS_ERR(plat_dev)) |
9507 | return NULL; | 9507 | return NULL; |
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 105d7f0630cc..2de9b90c5f8f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
@@ -171,7 +171,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
171 | if (skb->ip_summed == CHECKSUM_NONE) | 171 | if (skb->ip_summed == CHECKSUM_NONE) |
172 | skb->ip_summed = rcv_priv->ip_summed; | 172 | skb->ip_summed = rcv_priv->ip_summed; |
173 | 173 | ||
174 | length = skb->len + ETH_HLEN; | 174 | length = skb->len; |
175 | if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS) | 175 | if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS) |
176 | goto rx_drop; | 176 | goto rx_drop; |
177 | 177 | ||
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f616cefc95ba..2f7c76a85e53 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -60,6 +60,7 @@ static int move_iovec_hdr(struct iovec *from, struct iovec *to, | |||
60 | { | 60 | { |
61 | int seg = 0; | 61 | int seg = 0; |
62 | size_t size; | 62 | size_t size; |
63 | |||
63 | while (len && seg < iov_count) { | 64 | while (len && seg < iov_count) { |
64 | size = min(from->iov_len, len); | 65 | size = min(from->iov_len, len); |
65 | to->iov_base = from->iov_base; | 66 | to->iov_base = from->iov_base; |
@@ -79,6 +80,7 @@ static void copy_iovec_hdr(const struct iovec *from, struct iovec *to, | |||
79 | { | 80 | { |
80 | int seg = 0; | 81 | int seg = 0; |
81 | size_t size; | 82 | size_t size; |
83 | |||
82 | while (len && seg < iovcount) { | 84 | while (len && seg < iovcount) { |
83 | size = min(from->iov_len, len); | 85 | size = min(from->iov_len, len); |
84 | to->iov_base = from->iov_base; | 86 | to->iov_base = from->iov_base; |
@@ -211,12 +213,13 @@ static int peek_head_len(struct sock *sk) | |||
211 | { | 213 | { |
212 | struct sk_buff *head; | 214 | struct sk_buff *head; |
213 | int len = 0; | 215 | int len = 0; |
216 | unsigned long flags; | ||
214 | 217 | ||
215 | lock_sock(sk); | 218 | spin_lock_irqsave(&sk->sk_receive_queue.lock, flags); |
216 | head = skb_peek(&sk->sk_receive_queue); | 219 | head = skb_peek(&sk->sk_receive_queue); |
217 | if (head) | 220 | if (likely(head)) |
218 | len = head->len; | 221 | len = head->len; |
219 | release_sock(sk); | 222 | spin_unlock_irqrestore(&sk->sk_receive_queue.lock, flags); |
220 | return len; | 223 | return len; |
221 | } | 224 | } |
222 | 225 | ||
@@ -227,6 +230,7 @@ static int peek_head_len(struct sock *sk) | |||
227 | * @iovcount - returned count of io vectors we fill | 230 | * @iovcount - returned count of io vectors we fill |
228 | * @log - vhost log | 231 | * @log - vhost log |
229 | * @log_num - log offset | 232 | * @log_num - log offset |
233 | * @quota - headcount quota, 1 for big buffer | ||
230 | * returns number of buffer heads allocated, negative on error | 234 | * returns number of buffer heads allocated, negative on error |
231 | */ | 235 | */ |
232 | static int get_rx_bufs(struct vhost_virtqueue *vq, | 236 | static int get_rx_bufs(struct vhost_virtqueue *vq, |
@@ -234,7 +238,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, | |||
234 | int datalen, | 238 | int datalen, |
235 | unsigned *iovcount, | 239 | unsigned *iovcount, |
236 | struct vhost_log *log, | 240 | struct vhost_log *log, |
237 | unsigned *log_num) | 241 | unsigned *log_num, |
242 | unsigned int quota) | ||
238 | { | 243 | { |
239 | unsigned int out, in; | 244 | unsigned int out, in; |
240 | int seg = 0; | 245 | int seg = 0; |
@@ -242,7 +247,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, | |||
242 | unsigned d; | 247 | unsigned d; |
243 | int r, nlogs = 0; | 248 | int r, nlogs = 0; |
244 | 249 | ||
245 | while (datalen > 0) { | 250 | while (datalen > 0 && headcount < quota) { |
246 | if (unlikely(seg >= UIO_MAXIOV)) { | 251 | if (unlikely(seg >= UIO_MAXIOV)) { |
247 | r = -ENOBUFS; | 252 | r = -ENOBUFS; |
248 | goto err; | 253 | goto err; |
@@ -282,117 +287,7 @@ err: | |||
282 | 287 | ||
283 | /* Expects to be always run from workqueue - which acts as | 288 | /* Expects to be always run from workqueue - which acts as |
284 | * read-size critical section for our kind of RCU. */ | 289 | * read-size critical section for our kind of RCU. */ |
285 | static void handle_rx_big(struct vhost_net *net) | 290 | static void handle_rx(struct vhost_net *net) |
286 | { | ||
287 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; | ||
288 | unsigned out, in, log, s; | ||
289 | int head; | ||
290 | struct vhost_log *vq_log; | ||
291 | struct msghdr msg = { | ||
292 | .msg_name = NULL, | ||
293 | .msg_namelen = 0, | ||
294 | .msg_control = NULL, /* FIXME: get and handle RX aux data. */ | ||
295 | .msg_controllen = 0, | ||
296 | .msg_iov = vq->iov, | ||
297 | .msg_flags = MSG_DONTWAIT, | ||
298 | }; | ||
299 | |||
300 | struct virtio_net_hdr hdr = { | ||
301 | .flags = 0, | ||
302 | .gso_type = VIRTIO_NET_HDR_GSO_NONE | ||
303 | }; | ||
304 | |||
305 | size_t len, total_len = 0; | ||
306 | int err; | ||
307 | size_t hdr_size; | ||
308 | /* TODO: check that we are running from vhost_worker? */ | ||
309 | struct socket *sock = rcu_dereference_check(vq->private_data, 1); | ||
310 | if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) | ||
311 | return; | ||
312 | |||
313 | mutex_lock(&vq->mutex); | ||
314 | vhost_disable_notify(vq); | ||
315 | hdr_size = vq->vhost_hlen; | ||
316 | |||
317 | vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ? | ||
318 | vq->log : NULL; | ||
319 | |||
320 | for (;;) { | ||
321 | head = vhost_get_vq_desc(&net->dev, vq, vq->iov, | ||
322 | ARRAY_SIZE(vq->iov), | ||
323 | &out, &in, | ||
324 | vq_log, &log); | ||
325 | /* On error, stop handling until the next kick. */ | ||
326 | if (unlikely(head < 0)) | ||
327 | break; | ||
328 | /* OK, now we need to know about added descriptors. */ | ||
329 | if (head == vq->num) { | ||
330 | if (unlikely(vhost_enable_notify(vq))) { | ||
331 | /* They have slipped one in as we were | ||
332 | * doing that: check again. */ | ||
333 | vhost_disable_notify(vq); | ||
334 | continue; | ||
335 | } | ||
336 | /* Nothing new? Wait for eventfd to tell us | ||
337 | * they refilled. */ | ||
338 | break; | ||
339 | } | ||
340 | /* We don't need to be notified again. */ | ||
341 | if (out) { | ||
342 | vq_err(vq, "Unexpected descriptor format for RX: " | ||
343 | "out %d, int %d\n", | ||
344 | out, in); | ||
345 | break; | ||
346 | } | ||
347 | /* Skip header. TODO: support TSO/mergeable rx buffers. */ | ||
348 | s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in); | ||
349 | msg.msg_iovlen = in; | ||
350 | len = iov_length(vq->iov, in); | ||
351 | /* Sanity check */ | ||
352 | if (!len) { | ||
353 | vq_err(vq, "Unexpected header len for RX: " | ||
354 | "%zd expected %zd\n", | ||
355 | iov_length(vq->hdr, s), hdr_size); | ||
356 | break; | ||
357 | } | ||
358 | err = sock->ops->recvmsg(NULL, sock, &msg, | ||
359 | len, MSG_DONTWAIT | MSG_TRUNC); | ||
360 | /* TODO: Check specific error and bomb out unless EAGAIN? */ | ||
361 | if (err < 0) { | ||
362 | vhost_discard_vq_desc(vq, 1); | ||
363 | break; | ||
364 | } | ||
365 | /* TODO: Should check and handle checksum. */ | ||
366 | if (err > len) { | ||
367 | pr_debug("Discarded truncated rx packet: " | ||
368 | " len %d > %zd\n", err, len); | ||
369 | vhost_discard_vq_desc(vq, 1); | ||
370 | continue; | ||
371 | } | ||
372 | len = err; | ||
373 | err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size); | ||
374 | if (err) { | ||
375 | vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n", | ||
376 | vq->iov->iov_base, err); | ||
377 | break; | ||
378 | } | ||
379 | len += hdr_size; | ||
380 | vhost_add_used_and_signal(&net->dev, vq, head, len); | ||
381 | if (unlikely(vq_log)) | ||
382 | vhost_log_write(vq, vq_log, log, len); | ||
383 | total_len += len; | ||
384 | if (unlikely(total_len >= VHOST_NET_WEIGHT)) { | ||
385 | vhost_poll_queue(&vq->poll); | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | mutex_unlock(&vq->mutex); | ||
391 | } | ||
392 | |||
393 | /* Expects to be always run from workqueue - which acts as | ||
394 | * read-size critical section for our kind of RCU. */ | ||
395 | static void handle_rx_mergeable(struct vhost_net *net) | ||
396 | { | 291 | { |
397 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; | 292 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; |
398 | unsigned uninitialized_var(in), log; | 293 | unsigned uninitialized_var(in), log; |
@@ -405,19 +300,18 @@ static void handle_rx_mergeable(struct vhost_net *net) | |||
405 | .msg_iov = vq->iov, | 300 | .msg_iov = vq->iov, |
406 | .msg_flags = MSG_DONTWAIT, | 301 | .msg_flags = MSG_DONTWAIT, |
407 | }; | 302 | }; |
408 | |||
409 | struct virtio_net_hdr_mrg_rxbuf hdr = { | 303 | struct virtio_net_hdr_mrg_rxbuf hdr = { |
410 | .hdr.flags = 0, | 304 | .hdr.flags = 0, |
411 | .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE | 305 | .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE |
412 | }; | 306 | }; |
413 | |||
414 | size_t total_len = 0; | 307 | size_t total_len = 0; |
415 | int err, headcount; | 308 | int err, headcount, mergeable; |
416 | size_t vhost_hlen, sock_hlen; | 309 | size_t vhost_hlen, sock_hlen; |
417 | size_t vhost_len, sock_len; | 310 | size_t vhost_len, sock_len; |
418 | /* TODO: check that we are running from vhost_worker? */ | 311 | /* TODO: check that we are running from vhost_worker? */ |
419 | struct socket *sock = rcu_dereference_check(vq->private_data, 1); | 312 | struct socket *sock = rcu_dereference_check(vq->private_data, 1); |
420 | if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) | 313 | |
314 | if (!sock) | ||
421 | return; | 315 | return; |
422 | 316 | ||
423 | mutex_lock(&vq->mutex); | 317 | mutex_lock(&vq->mutex); |
@@ -427,12 +321,14 @@ static void handle_rx_mergeable(struct vhost_net *net) | |||
427 | 321 | ||
428 | vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ? | 322 | vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ? |
429 | vq->log : NULL; | 323 | vq->log : NULL; |
324 | mergeable = vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF); | ||
430 | 325 | ||
431 | while ((sock_len = peek_head_len(sock->sk))) { | 326 | while ((sock_len = peek_head_len(sock->sk))) { |
432 | sock_len += sock_hlen; | 327 | sock_len += sock_hlen; |
433 | vhost_len = sock_len + vhost_hlen; | 328 | vhost_len = sock_len + vhost_hlen; |
434 | headcount = get_rx_bufs(vq, vq->heads, vhost_len, | 329 | headcount = get_rx_bufs(vq, vq->heads, vhost_len, |
435 | &in, vq_log, &log); | 330 | &in, vq_log, &log, |
331 | likely(mergeable) ? UIO_MAXIOV : 1); | ||
436 | /* On error, stop handling until the next kick. */ | 332 | /* On error, stop handling until the next kick. */ |
437 | if (unlikely(headcount < 0)) | 333 | if (unlikely(headcount < 0)) |
438 | break; | 334 | break; |
@@ -476,7 +372,7 @@ static void handle_rx_mergeable(struct vhost_net *net) | |||
476 | break; | 372 | break; |
477 | } | 373 | } |
478 | /* TODO: Should check and handle checksum. */ | 374 | /* TODO: Should check and handle checksum. */ |
479 | if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF) && | 375 | if (likely(mergeable) && |
480 | memcpy_toiovecend(vq->hdr, (unsigned char *)&headcount, | 376 | memcpy_toiovecend(vq->hdr, (unsigned char *)&headcount, |
481 | offsetof(typeof(hdr), num_buffers), | 377 | offsetof(typeof(hdr), num_buffers), |
482 | sizeof hdr.num_buffers)) { | 378 | sizeof hdr.num_buffers)) { |
@@ -498,14 +394,6 @@ static void handle_rx_mergeable(struct vhost_net *net) | |||
498 | mutex_unlock(&vq->mutex); | 394 | mutex_unlock(&vq->mutex); |
499 | } | 395 | } |
500 | 396 | ||
501 | static void handle_rx(struct vhost_net *net) | ||
502 | { | ||
503 | if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF)) | ||
504 | handle_rx_mergeable(net); | ||
505 | else | ||
506 | handle_rx_big(net); | ||
507 | } | ||
508 | |||
509 | static void handle_tx_kick(struct vhost_work *work) | 397 | static void handle_tx_kick(struct vhost_work *work) |
510 | { | 398 | { |
511 | struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, | 399 | struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, |
@@ -654,6 +542,7 @@ static struct socket *get_raw_socket(int fd) | |||
654 | } uaddr; | 542 | } uaddr; |
655 | int uaddr_len = sizeof uaddr, r; | 543 | int uaddr_len = sizeof uaddr, r; |
656 | struct socket *sock = sockfd_lookup(fd, &r); | 544 | struct socket *sock = sockfd_lookup(fd, &r); |
545 | |||
657 | if (!sock) | 546 | if (!sock) |
658 | return ERR_PTR(-ENOTSOCK); | 547 | return ERR_PTR(-ENOTSOCK); |
659 | 548 | ||
@@ -682,6 +571,7 @@ static struct socket *get_tap_socket(int fd) | |||
682 | { | 571 | { |
683 | struct file *file = fget(fd); | 572 | struct file *file = fget(fd); |
684 | struct socket *sock; | 573 | struct socket *sock; |
574 | |||
685 | if (!file) | 575 | if (!file) |
686 | return ERR_PTR(-EBADF); | 576 | return ERR_PTR(-EBADF); |
687 | sock = tun_get_socket(file); | 577 | sock = tun_get_socket(file); |
@@ -696,6 +586,7 @@ static struct socket *get_tap_socket(int fd) | |||
696 | static struct socket *get_socket(int fd) | 586 | static struct socket *get_socket(int fd) |
697 | { | 587 | { |
698 | struct socket *sock; | 588 | struct socket *sock; |
589 | |||
699 | /* special case to disable backend */ | 590 | /* special case to disable backend */ |
700 | if (fd == -1) | 591 | if (fd == -1) |
701 | return NULL; | 592 | return NULL; |
@@ -741,9 +632,9 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
741 | oldsock = rcu_dereference_protected(vq->private_data, | 632 | oldsock = rcu_dereference_protected(vq->private_data, |
742 | lockdep_is_held(&vq->mutex)); | 633 | lockdep_is_held(&vq->mutex)); |
743 | if (sock != oldsock) { | 634 | if (sock != oldsock) { |
744 | vhost_net_disable_vq(n, vq); | 635 | vhost_net_disable_vq(n, vq); |
745 | rcu_assign_pointer(vq->private_data, sock); | 636 | rcu_assign_pointer(vq->private_data, sock); |
746 | vhost_net_enable_vq(n, vq); | 637 | vhost_net_enable_vq(n, vq); |
747 | } | 638 | } |
748 | 639 | ||
749 | mutex_unlock(&vq->mutex); | 640 | mutex_unlock(&vq->mutex); |
@@ -768,6 +659,7 @@ static long vhost_net_reset_owner(struct vhost_net *n) | |||
768 | struct socket *tx_sock = NULL; | 659 | struct socket *tx_sock = NULL; |
769 | struct socket *rx_sock = NULL; | 660 | struct socket *rx_sock = NULL; |
770 | long err; | 661 | long err; |
662 | |||
771 | mutex_lock(&n->dev.mutex); | 663 | mutex_lock(&n->dev.mutex); |
772 | err = vhost_dev_check_owner(&n->dev); | 664 | err = vhost_dev_check_owner(&n->dev); |
773 | if (err) | 665 | if (err) |
@@ -829,6 +721,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl, | |||
829 | struct vhost_vring_file backend; | 721 | struct vhost_vring_file backend; |
830 | u64 features; | 722 | u64 features; |
831 | int r; | 723 | int r; |
724 | |||
832 | switch (ioctl) { | 725 | switch (ioctl) { |
833 | case VHOST_NET_SET_BACKEND: | 726 | case VHOST_NET_SET_BACKEND: |
834 | if (copy_from_user(&backend, argp, sizeof backend)) | 727 | if (copy_from_user(&backend, argp, sizeof backend)) |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index ade0568c07a4..2ab291241635 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -41,8 +41,8 @@ static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, | |||
41 | poll_table *pt) | 41 | poll_table *pt) |
42 | { | 42 | { |
43 | struct vhost_poll *poll; | 43 | struct vhost_poll *poll; |
44 | poll = container_of(pt, struct vhost_poll, table); | ||
45 | 44 | ||
45 | poll = container_of(pt, struct vhost_poll, table); | ||
46 | poll->wqh = wqh; | 46 | poll->wqh = wqh; |
47 | add_wait_queue(wqh, &poll->wait); | 47 | add_wait_queue(wqh, &poll->wait); |
48 | } | 48 | } |
@@ -85,6 +85,7 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, | |||
85 | void vhost_poll_start(struct vhost_poll *poll, struct file *file) | 85 | void vhost_poll_start(struct vhost_poll *poll, struct file *file) |
86 | { | 86 | { |
87 | unsigned long mask; | 87 | unsigned long mask; |
88 | |||
88 | mask = file->f_op->poll(file, &poll->table); | 89 | mask = file->f_op->poll(file, &poll->table); |
89 | if (mask) | 90 | if (mask) |
90 | vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); | 91 | vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); |
@@ -101,6 +102,7 @@ static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, | |||
101 | unsigned seq) | 102 | unsigned seq) |
102 | { | 103 | { |
103 | int left; | 104 | int left; |
105 | |||
104 | spin_lock_irq(&dev->work_lock); | 106 | spin_lock_irq(&dev->work_lock); |
105 | left = seq - work->done_seq; | 107 | left = seq - work->done_seq; |
106 | spin_unlock_irq(&dev->work_lock); | 108 | spin_unlock_irq(&dev->work_lock); |
@@ -222,6 +224,7 @@ static int vhost_worker(void *data) | |||
222 | static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) | 224 | static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) |
223 | { | 225 | { |
224 | int i; | 226 | int i; |
227 | |||
225 | for (i = 0; i < dev->nvqs; ++i) { | 228 | for (i = 0; i < dev->nvqs; ++i) { |
226 | dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect * | 229 | dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect * |
227 | UIO_MAXIOV, GFP_KERNEL); | 230 | UIO_MAXIOV, GFP_KERNEL); |
@@ -235,6 +238,7 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) | |||
235 | goto err_nomem; | 238 | goto err_nomem; |
236 | } | 239 | } |
237 | return 0; | 240 | return 0; |
241 | |||
238 | err_nomem: | 242 | err_nomem: |
239 | for (; i >= 0; --i) { | 243 | for (; i >= 0; --i) { |
240 | kfree(dev->vqs[i].indirect); | 244 | kfree(dev->vqs[i].indirect); |
@@ -247,6 +251,7 @@ err_nomem: | |||
247 | static void vhost_dev_free_iovecs(struct vhost_dev *dev) | 251 | static void vhost_dev_free_iovecs(struct vhost_dev *dev) |
248 | { | 252 | { |
249 | int i; | 253 | int i; |
254 | |||
250 | for (i = 0; i < dev->nvqs; ++i) { | 255 | for (i = 0; i < dev->nvqs; ++i) { |
251 | kfree(dev->vqs[i].indirect); | 256 | kfree(dev->vqs[i].indirect); |
252 | dev->vqs[i].indirect = NULL; | 257 | dev->vqs[i].indirect = NULL; |
@@ -296,26 +301,28 @@ long vhost_dev_check_owner(struct vhost_dev *dev) | |||
296 | } | 301 | } |
297 | 302 | ||
298 | struct vhost_attach_cgroups_struct { | 303 | struct vhost_attach_cgroups_struct { |
299 | struct vhost_work work; | 304 | struct vhost_work work; |
300 | struct task_struct *owner; | 305 | struct task_struct *owner; |
301 | int ret; | 306 | int ret; |
302 | }; | 307 | }; |
303 | 308 | ||
304 | static void vhost_attach_cgroups_work(struct vhost_work *work) | 309 | static void vhost_attach_cgroups_work(struct vhost_work *work) |
305 | { | 310 | { |
306 | struct vhost_attach_cgroups_struct *s; | 311 | struct vhost_attach_cgroups_struct *s; |
307 | s = container_of(work, struct vhost_attach_cgroups_struct, work); | 312 | |
308 | s->ret = cgroup_attach_task_all(s->owner, current); | 313 | s = container_of(work, struct vhost_attach_cgroups_struct, work); |
314 | s->ret = cgroup_attach_task_all(s->owner, current); | ||
309 | } | 315 | } |
310 | 316 | ||
311 | static int vhost_attach_cgroups(struct vhost_dev *dev) | 317 | static int vhost_attach_cgroups(struct vhost_dev *dev) |
312 | { | 318 | { |
313 | struct vhost_attach_cgroups_struct attach; | 319 | struct vhost_attach_cgroups_struct attach; |
314 | attach.owner = current; | 320 | |
315 | vhost_work_init(&attach.work, vhost_attach_cgroups_work); | 321 | attach.owner = current; |
316 | vhost_work_queue(dev, &attach.work); | 322 | vhost_work_init(&attach.work, vhost_attach_cgroups_work); |
317 | vhost_work_flush(dev, &attach.work); | 323 | vhost_work_queue(dev, &attach.work); |
318 | return attach.ret; | 324 | vhost_work_flush(dev, &attach.work); |
325 | return attach.ret; | ||
319 | } | 326 | } |
320 | 327 | ||
321 | /* Caller should have device mutex */ | 328 | /* Caller should have device mutex */ |
@@ -323,11 +330,13 @@ static long vhost_dev_set_owner(struct vhost_dev *dev) | |||
323 | { | 330 | { |
324 | struct task_struct *worker; | 331 | struct task_struct *worker; |
325 | int err; | 332 | int err; |
333 | |||
326 | /* Is there an owner already? */ | 334 | /* Is there an owner already? */ |
327 | if (dev->mm) { | 335 | if (dev->mm) { |
328 | err = -EBUSY; | 336 | err = -EBUSY; |
329 | goto err_mm; | 337 | goto err_mm; |
330 | } | 338 | } |
339 | |||
331 | /* No owner, become one */ | 340 | /* No owner, become one */ |
332 | dev->mm = get_task_mm(current); | 341 | dev->mm = get_task_mm(current); |
333 | worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid); | 342 | worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid); |
@@ -380,6 +389,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev) | |||
380 | void vhost_dev_cleanup(struct vhost_dev *dev) | 389 | void vhost_dev_cleanup(struct vhost_dev *dev) |
381 | { | 390 | { |
382 | int i; | 391 | int i; |
392 | |||
383 | for (i = 0; i < dev->nvqs; ++i) { | 393 | for (i = 0; i < dev->nvqs; ++i) { |
384 | if (dev->vqs[i].kick && dev->vqs[i].handle_kick) { | 394 | if (dev->vqs[i].kick && dev->vqs[i].handle_kick) { |
385 | vhost_poll_stop(&dev->vqs[i].poll); | 395 | vhost_poll_stop(&dev->vqs[i].poll); |
@@ -421,6 +431,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev) | |||
421 | static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) | 431 | static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) |
422 | { | 432 | { |
423 | u64 a = addr / VHOST_PAGE_SIZE / 8; | 433 | u64 a = addr / VHOST_PAGE_SIZE / 8; |
434 | |||
424 | /* Make sure 64 bit math will not overflow. */ | 435 | /* Make sure 64 bit math will not overflow. */ |
425 | if (a > ULONG_MAX - (unsigned long)log_base || | 436 | if (a > ULONG_MAX - (unsigned long)log_base || |
426 | a + (unsigned long)log_base > ULONG_MAX) | 437 | a + (unsigned long)log_base > ULONG_MAX) |
@@ -461,6 +472,7 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem, | |||
461 | int log_all) | 472 | int log_all) |
462 | { | 473 | { |
463 | int i; | 474 | int i; |
475 | |||
464 | for (i = 0; i < d->nvqs; ++i) { | 476 | for (i = 0; i < d->nvqs; ++i) { |
465 | int ok; | 477 | int ok; |
466 | mutex_lock(&d->vqs[i].mutex); | 478 | mutex_lock(&d->vqs[i].mutex); |
@@ -527,6 +539,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
527 | { | 539 | { |
528 | struct vhost_memory mem, *newmem, *oldmem; | 540 | struct vhost_memory mem, *newmem, *oldmem; |
529 | unsigned long size = offsetof(struct vhost_memory, regions); | 541 | unsigned long size = offsetof(struct vhost_memory, regions); |
542 | |||
530 | if (copy_from_user(&mem, m, size)) | 543 | if (copy_from_user(&mem, m, size)) |
531 | return -EFAULT; | 544 | return -EFAULT; |
532 | if (mem.padding) | 545 | if (mem.padding) |
@@ -544,7 +557,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
544 | return -EFAULT; | 557 | return -EFAULT; |
545 | } | 558 | } |
546 | 559 | ||
547 | if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) { | 560 | if (!memory_access_ok(d, newmem, |
561 | vhost_has_feature(d, VHOST_F_LOG_ALL))) { | ||
548 | kfree(newmem); | 562 | kfree(newmem); |
549 | return -EFAULT; | 563 | return -EFAULT; |
550 | } | 564 | } |
@@ -560,6 +574,7 @@ static int init_used(struct vhost_virtqueue *vq, | |||
560 | struct vring_used __user *used) | 574 | struct vring_used __user *used) |
561 | { | 575 | { |
562 | int r = put_user(vq->used_flags, &used->flags); | 576 | int r = put_user(vq->used_flags, &used->flags); |
577 | |||
563 | if (r) | 578 | if (r) |
564 | return r; | 579 | return r; |
565 | return get_user(vq->last_used_idx, &used->idx); | 580 | return get_user(vq->last_used_idx, &used->idx); |
@@ -849,6 +864,7 @@ static const struct vhost_memory_region *find_region(struct vhost_memory *mem, | |||
849 | { | 864 | { |
850 | struct vhost_memory_region *reg; | 865 | struct vhost_memory_region *reg; |
851 | int i; | 866 | int i; |
867 | |||
852 | /* linear search is not brilliant, but we really have on the order of 6 | 868 | /* linear search is not brilliant, but we really have on the order of 6 |
853 | * regions in practice */ | 869 | * regions in practice */ |
854 | for (i = 0; i < mem->nregions; ++i) { | 870 | for (i = 0; i < mem->nregions; ++i) { |
@@ -871,6 +887,7 @@ static int set_bit_to_user(int nr, void __user *addr) | |||
871 | void *base; | 887 | void *base; |
872 | int bit = nr + (log % PAGE_SIZE) * 8; | 888 | int bit = nr + (log % PAGE_SIZE) * 8; |
873 | int r; | 889 | int r; |
890 | |||
874 | r = get_user_pages_fast(log, 1, 1, &page); | 891 | r = get_user_pages_fast(log, 1, 1, &page); |
875 | if (r < 0) | 892 | if (r < 0) |
876 | return r; | 893 | return r; |
@@ -888,6 +905,7 @@ static int log_write(void __user *log_base, | |||
888 | { | 905 | { |
889 | u64 write_page = write_address / VHOST_PAGE_SIZE; | 906 | u64 write_page = write_address / VHOST_PAGE_SIZE; |
890 | int r; | 907 | int r; |
908 | |||
891 | if (!write_length) | 909 | if (!write_length) |
892 | return 0; | 910 | return 0; |
893 | write_length += write_address % VHOST_PAGE_SIZE; | 911 | write_length += write_address % VHOST_PAGE_SIZE; |
@@ -1037,8 +1055,8 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
1037 | i, count); | 1055 | i, count); |
1038 | return -EINVAL; | 1056 | return -EINVAL; |
1039 | } | 1057 | } |
1040 | if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect, | 1058 | if (unlikely(memcpy_fromiovec((unsigned char *)&desc, |
1041 | sizeof desc))) { | 1059 | vq->indirect, sizeof desc))) { |
1042 | vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", | 1060 | vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", |
1043 | i, (size_t)indirect->addr + i * sizeof desc); | 1061 | i, (size_t)indirect->addr + i * sizeof desc); |
1044 | return -EINVAL; | 1062 | return -EINVAL; |
@@ -1153,7 +1171,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
1153 | i, vq->num, head); | 1171 | i, vq->num, head); |
1154 | return -EINVAL; | 1172 | return -EINVAL; |
1155 | } | 1173 | } |
1156 | ret = copy_from_user(&desc, vq->desc + i, sizeof desc); | 1174 | ret = __copy_from_user(&desc, vq->desc + i, sizeof desc); |
1157 | if (unlikely(ret)) { | 1175 | if (unlikely(ret)) { |
1158 | vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", | 1176 | vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", |
1159 | i, vq->desc + i); | 1177 | i, vq->desc + i); |
@@ -1317,6 +1335,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, | |||
1317 | void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) | 1335 | void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) |
1318 | { | 1336 | { |
1319 | __u16 flags; | 1337 | __u16 flags; |
1338 | |||
1320 | /* Flush out used index updates. This is paired | 1339 | /* Flush out used index updates. This is paired |
1321 | * with the barrier that the Guest executes when enabling | 1340 | * with the barrier that the Guest executes when enabling |
1322 | * interrupts. */ | 1341 | * interrupts. */ |
@@ -1361,6 +1380,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq) | |||
1361 | { | 1380 | { |
1362 | u16 avail_idx; | 1381 | u16 avail_idx; |
1363 | int r; | 1382 | int r; |
1383 | |||
1364 | if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) | 1384 | if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) |
1365 | return false; | 1385 | return false; |
1366 | vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; | 1386 | vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; |
@@ -1387,6 +1407,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq) | |||
1387 | void vhost_disable_notify(struct vhost_virtqueue *vq) | 1407 | void vhost_disable_notify(struct vhost_virtqueue *vq) |
1388 | { | 1408 | { |
1389 | int r; | 1409 | int r; |
1410 | |||
1390 | if (vq->used_flags & VRING_USED_F_NO_NOTIFY) | 1411 | if (vq->used_flags & VRING_USED_F_NO_NOTIFY) |
1391 | return; | 1412 | return; |
1392 | vq->used_flags |= VRING_USED_F_NO_NOTIFY; | 1413 | vq->used_flags |= VRING_USED_F_NO_NOTIFY; |
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index aac3e2eeb4fd..b297f288f6eb 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h | |||
@@ -13,6 +13,9 @@ | |||
13 | #ifndef _LINUX_ETHTOOL_H | 13 | #ifndef _LINUX_ETHTOOL_H |
14 | #define _LINUX_ETHTOOL_H | 14 | #define _LINUX_ETHTOOL_H |
15 | 15 | ||
16 | #ifdef __KERNEL__ | ||
17 | #include <linux/compat.h> | ||
18 | #endif | ||
16 | #include <linux/types.h> | 19 | #include <linux/types.h> |
17 | #include <linux/if_ether.h> | 20 | #include <linux/if_ether.h> |
18 | 21 | ||
@@ -450,6 +453,37 @@ struct ethtool_rxnfc { | |||
450 | __u32 rule_locs[0]; | 453 | __u32 rule_locs[0]; |
451 | }; | 454 | }; |
452 | 455 | ||
456 | #ifdef __KERNEL__ | ||
457 | #ifdef CONFIG_COMPAT | ||
458 | |||
459 | struct compat_ethtool_rx_flow_spec { | ||
460 | u32 flow_type; | ||
461 | union { | ||
462 | struct ethtool_tcpip4_spec tcp_ip4_spec; | ||
463 | struct ethtool_tcpip4_spec udp_ip4_spec; | ||
464 | struct ethtool_tcpip4_spec sctp_ip4_spec; | ||
465 | struct ethtool_ah_espip4_spec ah_ip4_spec; | ||
466 | struct ethtool_ah_espip4_spec esp_ip4_spec; | ||
467 | struct ethtool_usrip4_spec usr_ip4_spec; | ||
468 | struct ethhdr ether_spec; | ||
469 | u8 hdata[72]; | ||
470 | } h_u, m_u; | ||
471 | compat_u64 ring_cookie; | ||
472 | u32 location; | ||
473 | }; | ||
474 | |||
475 | struct compat_ethtool_rxnfc { | ||
476 | u32 cmd; | ||
477 | u32 flow_type; | ||
478 | compat_u64 data; | ||
479 | struct compat_ethtool_rx_flow_spec fs; | ||
480 | u32 rule_cnt; | ||
481 | u32 rule_locs[0]; | ||
482 | }; | ||
483 | |||
484 | #endif /* CONFIG_COMPAT */ | ||
485 | #endif /* __KERNEL__ */ | ||
486 | |||
453 | /** | 487 | /** |
454 | * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection | 488 | * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection |
455 | * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR | 489 | * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR |
diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index fcef103aa3f6..c9ad38322576 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h | |||
@@ -114,14 +114,14 @@ struct pppol2tp_ioc_stats { | |||
114 | __u16 tunnel_id; /* redundant */ | 114 | __u16 tunnel_id; /* redundant */ |
115 | __u16 session_id; /* if zero, get tunnel stats */ | 115 | __u16 session_id; /* if zero, get tunnel stats */ |
116 | __u32 using_ipsec:1; /* valid only for session_id == 0 */ | 116 | __u32 using_ipsec:1; /* valid only for session_id == 0 */ |
117 | aligned_u64 tx_packets; | 117 | __aligned_u64 tx_packets; |
118 | aligned_u64 tx_bytes; | 118 | __aligned_u64 tx_bytes; |
119 | aligned_u64 tx_errors; | 119 | __aligned_u64 tx_errors; |
120 | aligned_u64 rx_packets; | 120 | __aligned_u64 rx_packets; |
121 | aligned_u64 rx_bytes; | 121 | __aligned_u64 rx_bytes; |
122 | aligned_u64 rx_seq_discards; | 122 | __aligned_u64 rx_seq_discards; |
123 | aligned_u64 rx_oos_packets; | 123 | __aligned_u64 rx_oos_packets; |
124 | aligned_u64 rx_errors; | 124 | __aligned_u64 rx_errors; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | #define ifr__name b.ifr_ifrn.ifrn_name | 127 | #define ifr__name b.ifr_ifrn.ifrn_name |
diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h index 3882a81a3b3c..5aebd170f899 100644 --- a/include/linux/netfilter/ipset/ip_set_getport.h +++ b/include/linux/netfilter/ipset/ip_set_getport.h | |||
@@ -18,4 +18,14 @@ static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, | |||
18 | extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, | 18 | extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, |
19 | __be16 *port); | 19 | __be16 *port); |
20 | 20 | ||
21 | static inline bool ip_set_proto_with_ports(u8 proto) | ||
22 | { | ||
23 | switch (proto) { | ||
24 | case IPPROTO_TCP: | ||
25 | case IPPROTO_UDP: | ||
26 | return true; | ||
27 | } | ||
28 | return false; | ||
29 | } | ||
30 | |||
21 | #endif /*_IP_SET_GETPORT_H*/ | 31 | #endif /*_IP_SET_GETPORT_H*/ |
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index ea9b8d380527..90c2c9575bac 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h | |||
@@ -28,8 +28,8 @@ struct nfulnl_msg_packet_hw { | |||
28 | }; | 28 | }; |
29 | 29 | ||
30 | struct nfulnl_msg_packet_timestamp { | 30 | struct nfulnl_msg_packet_timestamp { |
31 | aligned_be64 sec; | 31 | __aligned_be64 sec; |
32 | aligned_be64 usec; | 32 | __aligned_be64 usec; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | enum nfulnl_attr_type { | 35 | enum nfulnl_attr_type { |
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 2455fe5f4e01..af94e0014ebd 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h | |||
@@ -25,8 +25,8 @@ struct nfqnl_msg_packet_hw { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | struct nfqnl_msg_packet_timestamp { | 27 | struct nfqnl_msg_packet_timestamp { |
28 | aligned_be64 sec; | 28 | __aligned_be64 sec; |
29 | aligned_be64 usec; | 29 | __aligned_be64 usec; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | enum nfqnl_attr_type { | 32 | enum nfqnl_attr_type { |
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h index 92fcbb0d193e..f1d6c15bd9e3 100644 --- a/include/linux/netfilter/xt_connbytes.h +++ b/include/linux/netfilter/xt_connbytes.h | |||
@@ -17,8 +17,8 @@ enum xt_connbytes_direction { | |||
17 | 17 | ||
18 | struct xt_connbytes_info { | 18 | struct xt_connbytes_info { |
19 | struct { | 19 | struct { |
20 | aligned_u64 from; /* count to be matched */ | 20 | __aligned_u64 from; /* count to be matched */ |
21 | aligned_u64 to; /* count to be matched */ | 21 | __aligned_u64 to; /* count to be matched */ |
22 | } count; | 22 | } count; |
23 | __u8 what; /* ipt_connbytes_what */ | 23 | __u8 what; /* ipt_connbytes_what */ |
24 | __u8 direction; /* ipt_connbytes_direction */ | 24 | __u8 direction; /* ipt_connbytes_direction */ |
diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h index ca6e03e47a17..9314723f39ca 100644 --- a/include/linux/netfilter/xt_quota.h +++ b/include/linux/netfilter/xt_quota.h | |||
@@ -13,7 +13,7 @@ struct xt_quota_priv; | |||
13 | struct xt_quota_info { | 13 | struct xt_quota_info { |
14 | __u32 flags; | 14 | __u32 flags; |
15 | __u32 pad; | 15 | __u32 pad; |
16 | aligned_u64 quota; | 16 | __aligned_u64 quota; |
17 | 17 | ||
18 | /* Used internally by the kernel */ | 18 | /* Used internally by the kernel */ |
19 | struct xt_quota_priv *master; | 19 | struct xt_quota_priv *master; |
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 272f59336b73..30b49ed72f0d 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -801,8 +801,6 @@ struct netns_ipvs { | |||
801 | struct list_head rs_table[IP_VS_RTAB_SIZE]; | 801 | struct list_head rs_table[IP_VS_RTAB_SIZE]; |
802 | /* ip_vs_app */ | 802 | /* ip_vs_app */ |
803 | struct list_head app_list; | 803 | struct list_head app_list; |
804 | struct mutex app_mutex; | ||
805 | struct lock_class_key app_key; /* mutex debuging */ | ||
806 | 804 | ||
807 | /* ip_vs_proto */ | 805 | /* ip_vs_proto */ |
808 | #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */ | 806 | #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */ |
diff --git a/include/net/snmp.h b/include/net/snmp.h index 762e2abce889..27461d6dd46f 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h | |||
@@ -150,7 +150,7 @@ struct linux_xfrm_mib { | |||
150 | #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ | 150 | #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ |
151 | do { \ | 151 | do { \ |
152 | __typeof__(*mib[0]) *ptr = \ | 152 | __typeof__(*mib[0]) *ptr = \ |
153 | __this_cpu_ptr((mib)[!in_softirq()]); \ | 153 | __this_cpu_ptr((mib)[0]); \ |
154 | ptr->mibs[basefield##PKTS]++; \ | 154 | ptr->mibs[basefield##PKTS]++; \ |
155 | ptr->mibs[basefield##OCTETS] += addend;\ | 155 | ptr->mibs[basefield##OCTETS] += addend;\ |
156 | } while (0) | 156 | } while (0) |
@@ -202,7 +202,7 @@ struct linux_xfrm_mib { | |||
202 | #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \ | 202 | #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \ |
203 | do { \ | 203 | do { \ |
204 | __typeof__(*mib[0]) *ptr; \ | 204 | __typeof__(*mib[0]) *ptr; \ |
205 | ptr = __this_cpu_ptr((mib)[!in_softirq()]); \ | 205 | ptr = __this_cpu_ptr((mib)[0]); \ |
206 | u64_stats_update_begin(&ptr->syncp); \ | 206 | u64_stats_update_begin(&ptr->syncp); \ |
207 | ptr->mibs[basefield##PKTS]++; \ | 207 | ptr->mibs[basefield##PKTS]++; \ |
208 | ptr->mibs[basefield##OCTETS] += addend; \ | 208 | ptr->mibs[basefield##OCTETS] += addend; \ |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 42a8c32a10e2..cffa5dc66449 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -1430,6 +1430,7 @@ extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); | |||
1430 | extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); | 1430 | extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); |
1431 | extern int xfrm_init_replay(struct xfrm_state *x); | 1431 | extern int xfrm_init_replay(struct xfrm_state *x); |
1432 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); | 1432 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); |
1433 | extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay); | ||
1433 | extern int xfrm_init_state(struct xfrm_state *x); | 1434 | extern int xfrm_init_state(struct xfrm_state *x); |
1434 | extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb); | 1435 | extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb); |
1435 | extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, | 1436 | extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ae610f046de5..e34ea9e5e28b 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -720,6 +720,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
720 | dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid; | 720 | dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid; |
721 | #endif | 721 | #endif |
722 | 722 | ||
723 | dev->needed_headroom = real_dev->needed_headroom; | ||
723 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | 724 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
724 | dev->header_ops = real_dev->header_ops; | 725 | dev->header_ops = real_dev->header_ops; |
725 | dev->hard_header_len = real_dev->hard_header_len; | 726 | dev->hard_header_len = real_dev->hard_header_len; |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 3d4f4b043406..206e771e82d1 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1051,6 +1051,7 @@ static int atalk_release(struct socket *sock) | |||
1051 | { | 1051 | { |
1052 | struct sock *sk = sock->sk; | 1052 | struct sock *sk = sock->sk; |
1053 | 1053 | ||
1054 | sock_hold(sk); | ||
1054 | lock_sock(sk); | 1055 | lock_sock(sk); |
1055 | if (sk) { | 1056 | if (sk) { |
1056 | sock_orphan(sk); | 1057 | sock_orphan(sk); |
@@ -1058,6 +1059,8 @@ static int atalk_release(struct socket *sock) | |||
1058 | atalk_destroy_socket(sk); | 1059 | atalk_destroy_socket(sk); |
1059 | } | 1060 | } |
1060 | release_sock(sk); | 1061 | release_sock(sk); |
1062 | sock_put(sk); | ||
1063 | |||
1061 | return 0; | 1064 | return 0; |
1062 | } | 1065 | } |
1063 | 1066 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index f97af5590ba1..008ff6c4eecf 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -739,6 +739,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, | |||
739 | nf_bridge->mask |= BRNF_PKT_TYPE; | 739 | nf_bridge->mask |= BRNF_PKT_TYPE; |
740 | } | 740 | } |
741 | 741 | ||
742 | if (br_parse_ip_options(skb)) | ||
743 | return NF_DROP; | ||
744 | |||
742 | /* The physdev module checks on this */ | 745 | /* The physdev module checks on this */ |
743 | nf_bridge->mask |= BRNF_BRIDGED; | 746 | nf_bridge->mask |= BRNF_BRIDGED; |
744 | nf_bridge->physoutdev = skb->dev; | 747 | nf_bridge->physoutdev = skb->dev; |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 36e603c78ce9..706502ff64aa 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -350,7 +350,7 @@ static int __init init_net_drop_monitor(void) | |||
350 | struct per_cpu_dm_data *data; | 350 | struct per_cpu_dm_data *data; |
351 | int cpu, rc; | 351 | int cpu, rc; |
352 | 352 | ||
353 | printk(KERN_INFO "Initalizing network drop monitor service\n"); | 353 | printk(KERN_INFO "Initializing network drop monitor service\n"); |
354 | 354 | ||
355 | if (sizeof(void *) > 8) { | 355 | if (sizeof(void *) > 8) { |
356 | printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n"); | 356 | printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n"); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index c1a71bb738da..a1086fb0c0c7 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -1457,6 +1457,9 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data) | |||
1457 | { | 1457 | { |
1458 | int err; | 1458 | int err; |
1459 | 1459 | ||
1460 | if (!dev->ethtool_ops->set_sg) | ||
1461 | return -EOPNOTSUPP; | ||
1462 | |||
1460 | if (data && !(dev->features & NETIF_F_ALL_CSUM)) | 1463 | if (data && !(dev->features & NETIF_F_ALL_CSUM)) |
1461 | return -EINVAL; | 1464 | return -EINVAL; |
1462 | 1465 | ||
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 0c2826337919..116d3fd3d669 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -435,10 +435,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
435 | udpdest.sin_addr.s_addr = htonl(network | addr.station); | 435 | udpdest.sin_addr.s_addr = htonl(network | addr.station); |
436 | } | 436 | } |
437 | 437 | ||
438 | memset(&ah, 0, sizeof(ah)); | ||
438 | ah.port = port; | 439 | ah.port = port; |
439 | ah.cb = cb & 0x7f; | 440 | ah.cb = cb & 0x7f; |
440 | ah.code = 2; /* magic */ | 441 | ah.code = 2; /* magic */ |
441 | ah.pad = 0; | ||
442 | 442 | ||
443 | /* tack our header on the front of the iovec */ | 443 | /* tack our header on the front of the iovec */ |
444 | size = sizeof(struct aunhdr); | 444 | size = sizeof(struct aunhdr); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index b09ed0d080f9..ffcea0d1678e 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -387,7 +387,7 @@ ipt_do_table(struct sk_buff *skb, | |||
387 | verdict = (unsigned)(-v) - 1; | 387 | verdict = (unsigned)(-v) - 1; |
388 | break; | 388 | break; |
389 | } | 389 | } |
390 | if (*stackptr == 0) { | 390 | if (*stackptr <= origptr) { |
391 | e = get_entry(table_base, | 391 | e = get_entry(table_base, |
392 | private->underflow[hook]); | 392 | private->underflow[hook]); |
393 | pr_debug("Underflow (this is normal) " | 393 | pr_debug("Underflow (this is normal) " |
@@ -427,10 +427,10 @@ ipt_do_table(struct sk_buff *skb, | |||
427 | /* Verdict */ | 427 | /* Verdict */ |
428 | break; | 428 | break; |
429 | } while (!acpar.hotdrop); | 429 | } while (!acpar.hotdrop); |
430 | xt_info_rdunlock_bh(); | ||
431 | pr_debug("Exiting %s; resetting sp from %u to %u\n", | 430 | pr_debug("Exiting %s; resetting sp from %u to %u\n", |
432 | __func__, *stackptr, origptr); | 431 | __func__, *stackptr, origptr); |
433 | *stackptr = origptr; | 432 | *stackptr = origptr; |
433 | xt_info_rdunlock_bh(); | ||
434 | #ifdef DEBUG_ALLOW_ALL | 434 | #ifdef DEBUG_ALLOW_ALL |
435 | return NF_ACCEPT; | 435 | return NF_ACCEPT; |
436 | #else | 436 | #else |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 403ca57f6011..d609ac3cb9a4 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -664,8 +664,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input, | |||
664 | char buffer[PROC_WRITELEN+1]; | 664 | char buffer[PROC_WRITELEN+1]; |
665 | unsigned long nodenum; | 665 | unsigned long nodenum; |
666 | 666 | ||
667 | if (copy_from_user(buffer, input, PROC_WRITELEN)) | 667 | if (size > PROC_WRITELEN) |
668 | return -EIO; | ||
669 | if (copy_from_user(buffer, input, size)) | ||
668 | return -EFAULT; | 670 | return -EFAULT; |
671 | buffer[size] = 0; | ||
669 | 672 | ||
670 | if (*buffer == '+') { | 673 | if (*buffer == '+') { |
671 | nodenum = simple_strtoul(buffer+1, NULL, 10); | 674 | nodenum = simple_strtoul(buffer+1, NULL, 10); |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index c9598a9067d7..0b2af9b85cec 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -410,7 +410,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
410 | verdict = (unsigned)(-v) - 1; | 410 | verdict = (unsigned)(-v) - 1; |
411 | break; | 411 | break; |
412 | } | 412 | } |
413 | if (*stackptr == 0) | 413 | if (*stackptr <= origptr) |
414 | e = get_entry(table_base, | 414 | e = get_entry(table_base, |
415 | private->underflow[hook]); | 415 | private->underflow[hook]); |
416 | else | 416 | else |
@@ -441,8 +441,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
441 | break; | 441 | break; |
442 | } while (!acpar.hotdrop); | 442 | } while (!acpar.hotdrop); |
443 | 443 | ||
444 | xt_info_rdunlock_bh(); | ||
445 | *stackptr = origptr; | 444 | *stackptr = origptr; |
445 | xt_info_rdunlock_bh(); | ||
446 | 446 | ||
447 | #ifdef DEBUG_ALLOW_ALL | 447 | #ifdef DEBUG_ALLOW_ALL |
448 | return NF_ACCEPT; | 448 | return NF_ACCEPT; |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 7cb65ef79f9c..6dcf5e7d661b 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -17,6 +17,16 @@ | |||
17 | 17 | ||
18 | static struct ctl_table empty[1]; | 18 | static struct ctl_table empty[1]; |
19 | 19 | ||
20 | static ctl_table ipv6_static_skeleton[] = { | ||
21 | { | ||
22 | .procname = "neigh", | ||
23 | .maxlen = 0, | ||
24 | .mode = 0555, | ||
25 | .child = empty, | ||
26 | }, | ||
27 | { } | ||
28 | }; | ||
29 | |||
20 | static ctl_table ipv6_table_template[] = { | 30 | static ctl_table ipv6_table_template[] = { |
21 | { | 31 | { |
22 | .procname = "route", | 32 | .procname = "route", |
@@ -37,12 +47,6 @@ static ctl_table ipv6_table_template[] = { | |||
37 | .mode = 0644, | 47 | .mode = 0644, |
38 | .proc_handler = proc_dointvec | 48 | .proc_handler = proc_dointvec |
39 | }, | 49 | }, |
40 | { | ||
41 | .procname = "neigh", | ||
42 | .maxlen = 0, | ||
43 | .mode = 0555, | ||
44 | .child = empty, | ||
45 | }, | ||
46 | { } | 50 | { } |
47 | }; | 51 | }; |
48 | 52 | ||
@@ -160,7 +164,7 @@ static struct ctl_table_header *ip6_base; | |||
160 | 164 | ||
161 | int ipv6_static_sysctl_register(void) | 165 | int ipv6_static_sysctl_register(void) |
162 | { | 166 | { |
163 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); | 167 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton); |
164 | if (ip6_base == NULL) | 168 | if (ip6_base == NULL) |
165 | return -ENOMEM; | 169 | return -ENOMEM; |
166 | return 0; | 170 | return 0; |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 2731b51923d1..9680226640ef 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -148,7 +148,6 @@ static void ipx_destroy_socket(struct sock *sk) | |||
148 | ipx_remove_socket(sk); | 148 | ipx_remove_socket(sk); |
149 | skb_queue_purge(&sk->sk_receive_queue); | 149 | skb_queue_purge(&sk->sk_receive_queue); |
150 | sk_refcnt_debug_dec(sk); | 150 | sk_refcnt_debug_dec(sk); |
151 | sock_put(sk); | ||
152 | } | 151 | } |
153 | 152 | ||
154 | /* | 153 | /* |
@@ -1404,6 +1403,7 @@ static int ipx_release(struct socket *sock) | |||
1404 | sk_refcnt_debug_release(sk); | 1403 | sk_refcnt_debug_release(sk); |
1405 | ipx_destroy_socket(sk); | 1404 | ipx_destroy_socket(sk); |
1406 | release_sock(sk); | 1405 | release_sock(sk); |
1406 | sock_put(sk); | ||
1407 | out: | 1407 | out: |
1408 | return 0; | 1408 | return 0; |
1409 | } | 1409 | } |
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 8d9ce0accc98..a8193f52c13c 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
@@ -283,7 +283,7 @@ static __net_init int l2tp_eth_init_net(struct net *net) | |||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | static __net_initdata struct pernet_operations l2tp_eth_net_ops = { | 286 | static struct pernet_operations l2tp_eth_net_ops = { |
287 | .init = l2tp_eth_init_net, | 287 | .init = l2tp_eth_init_net, |
288 | .id = &l2tp_eth_net_id, | 288 | .id = &l2tp_eth_net_id, |
289 | .size = sizeof(struct l2tp_eth_net), | 289 | .size = sizeof(struct l2tp_eth_net), |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 618a615acc9d..d6b48230a540 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -94,16 +94,28 @@ static int | |||
94 | find_set_type_get(const char *name, u8 family, u8 revision, | 94 | find_set_type_get(const char *name, u8 family, u8 revision, |
95 | struct ip_set_type **found) | 95 | struct ip_set_type **found) |
96 | { | 96 | { |
97 | struct ip_set_type *type; | ||
98 | int err; | ||
99 | |||
97 | rcu_read_lock(); | 100 | rcu_read_lock(); |
98 | *found = find_set_type(name, family, revision); | 101 | *found = find_set_type(name, family, revision); |
99 | if (*found) { | 102 | if (*found) { |
100 | int err = !try_module_get((*found)->me); | 103 | err = !try_module_get((*found)->me) ? -EFAULT : 0; |
101 | rcu_read_unlock(); | 104 | goto unlock; |
102 | return err ? -EFAULT : 0; | ||
103 | } | 105 | } |
106 | /* Make sure the type is loaded but we don't support the revision */ | ||
107 | list_for_each_entry_rcu(type, &ip_set_type_list, list) | ||
108 | if (STREQ(type->name, name)) { | ||
109 | err = -IPSET_ERR_FIND_TYPE; | ||
110 | goto unlock; | ||
111 | } | ||
104 | rcu_read_unlock(); | 112 | rcu_read_unlock(); |
105 | 113 | ||
106 | return try_to_load_type(name); | 114 | return try_to_load_type(name); |
115 | |||
116 | unlock: | ||
117 | rcu_read_unlock(); | ||
118 | return err; | ||
107 | } | 119 | } |
108 | 120 | ||
109 | /* Find a given set type by name and family. | 121 | /* Find a given set type by name and family. |
@@ -116,7 +128,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) | |||
116 | struct ip_set_type *type; | 128 | struct ip_set_type *type; |
117 | bool found = false; | 129 | bool found = false; |
118 | 130 | ||
119 | *min = *max = 0; | 131 | *min = 255; *max = 0; |
120 | rcu_read_lock(); | 132 | rcu_read_lock(); |
121 | list_for_each_entry_rcu(type, &ip_set_type_list, list) | 133 | list_for_each_entry_rcu(type, &ip_set_type_list, list) |
122 | if (STREQ(type->name, name) && | 134 | if (STREQ(type->name, name) && |
@@ -124,7 +136,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) | |||
124 | found = true; | 136 | found = true; |
125 | if (type->revision < *min) | 137 | if (type->revision < *min) |
126 | *min = type->revision; | 138 | *min = type->revision; |
127 | else if (type->revision > *max) | 139 | if (type->revision > *max) |
128 | *max = type->revision; | 140 | *max = type->revision; |
129 | } | 141 | } |
130 | rcu_read_unlock(); | 142 | rcu_read_unlock(); |
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index adbe787ea5dc..b9214145d357 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
@@ -150,6 +150,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
150 | struct hash_ipport4_elem data = { }; | 150 | struct hash_ipport4_elem data = { }; |
151 | u32 ip, ip_to, p, port, port_to; | 151 | u32 ip, ip_to, p, port, port_to; |
152 | u32 timeout = h->timeout; | 152 | u32 timeout = h->timeout; |
153 | bool with_ports = false; | ||
153 | int ret; | 154 | int ret; |
154 | 155 | ||
155 | if (unlikely(!tb[IPSET_ATTR_IP] || | 156 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -172,21 +173,15 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
172 | 173 | ||
173 | if (tb[IPSET_ATTR_PROTO]) { | 174 | if (tb[IPSET_ATTR_PROTO]) { |
174 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 175 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
176 | with_ports = ip_set_proto_with_ports(data.proto); | ||
175 | 177 | ||
176 | if (data.proto == 0) | 178 | if (data.proto == 0) |
177 | return -IPSET_ERR_INVALID_PROTO; | 179 | return -IPSET_ERR_INVALID_PROTO; |
178 | } else | 180 | } else |
179 | return -IPSET_ERR_MISSING_PROTO; | 181 | return -IPSET_ERR_MISSING_PROTO; |
180 | 182 | ||
181 | switch (data.proto) { | 183 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
182 | case IPPROTO_UDP: | ||
183 | case IPPROTO_TCP: | ||
184 | case IPPROTO_ICMP: | ||
185 | break; | ||
186 | default: | ||
187 | data.port = 0; | 184 | data.port = 0; |
188 | break; | ||
189 | } | ||
190 | 185 | ||
191 | if (tb[IPSET_ATTR_TIMEOUT]) { | 186 | if (tb[IPSET_ATTR_TIMEOUT]) { |
192 | if (!with_timeout(h->timeout)) | 187 | if (!with_timeout(h->timeout)) |
@@ -195,7 +190,6 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
195 | } | 190 | } |
196 | 191 | ||
197 | if (adt == IPSET_TEST || | 192 | if (adt == IPSET_TEST || |
198 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
199 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 193 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
200 | tb[IPSET_ATTR_PORT_TO])) { | 194 | tb[IPSET_ATTR_PORT_TO])) { |
201 | ret = adtfn(set, &data, timeout); | 195 | ret = adtfn(set, &data, timeout); |
@@ -219,13 +213,12 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
219 | } else | 213 | } else |
220 | ip_to = ip; | 214 | ip_to = ip; |
221 | 215 | ||
222 | port = ntohs(data.port); | 216 | port_to = port = ntohs(data.port); |
223 | if (tb[IPSET_ATTR_PORT_TO]) { | 217 | if (with_ports && tb[IPSET_ATTR_PORT_TO]) { |
224 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); | 218 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); |
225 | if (port > port_to) | 219 | if (port > port_to) |
226 | swap(port, port_to); | 220 | swap(port, port_to); |
227 | } else | 221 | } |
228 | port_to = port; | ||
229 | 222 | ||
230 | for (; !before(ip_to, ip); ip++) | 223 | for (; !before(ip_to, ip); ip++) |
231 | for (p = port; p <= port_to; p++) { | 224 | for (p = port; p <= port_to; p++) { |
@@ -361,6 +354,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
361 | struct hash_ipport6_elem data = { }; | 354 | struct hash_ipport6_elem data = { }; |
362 | u32 port, port_to; | 355 | u32 port, port_to; |
363 | u32 timeout = h->timeout; | 356 | u32 timeout = h->timeout; |
357 | bool with_ports = false; | ||
364 | int ret; | 358 | int ret; |
365 | 359 | ||
366 | if (unlikely(!tb[IPSET_ATTR_IP] || | 360 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -385,21 +379,15 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
385 | 379 | ||
386 | if (tb[IPSET_ATTR_PROTO]) { | 380 | if (tb[IPSET_ATTR_PROTO]) { |
387 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 381 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
382 | with_ports = ip_set_proto_with_ports(data.proto); | ||
388 | 383 | ||
389 | if (data.proto == 0) | 384 | if (data.proto == 0) |
390 | return -IPSET_ERR_INVALID_PROTO; | 385 | return -IPSET_ERR_INVALID_PROTO; |
391 | } else | 386 | } else |
392 | return -IPSET_ERR_MISSING_PROTO; | 387 | return -IPSET_ERR_MISSING_PROTO; |
393 | 388 | ||
394 | switch (data.proto) { | 389 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
395 | case IPPROTO_UDP: | ||
396 | case IPPROTO_TCP: | ||
397 | case IPPROTO_ICMPV6: | ||
398 | break; | ||
399 | default: | ||
400 | data.port = 0; | 390 | data.port = 0; |
401 | break; | ||
402 | } | ||
403 | 391 | ||
404 | if (tb[IPSET_ATTR_TIMEOUT]) { | 392 | if (tb[IPSET_ATTR_TIMEOUT]) { |
405 | if (!with_timeout(h->timeout)) | 393 | if (!with_timeout(h->timeout)) |
@@ -407,9 +395,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
407 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 395 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
408 | } | 396 | } |
409 | 397 | ||
410 | if (adt == IPSET_TEST || | 398 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
411 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
412 | !tb[IPSET_ATTR_PORT_TO]) { | ||
413 | ret = adtfn(set, &data, timeout); | 399 | ret = adtfn(set, &data, timeout); |
414 | return ip_set_eexist(ret, flags) ? 0 : ret; | 400 | return ip_set_eexist(ret, flags) ? 0 : ret; |
415 | } | 401 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 22e23abb86c6..4642872df6e1 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
@@ -154,6 +154,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
154 | struct hash_ipportip4_elem data = { }; | 154 | struct hash_ipportip4_elem data = { }; |
155 | u32 ip, ip_to, p, port, port_to; | 155 | u32 ip, ip_to, p, port, port_to; |
156 | u32 timeout = h->timeout; | 156 | u32 timeout = h->timeout; |
157 | bool with_ports = false; | ||
157 | int ret; | 158 | int ret; |
158 | 159 | ||
159 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 160 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -180,21 +181,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
180 | 181 | ||
181 | if (tb[IPSET_ATTR_PROTO]) { | 182 | if (tb[IPSET_ATTR_PROTO]) { |
182 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 183 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
184 | with_ports = ip_set_proto_with_ports(data.proto); | ||
183 | 185 | ||
184 | if (data.proto == 0) | 186 | if (data.proto == 0) |
185 | return -IPSET_ERR_INVALID_PROTO; | 187 | return -IPSET_ERR_INVALID_PROTO; |
186 | } else | 188 | } else |
187 | return -IPSET_ERR_MISSING_PROTO; | 189 | return -IPSET_ERR_MISSING_PROTO; |
188 | 190 | ||
189 | switch (data.proto) { | 191 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
190 | case IPPROTO_UDP: | ||
191 | case IPPROTO_TCP: | ||
192 | case IPPROTO_ICMP: | ||
193 | break; | ||
194 | default: | ||
195 | data.port = 0; | 192 | data.port = 0; |
196 | break; | ||
197 | } | ||
198 | 193 | ||
199 | if (tb[IPSET_ATTR_TIMEOUT]) { | 194 | if (tb[IPSET_ATTR_TIMEOUT]) { |
200 | if (!with_timeout(h->timeout)) | 195 | if (!with_timeout(h->timeout)) |
@@ -203,7 +198,6 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
203 | } | 198 | } |
204 | 199 | ||
205 | if (adt == IPSET_TEST || | 200 | if (adt == IPSET_TEST || |
206 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
207 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 201 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
208 | tb[IPSET_ATTR_PORT_TO])) { | 202 | tb[IPSET_ATTR_PORT_TO])) { |
209 | ret = adtfn(set, &data, timeout); | 203 | ret = adtfn(set, &data, timeout); |
@@ -227,13 +221,12 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
227 | } else | 221 | } else |
228 | ip_to = ip; | 222 | ip_to = ip; |
229 | 223 | ||
230 | port = ntohs(data.port); | 224 | port_to = port = ntohs(data.port); |
231 | if (tb[IPSET_ATTR_PORT_TO]) { | 225 | if (with_ports && tb[IPSET_ATTR_PORT_TO]) { |
232 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); | 226 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); |
233 | if (port > port_to) | 227 | if (port > port_to) |
234 | swap(port, port_to); | 228 | swap(port, port_to); |
235 | } else | 229 | } |
236 | port_to = port; | ||
237 | 230 | ||
238 | for (; !before(ip_to, ip); ip++) | 231 | for (; !before(ip_to, ip); ip++) |
239 | for (p = port; p <= port_to; p++) { | 232 | for (p = port; p <= port_to; p++) { |
@@ -375,6 +368,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
375 | struct hash_ipportip6_elem data = { }; | 368 | struct hash_ipportip6_elem data = { }; |
376 | u32 port, port_to; | 369 | u32 port, port_to; |
377 | u32 timeout = h->timeout; | 370 | u32 timeout = h->timeout; |
371 | bool with_ports = false; | ||
378 | int ret; | 372 | int ret; |
379 | 373 | ||
380 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 374 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -403,21 +397,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
403 | 397 | ||
404 | if (tb[IPSET_ATTR_PROTO]) { | 398 | if (tb[IPSET_ATTR_PROTO]) { |
405 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 399 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
400 | with_ports = ip_set_proto_with_ports(data.proto); | ||
406 | 401 | ||
407 | if (data.proto == 0) | 402 | if (data.proto == 0) |
408 | return -IPSET_ERR_INVALID_PROTO; | 403 | return -IPSET_ERR_INVALID_PROTO; |
409 | } else | 404 | } else |
410 | return -IPSET_ERR_MISSING_PROTO; | 405 | return -IPSET_ERR_MISSING_PROTO; |
411 | 406 | ||
412 | switch (data.proto) { | 407 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
413 | case IPPROTO_UDP: | ||
414 | case IPPROTO_TCP: | ||
415 | case IPPROTO_ICMPV6: | ||
416 | break; | ||
417 | default: | ||
418 | data.port = 0; | 408 | data.port = 0; |
419 | break; | ||
420 | } | ||
421 | 409 | ||
422 | if (tb[IPSET_ATTR_TIMEOUT]) { | 410 | if (tb[IPSET_ATTR_TIMEOUT]) { |
423 | if (!with_timeout(h->timeout)) | 411 | if (!with_timeout(h->timeout)) |
@@ -425,9 +413,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
425 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 413 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
426 | } | 414 | } |
427 | 415 | ||
428 | if (adt == IPSET_TEST || | 416 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
429 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
430 | !tb[IPSET_ATTR_PORT_TO]) { | ||
431 | ret = adtfn(set, &data, timeout); | 417 | ret = adtfn(set, &data, timeout); |
432 | return ip_set_eexist(ret, flags) ? 0 : ret; | 418 | return ip_set_eexist(ret, flags) ? 0 : ret; |
433 | } | 419 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 6033e8b54bbd..2cb84a54b7ad 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -174,6 +174,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
174 | struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; | 174 | struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; |
175 | u32 ip, ip_to, p, port, port_to; | 175 | u32 ip, ip_to, p, port, port_to; |
176 | u32 timeout = h->timeout; | 176 | u32 timeout = h->timeout; |
177 | bool with_ports = false; | ||
177 | int ret; | 178 | int ret; |
178 | 179 | ||
179 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 180 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -208,21 +209,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
208 | 209 | ||
209 | if (tb[IPSET_ATTR_PROTO]) { | 210 | if (tb[IPSET_ATTR_PROTO]) { |
210 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 211 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
212 | with_ports = ip_set_proto_with_ports(data.proto); | ||
211 | 213 | ||
212 | if (data.proto == 0) | 214 | if (data.proto == 0) |
213 | return -IPSET_ERR_INVALID_PROTO; | 215 | return -IPSET_ERR_INVALID_PROTO; |
214 | } else | 216 | } else |
215 | return -IPSET_ERR_MISSING_PROTO; | 217 | return -IPSET_ERR_MISSING_PROTO; |
216 | 218 | ||
217 | switch (data.proto) { | 219 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
218 | case IPPROTO_UDP: | ||
219 | case IPPROTO_TCP: | ||
220 | case IPPROTO_ICMP: | ||
221 | break; | ||
222 | default: | ||
223 | data.port = 0; | 220 | data.port = 0; |
224 | break; | ||
225 | } | ||
226 | 221 | ||
227 | if (tb[IPSET_ATTR_TIMEOUT]) { | 222 | if (tb[IPSET_ATTR_TIMEOUT]) { |
228 | if (!with_timeout(h->timeout)) | 223 | if (!with_timeout(h->timeout)) |
@@ -231,7 +226,6 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
231 | } | 226 | } |
232 | 227 | ||
233 | if (adt == IPSET_TEST || | 228 | if (adt == IPSET_TEST || |
234 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
235 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 229 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
236 | tb[IPSET_ATTR_PORT_TO])) { | 230 | tb[IPSET_ATTR_PORT_TO])) { |
237 | ret = adtfn(set, &data, timeout); | 231 | ret = adtfn(set, &data, timeout); |
@@ -255,13 +249,12 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
255 | } else | 249 | } else |
256 | ip_to = ip; | 250 | ip_to = ip; |
257 | 251 | ||
258 | port = ntohs(data.port); | 252 | port_to = port = ntohs(data.port); |
259 | if (tb[IPSET_ATTR_PORT_TO]) { | 253 | if (with_ports && tb[IPSET_ATTR_PORT_TO]) { |
260 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); | 254 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); |
261 | if (port > port_to) | 255 | if (port > port_to) |
262 | swap(port, port_to); | 256 | swap(port, port_to); |
263 | } else | 257 | } |
264 | port_to = port; | ||
265 | 258 | ||
266 | for (; !before(ip_to, ip); ip++) | 259 | for (; !before(ip_to, ip); ip++) |
267 | for (p = port; p <= port_to; p++) { | 260 | for (p = port; p <= port_to; p++) { |
@@ -429,6 +422,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
429 | struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; | 422 | struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; |
430 | u32 port, port_to; | 423 | u32 port, port_to; |
431 | u32 timeout = h->timeout; | 424 | u32 timeout = h->timeout; |
425 | bool with_ports = false; | ||
432 | int ret; | 426 | int ret; |
433 | 427 | ||
434 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 428 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -465,21 +459,15 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
465 | 459 | ||
466 | if (tb[IPSET_ATTR_PROTO]) { | 460 | if (tb[IPSET_ATTR_PROTO]) { |
467 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 461 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
462 | with_ports = ip_set_proto_with_ports(data.proto); | ||
468 | 463 | ||
469 | if (data.proto == 0) | 464 | if (data.proto == 0) |
470 | return -IPSET_ERR_INVALID_PROTO; | 465 | return -IPSET_ERR_INVALID_PROTO; |
471 | } else | 466 | } else |
472 | return -IPSET_ERR_MISSING_PROTO; | 467 | return -IPSET_ERR_MISSING_PROTO; |
473 | 468 | ||
474 | switch (data.proto) { | 469 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
475 | case IPPROTO_UDP: | ||
476 | case IPPROTO_TCP: | ||
477 | case IPPROTO_ICMPV6: | ||
478 | break; | ||
479 | default: | ||
480 | data.port = 0; | 470 | data.port = 0; |
481 | break; | ||
482 | } | ||
483 | 471 | ||
484 | if (tb[IPSET_ATTR_TIMEOUT]) { | 472 | if (tb[IPSET_ATTR_TIMEOUT]) { |
485 | if (!with_timeout(h->timeout)) | 473 | if (!with_timeout(h->timeout)) |
@@ -487,9 +475,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
487 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 475 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
488 | } | 476 | } |
489 | 477 | ||
490 | if (adt == IPSET_TEST || | 478 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
491 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
492 | !tb[IPSET_ATTR_PORT_TO]) { | ||
493 | ret = adtfn(set, &data, timeout); | 479 | ret = adtfn(set, &data, timeout); |
494 | return ip_set_eexist(ret, flags) ? 0 : ret; | 480 | return ip_set_eexist(ret, flags) ? 0 : ret; |
495 | } | 481 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 34a165626ee9..8598676f2a05 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -170,6 +170,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
170 | struct hash_netport4_elem data = { .cidr = HOST_MASK }; | 170 | struct hash_netport4_elem data = { .cidr = HOST_MASK }; |
171 | u32 port, port_to; | 171 | u32 port, port_to; |
172 | u32 timeout = h->timeout; | 172 | u32 timeout = h->timeout; |
173 | bool with_ports = false; | ||
173 | int ret; | 174 | int ret; |
174 | 175 | ||
175 | if (unlikely(!tb[IPSET_ATTR_IP] || | 176 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -198,21 +199,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
198 | 199 | ||
199 | if (tb[IPSET_ATTR_PROTO]) { | 200 | if (tb[IPSET_ATTR_PROTO]) { |
200 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 201 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
202 | with_ports = ip_set_proto_with_ports(data.proto); | ||
201 | 203 | ||
202 | if (data.proto == 0) | 204 | if (data.proto == 0) |
203 | return -IPSET_ERR_INVALID_PROTO; | 205 | return -IPSET_ERR_INVALID_PROTO; |
204 | } else | 206 | } else |
205 | return -IPSET_ERR_MISSING_PROTO; | 207 | return -IPSET_ERR_MISSING_PROTO; |
206 | 208 | ||
207 | switch (data.proto) { | 209 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
208 | case IPPROTO_UDP: | ||
209 | case IPPROTO_TCP: | ||
210 | case IPPROTO_ICMP: | ||
211 | break; | ||
212 | default: | ||
213 | data.port = 0; | 210 | data.port = 0; |
214 | break; | ||
215 | } | ||
216 | 211 | ||
217 | if (tb[IPSET_ATTR_TIMEOUT]) { | 212 | if (tb[IPSET_ATTR_TIMEOUT]) { |
218 | if (!with_timeout(h->timeout)) | 213 | if (!with_timeout(h->timeout)) |
@@ -220,9 +215,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
220 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 215 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
221 | } | 216 | } |
222 | 217 | ||
223 | if (adt == IPSET_TEST || | 218 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
224 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
225 | !tb[IPSET_ATTR_PORT_TO]) { | ||
226 | ret = adtfn(set, &data, timeout); | 219 | ret = adtfn(set, &data, timeout); |
227 | return ip_set_eexist(ret, flags) ? 0 : ret; | 220 | return ip_set_eexist(ret, flags) ? 0 : ret; |
228 | } | 221 | } |
@@ -390,6 +383,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
390 | struct hash_netport6_elem data = { .cidr = HOST_MASK }; | 383 | struct hash_netport6_elem data = { .cidr = HOST_MASK }; |
391 | u32 port, port_to; | 384 | u32 port, port_to; |
392 | u32 timeout = h->timeout; | 385 | u32 timeout = h->timeout; |
386 | bool with_ports = false; | ||
393 | int ret; | 387 | int ret; |
394 | 388 | ||
395 | if (unlikely(!tb[IPSET_ATTR_IP] || | 389 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -418,21 +412,15 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
418 | 412 | ||
419 | if (tb[IPSET_ATTR_PROTO]) { | 413 | if (tb[IPSET_ATTR_PROTO]) { |
420 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 414 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
415 | with_ports = ip_set_proto_with_ports(data.proto); | ||
421 | 416 | ||
422 | if (data.proto == 0) | 417 | if (data.proto == 0) |
423 | return -IPSET_ERR_INVALID_PROTO; | 418 | return -IPSET_ERR_INVALID_PROTO; |
424 | } else | 419 | } else |
425 | return -IPSET_ERR_MISSING_PROTO; | 420 | return -IPSET_ERR_MISSING_PROTO; |
426 | 421 | ||
427 | switch (data.proto) { | 422 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
428 | case IPPROTO_UDP: | ||
429 | case IPPROTO_TCP: | ||
430 | case IPPROTO_ICMPV6: | ||
431 | break; | ||
432 | default: | ||
433 | data.port = 0; | 423 | data.port = 0; |
434 | break; | ||
435 | } | ||
436 | 424 | ||
437 | if (tb[IPSET_ATTR_TIMEOUT]) { | 425 | if (tb[IPSET_ATTR_TIMEOUT]) { |
438 | if (!with_timeout(h->timeout)) | 426 | if (!with_timeout(h->timeout)) |
@@ -440,9 +428,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
440 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 428 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
441 | } | 429 | } |
442 | 430 | ||
443 | if (adt == IPSET_TEST || | 431 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
444 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
445 | !tb[IPSET_ATTR_PORT_TO]) { | ||
446 | ret = adtfn(set, &data, timeout); | 432 | ret = adtfn(set, &data, timeout); |
447 | return ip_set_eexist(ret, flags) ? 0 : ret; | 433 | return ip_set_eexist(ret, flags) ? 0 : ret; |
448 | } | 434 | } |
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 5c48ffb60c28..2dc6de13ac18 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
@@ -43,6 +43,8 @@ EXPORT_SYMBOL(register_ip_vs_app); | |||
43 | EXPORT_SYMBOL(unregister_ip_vs_app); | 43 | EXPORT_SYMBOL(unregister_ip_vs_app); |
44 | EXPORT_SYMBOL(register_ip_vs_app_inc); | 44 | EXPORT_SYMBOL(register_ip_vs_app_inc); |
45 | 45 | ||
46 | static DEFINE_MUTEX(__ip_vs_app_mutex); | ||
47 | |||
46 | /* | 48 | /* |
47 | * Get an ip_vs_app object | 49 | * Get an ip_vs_app object |
48 | */ | 50 | */ |
@@ -167,14 +169,13 @@ int | |||
167 | register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, | 169 | register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, |
168 | __u16 port) | 170 | __u16 port) |
169 | { | 171 | { |
170 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
171 | int result; | 172 | int result; |
172 | 173 | ||
173 | mutex_lock(&ipvs->app_mutex); | 174 | mutex_lock(&__ip_vs_app_mutex); |
174 | 175 | ||
175 | result = ip_vs_app_inc_new(net, app, proto, port); | 176 | result = ip_vs_app_inc_new(net, app, proto, port); |
176 | 177 | ||
177 | mutex_unlock(&ipvs->app_mutex); | 178 | mutex_unlock(&__ip_vs_app_mutex); |
178 | 179 | ||
179 | return result; | 180 | return result; |
180 | } | 181 | } |
@@ -189,11 +190,11 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
189 | /* increase the module use count */ | 190 | /* increase the module use count */ |
190 | ip_vs_use_count_inc(); | 191 | ip_vs_use_count_inc(); |
191 | 192 | ||
192 | mutex_lock(&ipvs->app_mutex); | 193 | mutex_lock(&__ip_vs_app_mutex); |
193 | 194 | ||
194 | list_add(&app->a_list, &ipvs->app_list); | 195 | list_add(&app->a_list, &ipvs->app_list); |
195 | 196 | ||
196 | mutex_unlock(&ipvs->app_mutex); | 197 | mutex_unlock(&__ip_vs_app_mutex); |
197 | 198 | ||
198 | return 0; | 199 | return 0; |
199 | } | 200 | } |
@@ -205,10 +206,9 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
205 | */ | 206 | */ |
206 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) | 207 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) |
207 | { | 208 | { |
208 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
209 | struct ip_vs_app *inc, *nxt; | 209 | struct ip_vs_app *inc, *nxt; |
210 | 210 | ||
211 | mutex_lock(&ipvs->app_mutex); | 211 | mutex_lock(&__ip_vs_app_mutex); |
212 | 212 | ||
213 | list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { | 213 | list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { |
214 | ip_vs_app_inc_release(net, inc); | 214 | ip_vs_app_inc_release(net, inc); |
@@ -216,7 +216,7 @@ void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
216 | 216 | ||
217 | list_del(&app->a_list); | 217 | list_del(&app->a_list); |
218 | 218 | ||
219 | mutex_unlock(&ipvs->app_mutex); | 219 | mutex_unlock(&__ip_vs_app_mutex); |
220 | 220 | ||
221 | /* decrease the module use count */ | 221 | /* decrease the module use count */ |
222 | ip_vs_use_count_dec(); | 222 | ip_vs_use_count_dec(); |
@@ -501,7 +501,7 @@ static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos) | |||
501 | struct net *net = seq_file_net(seq); | 501 | struct net *net = seq_file_net(seq); |
502 | struct netns_ipvs *ipvs = net_ipvs(net); | 502 | struct netns_ipvs *ipvs = net_ipvs(net); |
503 | 503 | ||
504 | mutex_lock(&ipvs->app_mutex); | 504 | mutex_lock(&__ip_vs_app_mutex); |
505 | 505 | ||
506 | return *pos ? ip_vs_app_idx(ipvs, *pos - 1) : SEQ_START_TOKEN; | 506 | return *pos ? ip_vs_app_idx(ipvs, *pos - 1) : SEQ_START_TOKEN; |
507 | } | 507 | } |
@@ -535,9 +535,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
535 | 535 | ||
536 | static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) | 536 | static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) |
537 | { | 537 | { |
538 | struct netns_ipvs *ipvs = net_ipvs(seq_file_net(seq)); | 538 | mutex_unlock(&__ip_vs_app_mutex); |
539 | |||
540 | mutex_unlock(&ipvs->app_mutex); | ||
541 | } | 539 | } |
542 | 540 | ||
543 | static int ip_vs_app_seq_show(struct seq_file *seq, void *v) | 541 | static int ip_vs_app_seq_show(struct seq_file *seq, void *v) |
@@ -583,7 +581,6 @@ static int __net_init __ip_vs_app_init(struct net *net) | |||
583 | struct netns_ipvs *ipvs = net_ipvs(net); | 581 | struct netns_ipvs *ipvs = net_ipvs(net); |
584 | 582 | ||
585 | INIT_LIST_HEAD(&ipvs->app_list); | 583 | INIT_LIST_HEAD(&ipvs->app_list); |
586 | __mutex_init(&ipvs->app_mutex, "ipvs->app_mutex", &ipvs->app_key); | ||
587 | proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops); | 584 | proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops); |
588 | return 0; | 585 | return 0; |
589 | } | 586 | } |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index b799cea31f95..33733c8872e7 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -3605,7 +3605,7 @@ int __net_init __ip_vs_control_init(struct net *net) | |||
3605 | 3605 | ||
3606 | /* procfs stats */ | 3606 | /* procfs stats */ |
3607 | ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); | 3607 | ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); |
3608 | if (ipvs->tot_stats.cpustats) { | 3608 | if (!ipvs->tot_stats.cpustats) { |
3609 | pr_err("%s(): alloc_percpu.\n", __func__); | 3609 | pr_err("%s(): alloc_percpu.\n", __func__); |
3610 | return -ENOMEM; | 3610 | return -ENOMEM; |
3611 | } | 3611 | } |
diff --git a/net/socket.c b/net/socket.c index 937d0fcf74bc..5212447c86e7 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2588,23 +2588,123 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | |||
2588 | 2588 | ||
2589 | static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | 2589 | static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) |
2590 | { | 2590 | { |
2591 | struct compat_ethtool_rxnfc __user *compat_rxnfc; | ||
2592 | bool convert_in = false, convert_out = false; | ||
2593 | size_t buf_size = ALIGN(sizeof(struct ifreq), 8); | ||
2594 | struct ethtool_rxnfc __user *rxnfc; | ||
2591 | struct ifreq __user *ifr; | 2595 | struct ifreq __user *ifr; |
2596 | u32 rule_cnt = 0, actual_rule_cnt; | ||
2597 | u32 ethcmd; | ||
2592 | u32 data; | 2598 | u32 data; |
2593 | void __user *datap; | 2599 | int ret; |
2600 | |||
2601 | if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | ||
2602 | return -EFAULT; | ||
2594 | 2603 | ||
2595 | ifr = compat_alloc_user_space(sizeof(*ifr)); | 2604 | compat_rxnfc = compat_ptr(data); |
2596 | 2605 | ||
2597 | if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | 2606 | if (get_user(ethcmd, &compat_rxnfc->cmd)) |
2598 | return -EFAULT; | 2607 | return -EFAULT; |
2599 | 2608 | ||
2600 | if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | 2609 | /* Most ethtool structures are defined without padding. |
2610 | * Unfortunately struct ethtool_rxnfc is an exception. | ||
2611 | */ | ||
2612 | switch (ethcmd) { | ||
2613 | default: | ||
2614 | break; | ||
2615 | case ETHTOOL_GRXCLSRLALL: | ||
2616 | /* Buffer size is variable */ | ||
2617 | if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) | ||
2618 | return -EFAULT; | ||
2619 | if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) | ||
2620 | return -ENOMEM; | ||
2621 | buf_size += rule_cnt * sizeof(u32); | ||
2622 | /* fall through */ | ||
2623 | case ETHTOOL_GRXRINGS: | ||
2624 | case ETHTOOL_GRXCLSRLCNT: | ||
2625 | case ETHTOOL_GRXCLSRULE: | ||
2626 | convert_out = true; | ||
2627 | /* fall through */ | ||
2628 | case ETHTOOL_SRXCLSRLDEL: | ||
2629 | case ETHTOOL_SRXCLSRLINS: | ||
2630 | buf_size += sizeof(struct ethtool_rxnfc); | ||
2631 | convert_in = true; | ||
2632 | break; | ||
2633 | } | ||
2634 | |||
2635 | ifr = compat_alloc_user_space(buf_size); | ||
2636 | rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8); | ||
2637 | |||
2638 | if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | ||
2601 | return -EFAULT; | 2639 | return -EFAULT; |
2602 | 2640 | ||
2603 | datap = compat_ptr(data); | 2641 | if (put_user(convert_in ? rxnfc : compat_ptr(data), |
2604 | if (put_user(datap, &ifr->ifr_ifru.ifru_data)) | 2642 | &ifr->ifr_ifru.ifru_data)) |
2605 | return -EFAULT; | 2643 | return -EFAULT; |
2606 | 2644 | ||
2607 | return dev_ioctl(net, SIOCETHTOOL, ifr); | 2645 | if (convert_in) { |
2646 | /* We expect there to be holes between fs.m_u and | ||
2647 | * fs.ring_cookie and at the end of fs, but nowhere else. | ||
2648 | */ | ||
2649 | BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) + | ||
2650 | sizeof(compat_rxnfc->fs.m_u) != | ||
2651 | offsetof(struct ethtool_rxnfc, fs.m_u) + | ||
2652 | sizeof(rxnfc->fs.m_u)); | ||
2653 | BUILD_BUG_ON( | ||
2654 | offsetof(struct compat_ethtool_rxnfc, fs.location) - | ||
2655 | offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != | ||
2656 | offsetof(struct ethtool_rxnfc, fs.location) - | ||
2657 | offsetof(struct ethtool_rxnfc, fs.ring_cookie)); | ||
2658 | |||
2659 | if (copy_in_user(rxnfc, compat_rxnfc, | ||
2660 | (void *)(&rxnfc->fs.m_u + 1) - | ||
2661 | (void *)rxnfc) || | ||
2662 | copy_in_user(&rxnfc->fs.ring_cookie, | ||
2663 | &compat_rxnfc->fs.ring_cookie, | ||
2664 | (void *)(&rxnfc->fs.location + 1) - | ||
2665 | (void *)&rxnfc->fs.ring_cookie) || | ||
2666 | copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, | ||
2667 | sizeof(rxnfc->rule_cnt))) | ||
2668 | return -EFAULT; | ||
2669 | } | ||
2670 | |||
2671 | ret = dev_ioctl(net, SIOCETHTOOL, ifr); | ||
2672 | if (ret) | ||
2673 | return ret; | ||
2674 | |||
2675 | if (convert_out) { | ||
2676 | if (copy_in_user(compat_rxnfc, rxnfc, | ||
2677 | (const void *)(&rxnfc->fs.m_u + 1) - | ||
2678 | (const void *)rxnfc) || | ||
2679 | copy_in_user(&compat_rxnfc->fs.ring_cookie, | ||
2680 | &rxnfc->fs.ring_cookie, | ||
2681 | (const void *)(&rxnfc->fs.location + 1) - | ||
2682 | (const void *)&rxnfc->fs.ring_cookie) || | ||
2683 | copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, | ||
2684 | sizeof(rxnfc->rule_cnt))) | ||
2685 | return -EFAULT; | ||
2686 | |||
2687 | if (ethcmd == ETHTOOL_GRXCLSRLALL) { | ||
2688 | /* As an optimisation, we only copy the actual | ||
2689 | * number of rules that the underlying | ||
2690 | * function returned. Since Mallory might | ||
2691 | * change the rule count in user memory, we | ||
2692 | * check that it is less than the rule count | ||
2693 | * originally given (as the user buffer size), | ||
2694 | * which has been range-checked. | ||
2695 | */ | ||
2696 | if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) | ||
2697 | return -EFAULT; | ||
2698 | if (actual_rule_cnt < rule_cnt) | ||
2699 | rule_cnt = actual_rule_cnt; | ||
2700 | if (copy_in_user(&compat_rxnfc->rule_locs[0], | ||
2701 | &rxnfc->rule_locs[0], | ||
2702 | rule_cnt * sizeof(u32))) | ||
2703 | return -EFAULT; | ||
2704 | } | ||
2705 | } | ||
2706 | |||
2707 | return 0; | ||
2608 | } | 2708 | } |
2609 | 2709 | ||
2610 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) | 2710 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index d575f0534868..f83a3d1da81b 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1907,7 +1907,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
1907 | return res; | 1907 | return res; |
1908 | } | 1908 | } |
1909 | 1909 | ||
1910 | int xfrm_init_state(struct xfrm_state *x) | 1910 | int __xfrm_init_state(struct xfrm_state *x, bool init_replay) |
1911 | { | 1911 | { |
1912 | struct xfrm_state_afinfo *afinfo; | 1912 | struct xfrm_state_afinfo *afinfo; |
1913 | struct xfrm_mode *inner_mode; | 1913 | struct xfrm_mode *inner_mode; |
@@ -1980,12 +1980,25 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1980 | if (x->outer_mode == NULL) | 1980 | if (x->outer_mode == NULL) |
1981 | goto error; | 1981 | goto error; |
1982 | 1982 | ||
1983 | if (init_replay) { | ||
1984 | err = xfrm_init_replay(x); | ||
1985 | if (err) | ||
1986 | goto error; | ||
1987 | } | ||
1988 | |||
1983 | x->km.state = XFRM_STATE_VALID; | 1989 | x->km.state = XFRM_STATE_VALID; |
1984 | 1990 | ||
1985 | error: | 1991 | error: |
1986 | return err; | 1992 | return err; |
1987 | } | 1993 | } |
1988 | 1994 | ||
1995 | EXPORT_SYMBOL(__xfrm_init_state); | ||
1996 | |||
1997 | int xfrm_init_state(struct xfrm_state *x) | ||
1998 | { | ||
1999 | return __xfrm_init_state(x, true); | ||
2000 | } | ||
2001 | |||
1989 | EXPORT_SYMBOL(xfrm_init_state); | 2002 | EXPORT_SYMBOL(xfrm_init_state); |
1990 | 2003 | ||
1991 | int __net_init xfrm_state_init(struct net *net) | 2004 | int __net_init xfrm_state_init(struct net *net) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 706385ae3e4b..fc152d28753c 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -511,7 +511,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, | |||
511 | 511 | ||
512 | xfrm_mark_get(attrs, &x->mark); | 512 | xfrm_mark_get(attrs, &x->mark); |
513 | 513 | ||
514 | err = xfrm_init_state(x); | 514 | err = __xfrm_init_state(x, false); |
515 | if (err) | 515 | if (err) |
516 | goto error; | 516 | goto error; |
517 | 517 | ||