diff options
author | David S. Miller <davem@davemloft.net> | 2011-10-24 18:18:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-24 18:18:09 -0400 |
commit | 1805b2f04855f07afe3a71d620a68f483b0ed74f (patch) | |
tree | b823b90f37f5404fcaef70f785c70112ca74a329 /net | |
parent | 78d81d15b74246c7cedf84894434890b33da3907 (diff) | |
parent | f42af6c486aa5ca6ee62800cb45c5b252020509d (diff) |
Merge branch 'master' of ra.kernel.org:/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net')
-rw-r--r-- | net/batman-adv/translation-table.c | 7 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 4 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 3 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 5 | ||||
-rw-r--r-- | net/bridge/br_if.c | 9 | ||||
-rw-r--r-- | net/bridge/br_netlink.c | 1 | ||||
-rw-r--r-- | net/bridge/br_private.h | 1 | ||||
-rw-r--r-- | net/core/dev.c | 1 | ||||
-rw-r--r-- | net/core/fib_rules.c | 5 | ||||
-rw-r--r-- | net/core/timestamping.c | 12 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 2 | ||||
-rw-r--r-- | net/ipv4/route.c | 36 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 1 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 14 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 1 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 131 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 6 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 4 | ||||
-rw-r--r-- | net/x25/af_x25.c | 40 | ||||
-rw-r--r-- | net/x25/x25_dev.c | 6 | ||||
-rw-r--r-- | net/x25/x25_facilities.c | 10 | ||||
-rw-r--r-- | net/x25/x25_in.c | 43 | ||||
-rw-r--r-- | net/x25/x25_link.c | 3 | ||||
-rw-r--r-- | net/x25/x25_subr.c | 14 |
25 files changed, 268 insertions, 95 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index cc53f78e448c..873fb3d8e56f 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -1049,7 +1049,6 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, | |||
1049 | tt_response = (struct tt_query_packet *)skb_put(skb, | 1049 | tt_response = (struct tt_query_packet *)skb_put(skb, |
1050 | tt_query_size + tt_len); | 1050 | tt_query_size + tt_len); |
1051 | tt_response->ttvn = ttvn; | 1051 | tt_response->ttvn = ttvn; |
1052 | tt_response->tt_data = htons(tt_tot); | ||
1053 | 1052 | ||
1054 | tt_change = (struct tt_change *)(skb->data + tt_query_size); | 1053 | tt_change = (struct tt_change *)(skb->data + tt_query_size); |
1055 | tt_count = 0; | 1054 | tt_count = 0; |
@@ -1075,6 +1074,10 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, | |||
1075 | } | 1074 | } |
1076 | rcu_read_unlock(); | 1075 | rcu_read_unlock(); |
1077 | 1076 | ||
1077 | /* store in the message the number of entries we have successfully | ||
1078 | * copied */ | ||
1079 | tt_response->tt_data = htons(tt_count); | ||
1080 | |||
1078 | out: | 1081 | out: |
1079 | return skb; | 1082 | return skb; |
1080 | } | 1083 | } |
@@ -1722,6 +1725,8 @@ static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags) | |||
1722 | rcu_read_lock(); | 1725 | rcu_read_lock(); |
1723 | hlist_for_each_entry_rcu(tt_local_entry, node, | 1726 | hlist_for_each_entry_rcu(tt_local_entry, node, |
1724 | head, hash_entry) { | 1727 | head, hash_entry) { |
1728 | if (!(tt_local_entry->flags & flags)) | ||
1729 | continue; | ||
1725 | tt_local_entry->flags &= ~flags; | 1730 | tt_local_entry->flags &= ~flags; |
1726 | atomic_inc(&bat_priv->num_local_tt); | 1731 | atomic_inc(&bat_priv->num_local_tt); |
1727 | } | 1732 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 61f1f623091d..e8292369cdcf 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -26,6 +26,8 @@ | |||
26 | 26 | ||
27 | /* Bluetooth L2CAP sockets. */ | 27 | /* Bluetooth L2CAP sockets. */ |
28 | 28 | ||
29 | #include <linux/security.h> | ||
30 | |||
29 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
30 | #include <net/bluetooth/hci_core.h> | 32 | #include <net/bluetooth/hci_core.h> |
31 | #include <net/bluetooth/l2cap.h> | 33 | #include <net/bluetooth/l2cap.h> |
@@ -933,6 +935,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
933 | chan->force_reliable = pchan->force_reliable; | 935 | chan->force_reliable = pchan->force_reliable; |
934 | chan->flushable = pchan->flushable; | 936 | chan->flushable = pchan->flushable; |
935 | chan->force_active = pchan->force_active; | 937 | chan->force_active = pchan->force_active; |
938 | |||
939 | security_sk_clone(parent, sk); | ||
936 | } else { | 940 | } else { |
937 | 941 | ||
938 | switch (sk->sk_type) { | 942 | switch (sk->sk_type) { |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 482722bbc7a0..5417f6127323 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/device.h> | 42 | #include <linux/device.h> |
43 | #include <linux/debugfs.h> | 43 | #include <linux/debugfs.h> |
44 | #include <linux/seq_file.h> | 44 | #include <linux/seq_file.h> |
45 | #include <linux/security.h> | ||
45 | #include <net/sock.h> | 46 | #include <net/sock.h> |
46 | 47 | ||
47 | #include <asm/system.h> | 48 | #include <asm/system.h> |
@@ -264,6 +265,8 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent) | |||
264 | 265 | ||
265 | pi->sec_level = rfcomm_pi(parent)->sec_level; | 266 | pi->sec_level = rfcomm_pi(parent)->sec_level; |
266 | pi->role_switch = rfcomm_pi(parent)->role_switch; | 267 | pi->role_switch = rfcomm_pi(parent)->role_switch; |
268 | |||
269 | security_sk_clone(parent, sk); | ||
267 | } else { | 270 | } else { |
268 | pi->dlc->defer_setup = 0; | 271 | pi->dlc->defer_setup = 0; |
269 | 272 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8270f05e3f1f..a324b009e34b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/debugfs.h> | 41 | #include <linux/debugfs.h> |
42 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
43 | #include <linux/list.h> | 43 | #include <linux/list.h> |
44 | #include <linux/security.h> | ||
44 | #include <net/sock.h> | 45 | #include <net/sock.h> |
45 | 46 | ||
46 | #include <asm/system.h> | 47 | #include <asm/system.h> |
@@ -403,8 +404,10 @@ static void sco_sock_init(struct sock *sk, struct sock *parent) | |||
403 | { | 404 | { |
404 | BT_DBG("sk %p", sk); | 405 | BT_DBG("sk %p", sk); |
405 | 406 | ||
406 | if (parent) | 407 | if (parent) { |
407 | sk->sk_type = parent->sk_type; | 408 | sk->sk_type = parent->sk_type; |
409 | security_sk_clone(parent, sk); | ||
410 | } | ||
408 | } | 411 | } |
409 | 412 | ||
410 | static struct proto sco_proto = { | 413 | static struct proto sco_proto = { |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index c3b77dceb937..f603e5b0b930 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -160,9 +160,10 @@ static void del_nbp(struct net_bridge_port *p) | |||
160 | call_rcu(&p->rcu, destroy_nbp_rcu); | 160 | call_rcu(&p->rcu, destroy_nbp_rcu); |
161 | } | 161 | } |
162 | 162 | ||
163 | /* called with RTNL */ | 163 | /* Delete bridge device */ |
164 | static void del_br(struct net_bridge *br, struct list_head *head) | 164 | void br_dev_delete(struct net_device *dev, struct list_head *head) |
165 | { | 165 | { |
166 | struct net_bridge *br = netdev_priv(dev); | ||
166 | struct net_bridge_port *p, *n; | 167 | struct net_bridge_port *p, *n; |
167 | 168 | ||
168 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 169 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
@@ -267,7 +268,7 @@ int br_del_bridge(struct net *net, const char *name) | |||
267 | } | 268 | } |
268 | 269 | ||
269 | else | 270 | else |
270 | del_br(netdev_priv(dev), NULL); | 271 | br_dev_delete(dev, NULL); |
271 | 272 | ||
272 | rtnl_unlock(); | 273 | rtnl_unlock(); |
273 | return ret; | 274 | return ret; |
@@ -446,7 +447,7 @@ void __net_exit br_net_exit(struct net *net) | |||
446 | rtnl_lock(); | 447 | rtnl_lock(); |
447 | for_each_netdev(net, dev) | 448 | for_each_netdev(net, dev) |
448 | if (dev->priv_flags & IFF_EBRIDGE) | 449 | if (dev->priv_flags & IFF_EBRIDGE) |
449 | del_br(netdev_priv(dev), &list); | 450 | br_dev_delete(dev, &list); |
450 | 451 | ||
451 | unregister_netdevice_many(&list); | 452 | unregister_netdevice_many(&list); |
452 | rtnl_unlock(); | 453 | rtnl_unlock(); |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 5b1ed1ba9aa7..e5f9ece3c9a0 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -210,6 +210,7 @@ static struct rtnl_link_ops br_link_ops __read_mostly = { | |||
210 | .priv_size = sizeof(struct net_bridge), | 210 | .priv_size = sizeof(struct net_bridge), |
211 | .setup = br_dev_setup, | 211 | .setup = br_dev_setup, |
212 | .validate = br_validate, | 212 | .validate = br_validate, |
213 | .dellink = br_dev_delete, | ||
213 | }; | 214 | }; |
214 | 215 | ||
215 | int __init br_netlink_init(void) | 216 | int __init br_netlink_init(void) |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a248fe65b29a..d7d6fb05411f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -301,6 +301,7 @@ static inline int br_is_root_bridge(const struct net_bridge *br) | |||
301 | 301 | ||
302 | /* br_device.c */ | 302 | /* br_device.c */ |
303 | extern void br_dev_setup(struct net_device *dev); | 303 | extern void br_dev_setup(struct net_device *dev); |
304 | extern void br_dev_delete(struct net_device *dev, struct list_head *list); | ||
304 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, | 305 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, |
305 | struct net_device *dev); | 306 | struct net_device *dev); |
306 | #ifdef CONFIG_NET_POLL_CONTROLLER | 307 | #ifdef CONFIG_NET_POLL_CONTROLLER |
diff --git a/net/core/dev.c b/net/core/dev.c index ad5d7027c545..b7ba81afc6f9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -6266,6 +6266,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6266 | */ | 6266 | */ |
6267 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); | 6267 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); |
6268 | call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); | 6268 | call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); |
6269 | rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); | ||
6269 | 6270 | ||
6270 | /* | 6271 | /* |
6271 | * Flush the unicast and multicast chains | 6272 | * Flush the unicast and multicast chains |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 38be4744133f..57e8f95110e6 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -475,8 +475,11 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
475 | 475 | ||
476 | list_del_rcu(&rule->list); | 476 | list_del_rcu(&rule->list); |
477 | 477 | ||
478 | if (rule->action == FR_ACT_GOTO) | 478 | if (rule->action == FR_ACT_GOTO) { |
479 | ops->nr_goto_rules--; | 479 | ops->nr_goto_rules--; |
480 | if (rtnl_dereference(rule->ctarget) == NULL) | ||
481 | ops->unresolved_rules--; | ||
482 | } | ||
480 | 483 | ||
481 | /* | 484 | /* |
482 | * Check if this rule is a target to any of them. If so, | 485 | * Check if this rule is a target to any of them. If so, |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 98a52640e7cd..82fb28857b64 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
@@ -57,9 +57,13 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
57 | case PTP_CLASS_V2_VLAN: | 57 | case PTP_CLASS_V2_VLAN: |
58 | phydev = skb->dev->phydev; | 58 | phydev = skb->dev->phydev; |
59 | if (likely(phydev->drv->txtstamp)) { | 59 | if (likely(phydev->drv->txtstamp)) { |
60 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
61 | return; | ||
60 | clone = skb_clone(skb, GFP_ATOMIC); | 62 | clone = skb_clone(skb, GFP_ATOMIC); |
61 | if (!clone) | 63 | if (!clone) { |
64 | sock_put(sk); | ||
62 | return; | 65 | return; |
66 | } | ||
63 | clone->sk = sk; | 67 | clone->sk = sk; |
64 | phydev->drv->txtstamp(phydev, clone, type); | 68 | phydev->drv->txtstamp(phydev, clone, type); |
65 | } | 69 | } |
@@ -77,8 +81,11 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
77 | struct sock_exterr_skb *serr; | 81 | struct sock_exterr_skb *serr; |
78 | int err; | 82 | int err; |
79 | 83 | ||
80 | if (!hwtstamps) | 84 | if (!hwtstamps) { |
85 | sock_put(sk); | ||
86 | kfree_skb(skb); | ||
81 | return; | 87 | return; |
88 | } | ||
82 | 89 | ||
83 | *skb_hwtstamps(skb) = *hwtstamps; | 90 | *skb_hwtstamps(skb) = *hwtstamps; |
84 | serr = SKB_EXT_ERR(skb); | 91 | serr = SKB_EXT_ERR(skb); |
@@ -87,6 +94,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
87 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 94 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
88 | skb->sk = NULL; | 95 | skb->sk = NULL; |
89 | err = sock_queue_err_skb(sk, skb); | 96 | err = sock_queue_err_skb(sk, skb); |
97 | sock_put(sk); | ||
90 | if (err) | 98 | if (err) |
91 | kfree_skb(skb); | 99 | kfree_skb(skb); |
92 | } | 100 | } |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d7bb94c48345..d55110e93120 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -835,8 +835,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
835 | if (skb_headroom(skb) < max_headroom || skb_shared(skb)|| | 835 | if (skb_headroom(skb) < max_headroom || skb_shared(skb)|| |
836 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { | 836 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { |
837 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 837 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
838 | if (max_headroom > dev->needed_headroom) | ||
839 | dev->needed_headroom = max_headroom; | ||
840 | if (!new_skb) { | 838 | if (!new_skb) { |
841 | ip_rt_put(rt); | 839 | ip_rt_put(rt); |
842 | dev->stats.tx_dropped++; | 840 | dev->stats.tx_dropped++; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 26c77e14395f..1082460daca7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1308,7 +1308,12 @@ static void rt_del(unsigned hash, struct rtable *rt) | |||
1308 | void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, | 1308 | void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, |
1309 | __be32 saddr, struct net_device *dev) | 1309 | __be32 saddr, struct net_device *dev) |
1310 | { | 1310 | { |
1311 | int s, i; | ||
1311 | struct in_device *in_dev = __in_dev_get_rcu(dev); | 1312 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
1313 | struct rtable *rt; | ||
1314 | __be32 skeys[2] = { saddr, 0 }; | ||
1315 | int ikeys[2] = { dev->ifindex, 0 }; | ||
1316 | struct flowi4 fl4; | ||
1312 | struct inet_peer *peer; | 1317 | struct inet_peer *peer; |
1313 | struct net *net; | 1318 | struct net *net; |
1314 | 1319 | ||
@@ -1331,13 +1336,34 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, | |||
1331 | goto reject_redirect; | 1336 | goto reject_redirect; |
1332 | } | 1337 | } |
1333 | 1338 | ||
1334 | peer = inet_getpeer_v4(daddr, 1); | 1339 | memset(&fl4, 0, sizeof(fl4)); |
1335 | if (peer) { | 1340 | fl4.daddr = daddr; |
1336 | peer->redirect_learned.a4 = new_gw; | 1341 | for (s = 0; s < 2; s++) { |
1342 | for (i = 0; i < 2; i++) { | ||
1343 | fl4.flowi4_oif = ikeys[i]; | ||
1344 | fl4.saddr = skeys[s]; | ||
1345 | rt = __ip_route_output_key(net, &fl4); | ||
1346 | if (IS_ERR(rt)) | ||
1347 | continue; | ||
1337 | 1348 | ||
1338 | inet_putpeer(peer); | 1349 | if (rt->dst.error || rt->dst.dev != dev || |
1350 | rt->rt_gateway != old_gw) { | ||
1351 | ip_rt_put(rt); | ||
1352 | continue; | ||
1353 | } | ||
1339 | 1354 | ||
1340 | atomic_inc(&__rt_peer_genid); | 1355 | if (!rt->peer) |
1356 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
1357 | |||
1358 | peer = rt->peer; | ||
1359 | if (peer) { | ||
1360 | peer->redirect_learned.a4 = new_gw; | ||
1361 | atomic_inc(&__rt_peer_genid); | ||
1362 | } | ||
1363 | |||
1364 | ip_rt_put(rt); | ||
1365 | return; | ||
1366 | } | ||
1341 | } | 1367 | } |
1342 | return; | 1368 | return; |
1343 | 1369 | ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index b767a951d47c..85a2fbebd7ef 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -328,6 +328,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
328 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); | 328 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); |
329 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); | 329 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); |
330 | 330 | ||
331 | tw->tw_transparent = inet_sk(sk)->transparent; | ||
331 | tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; | 332 | tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; |
332 | tcptw->tw_rcv_nxt = tp->rcv_nxt; | 333 | tcptw->tw_rcv_nxt = tp->rcv_nxt; |
333 | tcptw->tw_snd_nxt = tp->snd_nxt; | 334 | tcptw->tw_snd_nxt = tp->snd_nxt; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index fc5368ad2b0d..a0b4c5da8d43 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -79,13 +79,13 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
79 | struct rtable *rt = (struct rtable *)xdst->route; | 79 | struct rtable *rt = (struct rtable *)xdst->route; |
80 | const struct flowi4 *fl4 = &fl->u.ip4; | 80 | const struct flowi4 *fl4 = &fl->u.ip4; |
81 | 81 | ||
82 | rt->rt_key_dst = fl4->daddr; | 82 | xdst->u.rt.rt_key_dst = fl4->daddr; |
83 | rt->rt_key_src = fl4->saddr; | 83 | xdst->u.rt.rt_key_src = fl4->saddr; |
84 | rt->rt_key_tos = fl4->flowi4_tos; | 84 | xdst->u.rt.rt_key_tos = fl4->flowi4_tos; |
85 | rt->rt_route_iif = fl4->flowi4_iif; | 85 | xdst->u.rt.rt_route_iif = fl4->flowi4_iif; |
86 | rt->rt_iif = fl4->flowi4_iif; | 86 | xdst->u.rt.rt_iif = fl4->flowi4_iif; |
87 | rt->rt_oif = fl4->flowi4_oif; | 87 | xdst->u.rt.rt_oif = fl4->flowi4_oif; |
88 | rt->rt_mark = fl4->flowi4_mark; | 88 | xdst->u.rt.rt_mark = fl4->flowi4_mark; |
89 | 89 | ||
90 | xdst->u.dst.dev = dev; | 90 | xdst->u.dst.dev = dev; |
91 | dev_hold(dev); | 91 | dev_hold(dev); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3b5669a2582d..d27c797f9f05 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -875,6 +875,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
875 | skb_reset_transport_header(skb); | 875 | skb_reset_transport_header(skb); |
876 | __skb_push(skb, skb_gro_offset(skb)); | 876 | __skb_push(skb, skb_gro_offset(skb)); |
877 | 877 | ||
878 | ops = rcu_dereference(inet6_protos[proto]); | ||
878 | if (!ops || !ops->gro_receive) | 879 | if (!ops || !ops->gro_receive) |
879 | goto out_unlock; | 880 | goto out_unlock; |
880 | 881 | ||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index ad4ac2601a56..34b2ddeacb67 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -1045,8 +1045,10 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1045 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + | 1045 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + |
1046 | uhlen + hdr_len; | 1046 | uhlen + hdr_len; |
1047 | old_headroom = skb_headroom(skb); | 1047 | old_headroom = skb_headroom(skb); |
1048 | if (skb_cow_head(skb, headroom)) | 1048 | if (skb_cow_head(skb, headroom)) { |
1049 | dev_kfree_skb(skb); | ||
1049 | goto abort; | 1050 | goto abort; |
1051 | } | ||
1050 | 1052 | ||
1051 | new_headroom = skb_headroom(skb); | 1053 | new_headroom = skb_headroom(skb); |
1052 | skb_orphan(skb); | 1054 | skb_orphan(skb); |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 5290ac353a5e..e3be48bf4dcd 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -2283,6 +2283,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2283 | struct ip_vs_service *svc; | 2283 | struct ip_vs_service *svc; |
2284 | struct ip_vs_dest_user *udest_compat; | 2284 | struct ip_vs_dest_user *udest_compat; |
2285 | struct ip_vs_dest_user_kern udest; | 2285 | struct ip_vs_dest_user_kern udest; |
2286 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
2286 | 2287 | ||
2287 | if (!capable(CAP_NET_ADMIN)) | 2288 | if (!capable(CAP_NET_ADMIN)) |
2288 | return -EPERM; | 2289 | return -EPERM; |
@@ -2303,6 +2304,24 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2303 | /* increase the module use count */ | 2304 | /* increase the module use count */ |
2304 | ip_vs_use_count_inc(); | 2305 | ip_vs_use_count_inc(); |
2305 | 2306 | ||
2307 | /* Handle daemons since they have another lock */ | ||
2308 | if (cmd == IP_VS_SO_SET_STARTDAEMON || | ||
2309 | cmd == IP_VS_SO_SET_STOPDAEMON) { | ||
2310 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | ||
2311 | |||
2312 | if (mutex_lock_interruptible(&ipvs->sync_mutex)) { | ||
2313 | ret = -ERESTARTSYS; | ||
2314 | goto out_dec; | ||
2315 | } | ||
2316 | if (cmd == IP_VS_SO_SET_STARTDAEMON) | ||
2317 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, | ||
2318 | dm->syncid); | ||
2319 | else | ||
2320 | ret = stop_sync_thread(net, dm->state); | ||
2321 | mutex_unlock(&ipvs->sync_mutex); | ||
2322 | goto out_dec; | ||
2323 | } | ||
2324 | |||
2306 | if (mutex_lock_interruptible(&__ip_vs_mutex)) { | 2325 | if (mutex_lock_interruptible(&__ip_vs_mutex)) { |
2307 | ret = -ERESTARTSYS; | 2326 | ret = -ERESTARTSYS; |
2308 | goto out_dec; | 2327 | goto out_dec; |
@@ -2316,15 +2335,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2316 | /* Set timeout values for (tcp tcpfin udp) */ | 2335 | /* Set timeout values for (tcp tcpfin udp) */ |
2317 | ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg); | 2336 | ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg); |
2318 | goto out_unlock; | 2337 | goto out_unlock; |
2319 | } else if (cmd == IP_VS_SO_SET_STARTDAEMON) { | ||
2320 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | ||
2321 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, | ||
2322 | dm->syncid); | ||
2323 | goto out_unlock; | ||
2324 | } else if (cmd == IP_VS_SO_SET_STOPDAEMON) { | ||
2325 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | ||
2326 | ret = stop_sync_thread(net, dm->state); | ||
2327 | goto out_unlock; | ||
2328 | } | 2338 | } |
2329 | 2339 | ||
2330 | usvc_compat = (struct ip_vs_service_user *)arg; | 2340 | usvc_compat = (struct ip_vs_service_user *)arg; |
@@ -2584,6 +2594,33 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2584 | 2594 | ||
2585 | if (copy_from_user(arg, user, copylen) != 0) | 2595 | if (copy_from_user(arg, user, copylen) != 0) |
2586 | return -EFAULT; | 2596 | return -EFAULT; |
2597 | /* | ||
2598 | * Handle daemons first since it has its own locking | ||
2599 | */ | ||
2600 | if (cmd == IP_VS_SO_GET_DAEMON) { | ||
2601 | struct ip_vs_daemon_user d[2]; | ||
2602 | |||
2603 | memset(&d, 0, sizeof(d)); | ||
2604 | if (mutex_lock_interruptible(&ipvs->sync_mutex)) | ||
2605 | return -ERESTARTSYS; | ||
2606 | |||
2607 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { | ||
2608 | d[0].state = IP_VS_STATE_MASTER; | ||
2609 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, | ||
2610 | sizeof(d[0].mcast_ifn)); | ||
2611 | d[0].syncid = ipvs->master_syncid; | ||
2612 | } | ||
2613 | if (ipvs->sync_state & IP_VS_STATE_BACKUP) { | ||
2614 | d[1].state = IP_VS_STATE_BACKUP; | ||
2615 | strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn, | ||
2616 | sizeof(d[1].mcast_ifn)); | ||
2617 | d[1].syncid = ipvs->backup_syncid; | ||
2618 | } | ||
2619 | if (copy_to_user(user, &d, sizeof(d)) != 0) | ||
2620 | ret = -EFAULT; | ||
2621 | mutex_unlock(&ipvs->sync_mutex); | ||
2622 | return ret; | ||
2623 | } | ||
2587 | 2624 | ||
2588 | if (mutex_lock_interruptible(&__ip_vs_mutex)) | 2625 | if (mutex_lock_interruptible(&__ip_vs_mutex)) |
2589 | return -ERESTARTSYS; | 2626 | return -ERESTARTSYS; |
@@ -2681,28 +2718,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2681 | } | 2718 | } |
2682 | break; | 2719 | break; |
2683 | 2720 | ||
2684 | case IP_VS_SO_GET_DAEMON: | ||
2685 | { | ||
2686 | struct ip_vs_daemon_user d[2]; | ||
2687 | |||
2688 | memset(&d, 0, sizeof(d)); | ||
2689 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { | ||
2690 | d[0].state = IP_VS_STATE_MASTER; | ||
2691 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, | ||
2692 | sizeof(d[0].mcast_ifn)); | ||
2693 | d[0].syncid = ipvs->master_syncid; | ||
2694 | } | ||
2695 | if (ipvs->sync_state & IP_VS_STATE_BACKUP) { | ||
2696 | d[1].state = IP_VS_STATE_BACKUP; | ||
2697 | strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn, | ||
2698 | sizeof(d[1].mcast_ifn)); | ||
2699 | d[1].syncid = ipvs->backup_syncid; | ||
2700 | } | ||
2701 | if (copy_to_user(user, &d, sizeof(d)) != 0) | ||
2702 | ret = -EFAULT; | ||
2703 | } | ||
2704 | break; | ||
2705 | |||
2706 | default: | 2721 | default: |
2707 | ret = -EINVAL; | 2722 | ret = -EINVAL; |
2708 | } | 2723 | } |
@@ -3205,7 +3220,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | |||
3205 | struct net *net = skb_sknet(skb); | 3220 | struct net *net = skb_sknet(skb); |
3206 | struct netns_ipvs *ipvs = net_ipvs(net); | 3221 | struct netns_ipvs *ipvs = net_ipvs(net); |
3207 | 3222 | ||
3208 | mutex_lock(&__ip_vs_mutex); | 3223 | mutex_lock(&ipvs->sync_mutex); |
3209 | if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { | 3224 | if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { |
3210 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, | 3225 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, |
3211 | ipvs->master_mcast_ifn, | 3226 | ipvs->master_mcast_ifn, |
@@ -3225,7 +3240,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | |||
3225 | } | 3240 | } |
3226 | 3241 | ||
3227 | nla_put_failure: | 3242 | nla_put_failure: |
3228 | mutex_unlock(&__ip_vs_mutex); | 3243 | mutex_unlock(&ipvs->sync_mutex); |
3229 | 3244 | ||
3230 | return skb->len; | 3245 | return skb->len; |
3231 | } | 3246 | } |
@@ -3271,13 +3286,9 @@ static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs) | |||
3271 | return ip_vs_set_timeout(net, &t); | 3286 | return ip_vs_set_timeout(net, &t); |
3272 | } | 3287 | } |
3273 | 3288 | ||
3274 | static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | 3289 | static int ip_vs_genl_set_daemon(struct sk_buff *skb, struct genl_info *info) |
3275 | { | 3290 | { |
3276 | struct ip_vs_service *svc = NULL; | ||
3277 | struct ip_vs_service_user_kern usvc; | ||
3278 | struct ip_vs_dest_user_kern udest; | ||
3279 | int ret = 0, cmd; | 3291 | int ret = 0, cmd; |
3280 | int need_full_svc = 0, need_full_dest = 0; | ||
3281 | struct net *net; | 3292 | struct net *net; |
3282 | struct netns_ipvs *ipvs; | 3293 | struct netns_ipvs *ipvs; |
3283 | 3294 | ||
@@ -3285,19 +3296,10 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3285 | ipvs = net_ipvs(net); | 3296 | ipvs = net_ipvs(net); |
3286 | cmd = info->genlhdr->cmd; | 3297 | cmd = info->genlhdr->cmd; |
3287 | 3298 | ||
3288 | mutex_lock(&__ip_vs_mutex); | 3299 | if (cmd == IPVS_CMD_NEW_DAEMON || cmd == IPVS_CMD_DEL_DAEMON) { |
3289 | |||
3290 | if (cmd == IPVS_CMD_FLUSH) { | ||
3291 | ret = ip_vs_flush(net); | ||
3292 | goto out; | ||
3293 | } else if (cmd == IPVS_CMD_SET_CONFIG) { | ||
3294 | ret = ip_vs_genl_set_config(net, info->attrs); | ||
3295 | goto out; | ||
3296 | } else if (cmd == IPVS_CMD_NEW_DAEMON || | ||
3297 | cmd == IPVS_CMD_DEL_DAEMON) { | ||
3298 | |||
3299 | struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1]; | 3300 | struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1]; |
3300 | 3301 | ||
3302 | mutex_lock(&ipvs->sync_mutex); | ||
3301 | if (!info->attrs[IPVS_CMD_ATTR_DAEMON] || | 3303 | if (!info->attrs[IPVS_CMD_ATTR_DAEMON] || |
3302 | nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX, | 3304 | nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX, |
3303 | info->attrs[IPVS_CMD_ATTR_DAEMON], | 3305 | info->attrs[IPVS_CMD_ATTR_DAEMON], |
@@ -3310,6 +3312,33 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3310 | ret = ip_vs_genl_new_daemon(net, daemon_attrs); | 3312 | ret = ip_vs_genl_new_daemon(net, daemon_attrs); |
3311 | else | 3313 | else |
3312 | ret = ip_vs_genl_del_daemon(net, daemon_attrs); | 3314 | ret = ip_vs_genl_del_daemon(net, daemon_attrs); |
3315 | out: | ||
3316 | mutex_unlock(&ipvs->sync_mutex); | ||
3317 | } | ||
3318 | return ret; | ||
3319 | } | ||
3320 | |||
3321 | static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | ||
3322 | { | ||
3323 | struct ip_vs_service *svc = NULL; | ||
3324 | struct ip_vs_service_user_kern usvc; | ||
3325 | struct ip_vs_dest_user_kern udest; | ||
3326 | int ret = 0, cmd; | ||
3327 | int need_full_svc = 0, need_full_dest = 0; | ||
3328 | struct net *net; | ||
3329 | struct netns_ipvs *ipvs; | ||
3330 | |||
3331 | net = skb_sknet(skb); | ||
3332 | ipvs = net_ipvs(net); | ||
3333 | cmd = info->genlhdr->cmd; | ||
3334 | |||
3335 | mutex_lock(&__ip_vs_mutex); | ||
3336 | |||
3337 | if (cmd == IPVS_CMD_FLUSH) { | ||
3338 | ret = ip_vs_flush(net); | ||
3339 | goto out; | ||
3340 | } else if (cmd == IPVS_CMD_SET_CONFIG) { | ||
3341 | ret = ip_vs_genl_set_config(net, info->attrs); | ||
3313 | goto out; | 3342 | goto out; |
3314 | } else if (cmd == IPVS_CMD_ZERO && | 3343 | } else if (cmd == IPVS_CMD_ZERO && |
3315 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { | 3344 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { |
@@ -3536,13 +3565,13 @@ static struct genl_ops ip_vs_genl_ops[] __read_mostly = { | |||
3536 | .cmd = IPVS_CMD_NEW_DAEMON, | 3565 | .cmd = IPVS_CMD_NEW_DAEMON, |
3537 | .flags = GENL_ADMIN_PERM, | 3566 | .flags = GENL_ADMIN_PERM, |
3538 | .policy = ip_vs_cmd_policy, | 3567 | .policy = ip_vs_cmd_policy, |
3539 | .doit = ip_vs_genl_set_cmd, | 3568 | .doit = ip_vs_genl_set_daemon, |
3540 | }, | 3569 | }, |
3541 | { | 3570 | { |
3542 | .cmd = IPVS_CMD_DEL_DAEMON, | 3571 | .cmd = IPVS_CMD_DEL_DAEMON, |
3543 | .flags = GENL_ADMIN_PERM, | 3572 | .flags = GENL_ADMIN_PERM, |
3544 | .policy = ip_vs_cmd_policy, | 3573 | .policy = ip_vs_cmd_policy, |
3545 | .doit = ip_vs_genl_set_cmd, | 3574 | .doit = ip_vs_genl_set_daemon, |
3546 | }, | 3575 | }, |
3547 | { | 3576 | { |
3548 | .cmd = IPVS_CMD_GET_DAEMON, | 3577 | .cmd = IPVS_CMD_GET_DAEMON, |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 7ee7215b8ba0..3cdd479f9b5d 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -61,6 +61,7 @@ | |||
61 | 61 | ||
62 | #define SYNC_PROTO_VER 1 /* Protocol version in header */ | 62 | #define SYNC_PROTO_VER 1 /* Protocol version in header */ |
63 | 63 | ||
64 | static struct lock_class_key __ipvs_sync_key; | ||
64 | /* | 65 | /* |
65 | * IPVS sync connection entry | 66 | * IPVS sync connection entry |
66 | * Version 0, i.e. original version. | 67 | * Version 0, i.e. original version. |
@@ -1545,6 +1546,7 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid) | |||
1545 | IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n", | 1546 | IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n", |
1546 | sizeof(struct ip_vs_sync_conn_v0)); | 1547 | sizeof(struct ip_vs_sync_conn_v0)); |
1547 | 1548 | ||
1549 | |||
1548 | if (state == IP_VS_STATE_MASTER) { | 1550 | if (state == IP_VS_STATE_MASTER) { |
1549 | if (ipvs->master_thread) | 1551 | if (ipvs->master_thread) |
1550 | return -EEXIST; | 1552 | return -EEXIST; |
@@ -1667,6 +1669,7 @@ int __net_init ip_vs_sync_net_init(struct net *net) | |||
1667 | { | 1669 | { |
1668 | struct netns_ipvs *ipvs = net_ipvs(net); | 1670 | struct netns_ipvs *ipvs = net_ipvs(net); |
1669 | 1671 | ||
1672 | __mutex_init(&ipvs->sync_mutex, "ipvs->sync_mutex", &__ipvs_sync_key); | ||
1670 | INIT_LIST_HEAD(&ipvs->sync_queue); | 1673 | INIT_LIST_HEAD(&ipvs->sync_queue); |
1671 | spin_lock_init(&ipvs->sync_lock); | 1674 | spin_lock_init(&ipvs->sync_lock); |
1672 | spin_lock_init(&ipvs->sync_buff_lock); | 1675 | spin_lock_init(&ipvs->sync_buff_lock); |
@@ -1680,7 +1683,9 @@ int __net_init ip_vs_sync_net_init(struct net *net) | |||
1680 | void ip_vs_sync_net_cleanup(struct net *net) | 1683 | void ip_vs_sync_net_cleanup(struct net *net) |
1681 | { | 1684 | { |
1682 | int retc; | 1685 | int retc; |
1686 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1683 | 1687 | ||
1688 | mutex_lock(&ipvs->sync_mutex); | ||
1684 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); | 1689 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); |
1685 | if (retc && retc != -ESRCH) | 1690 | if (retc && retc != -ESRCH) |
1686 | pr_err("Failed to stop Master Daemon\n"); | 1691 | pr_err("Failed to stop Master Daemon\n"); |
@@ -1688,4 +1693,5 @@ void ip_vs_sync_net_cleanup(struct net *net) | |||
1688 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); | 1693 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); |
1689 | if (retc && retc != -ESRCH) | 1694 | if (retc && retc != -ESRCH) |
1690 | pr_err("Failed to stop Backup Daemon\n"); | 1695 | pr_err("Failed to stop Backup Daemon\n"); |
1696 | mutex_unlock(&ipvs->sync_mutex); | ||
1691 | } | 1697 | } |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index cf616e55ca41..d69facdd9a7a 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
@@ -241,8 +241,8 @@ static int gre_packet(struct nf_conn *ct, | |||
241 | nf_ct_refresh_acct(ct, ctinfo, skb, | 241 | nf_ct_refresh_acct(ct, ctinfo, skb, |
242 | ct->proto.gre.stream_timeout); | 242 | ct->proto.gre.stream_timeout); |
243 | /* Also, more likely to be important, and not a probe. */ | 243 | /* Also, more likely to be important, and not a probe. */ |
244 | set_bit(IPS_ASSURED_BIT, &ct->status); | 244 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) |
245 | nf_conntrack_event_cache(IPCT_ASSURED, ct); | 245 | nf_conntrack_event_cache(IPCT_ASSURED, ct); |
246 | } else | 246 | } else |
247 | nf_ct_refresh_acct(ct, ctinfo, skb, | 247 | nf_ct_refresh_acct(ct, ctinfo, skb, |
248 | ct->proto.gre.timeout); | 248 | ct->proto.gre.timeout); |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index d30615419b4d..5f03e4ea65bf 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -91,7 +91,7 @@ int x25_parse_address_block(struct sk_buff *skb, | |||
91 | int needed; | 91 | int needed; |
92 | int rc; | 92 | int rc; |
93 | 93 | ||
94 | if (skb->len < 1) { | 94 | if (!pskb_may_pull(skb, 1)) { |
95 | /* packet has no address block */ | 95 | /* packet has no address block */ |
96 | rc = 0; | 96 | rc = 0; |
97 | goto empty; | 97 | goto empty; |
@@ -100,7 +100,7 @@ int x25_parse_address_block(struct sk_buff *skb, | |||
100 | len = *skb->data; | 100 | len = *skb->data; |
101 | needed = 1 + (len >> 4) + (len & 0x0f); | 101 | needed = 1 + (len >> 4) + (len & 0x0f); |
102 | 102 | ||
103 | if (skb->len < needed) { | 103 | if (!pskb_may_pull(skb, needed)) { |
104 | /* packet is too short to hold the addresses it claims | 104 | /* packet is too short to hold the addresses it claims |
105 | to hold */ | 105 | to hold */ |
106 | rc = -1; | 106 | rc = -1; |
@@ -295,7 +295,8 @@ static struct sock *x25_find_listener(struct x25_address *addr, | |||
295 | * Found a listening socket, now check the incoming | 295 | * Found a listening socket, now check the incoming |
296 | * call user data vs this sockets call user data | 296 | * call user data vs this sockets call user data |
297 | */ | 297 | */ |
298 | if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) { | 298 | if (x25_sk(s)->cudmatchlength > 0 && |
299 | skb->len >= x25_sk(s)->cudmatchlength) { | ||
299 | if((memcmp(x25_sk(s)->calluserdata.cuddata, | 300 | if((memcmp(x25_sk(s)->calluserdata.cuddata, |
300 | skb->data, | 301 | skb->data, |
301 | x25_sk(s)->cudmatchlength)) == 0) { | 302 | x25_sk(s)->cudmatchlength)) == 0) { |
@@ -951,14 +952,27 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
951 | * | 952 | * |
952 | * Facilities length is mandatory in call request packets | 953 | * Facilities length is mandatory in call request packets |
953 | */ | 954 | */ |
954 | if (skb->len < 1) | 955 | if (!pskb_may_pull(skb, 1)) |
955 | goto out_clear_request; | 956 | goto out_clear_request; |
956 | len = skb->data[0] + 1; | 957 | len = skb->data[0] + 1; |
957 | if (skb->len < len) | 958 | if (!pskb_may_pull(skb, len)) |
958 | goto out_clear_request; | 959 | goto out_clear_request; |
959 | skb_pull(skb,len); | 960 | skb_pull(skb,len); |
960 | 961 | ||
961 | /* | 962 | /* |
963 | * Ensure that the amount of call user data is valid. | ||
964 | */ | ||
965 | if (skb->len > X25_MAX_CUD_LEN) | ||
966 | goto out_clear_request; | ||
967 | |||
968 | /* | ||
969 | * Get all the call user data so it can be used in | ||
970 | * x25_find_listener and skb_copy_from_linear_data up ahead. | ||
971 | */ | ||
972 | if (!pskb_may_pull(skb, skb->len)) | ||
973 | goto out_clear_request; | ||
974 | |||
975 | /* | ||
962 | * Find a listener for the particular address/cud pair. | 976 | * Find a listener for the particular address/cud pair. |
963 | */ | 977 | */ |
964 | sk = x25_find_listener(&source_addr,skb); | 978 | sk = x25_find_listener(&source_addr,skb); |
@@ -1166,6 +1180,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1166 | * byte of the user data is the logical value of the Q Bit. | 1180 | * byte of the user data is the logical value of the Q Bit. |
1167 | */ | 1181 | */ |
1168 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { | 1182 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1183 | if (!pskb_may_pull(skb, 1)) | ||
1184 | goto out_kfree_skb; | ||
1185 | |||
1169 | qbit = skb->data[0]; | 1186 | qbit = skb->data[0]; |
1170 | skb_pull(skb, 1); | 1187 | skb_pull(skb, 1); |
1171 | } | 1188 | } |
@@ -1244,7 +1261,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1244 | struct x25_sock *x25 = x25_sk(sk); | 1261 | struct x25_sock *x25 = x25_sk(sk); |
1245 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; | 1262 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; |
1246 | size_t copied; | 1263 | size_t copied; |
1247 | int qbit; | 1264 | int qbit, header_len = x25->neighbour->extended ? |
1265 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN; | ||
1266 | |||
1248 | struct sk_buff *skb; | 1267 | struct sk_buff *skb; |
1249 | unsigned char *asmptr; | 1268 | unsigned char *asmptr; |
1250 | int rc = -ENOTCONN; | 1269 | int rc = -ENOTCONN; |
@@ -1265,6 +1284,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1265 | 1284 | ||
1266 | skb = skb_dequeue(&x25->interrupt_in_queue); | 1285 | skb = skb_dequeue(&x25->interrupt_in_queue); |
1267 | 1286 | ||
1287 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
1288 | goto out_free_dgram; | ||
1289 | |||
1268 | skb_pull(skb, X25_STD_MIN_LEN); | 1290 | skb_pull(skb, X25_STD_MIN_LEN); |
1269 | 1291 | ||
1270 | /* | 1292 | /* |
@@ -1285,10 +1307,12 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1285 | if (!skb) | 1307 | if (!skb) |
1286 | goto out; | 1308 | goto out; |
1287 | 1309 | ||
1310 | if (!pskb_may_pull(skb, header_len)) | ||
1311 | goto out_free_dgram; | ||
1312 | |||
1288 | qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; | 1313 | qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; |
1289 | 1314 | ||
1290 | skb_pull(skb, x25->neighbour->extended ? | 1315 | skb_pull(skb, header_len); |
1291 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN); | ||
1292 | 1316 | ||
1293 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { | 1317 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1294 | asmptr = skb_push(skb, 1); | 1318 | asmptr = skb_push(skb, 1); |
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index e547ca1578c3..fa2b41888bd9 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c | |||
@@ -32,6 +32,9 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) | |||
32 | unsigned short frametype; | 32 | unsigned short frametype; |
33 | unsigned int lci; | 33 | unsigned int lci; |
34 | 34 | ||
35 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
36 | return 0; | ||
37 | |||
35 | frametype = skb->data[2]; | 38 | frametype = skb->data[2]; |
36 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 39 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
37 | 40 | ||
@@ -115,6 +118,9 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev, | |||
115 | goto drop; | 118 | goto drop; |
116 | } | 119 | } |
117 | 120 | ||
121 | if (!pskb_may_pull(skb, 1)) | ||
122 | return 0; | ||
123 | |||
118 | switch (skb->data[0]) { | 124 | switch (skb->data[0]) { |
119 | 125 | ||
120 | case X25_IFACE_DATA: | 126 | case X25_IFACE_DATA: |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index f77e4e75f914..36384a1fa9f2 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
@@ -44,7 +44,7 @@ | |||
44 | int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | 44 | int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, |
45 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 45 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
46 | { | 46 | { |
47 | unsigned char *p = skb->data; | 47 | unsigned char *p; |
48 | unsigned int len; | 48 | unsigned int len; |
49 | 49 | ||
50 | *vc_fac_mask = 0; | 50 | *vc_fac_mask = 0; |
@@ -60,14 +60,16 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
60 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | 60 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); |
61 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | 61 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); |
62 | 62 | ||
63 | if (skb->len < 1) | 63 | if (!pskb_may_pull(skb, 1)) |
64 | return 0; | 64 | return 0; |
65 | 65 | ||
66 | len = *p++; | 66 | len = skb->data[0]; |
67 | 67 | ||
68 | if (len >= skb->len) | 68 | if (!pskb_may_pull(skb, 1 + len)) |
69 | return -1; | 69 | return -1; |
70 | 70 | ||
71 | p = skb->data + 1; | ||
72 | |||
71 | while (len > 0) { | 73 | while (len > 0) { |
72 | switch (*p & X25_FAC_CLASS_MASK) { | 74 | switch (*p & X25_FAC_CLASS_MASK) { |
73 | case X25_FAC_CLASS_A: | 75 | case X25_FAC_CLASS_A: |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 0b073b51b183..a49cd4ec551a 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -107,6 +107,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
107 | /* | 107 | /* |
108 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
109 | */ | 109 | */ |
110 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
111 | goto out_clear; | ||
110 | skb_pull(skb, X25_STD_MIN_LEN); | 112 | skb_pull(skb, X25_STD_MIN_LEN); |
111 | 113 | ||
112 | len = x25_parse_address_block(skb, &source_addr, | 114 | len = x25_parse_address_block(skb, &source_addr, |
@@ -127,9 +129,11 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
127 | * Copy any Call User Data. | 129 | * Copy any Call User Data. |
128 | */ | 130 | */ |
129 | if (skb->len > 0) { | 131 | if (skb->len > 0) { |
130 | skb_copy_from_linear_data(skb, | 132 | if (skb->len > X25_MAX_CUD_LEN) |
131 | x25->calluserdata.cuddata, | 133 | goto out_clear; |
132 | skb->len); | 134 | |
135 | skb_copy_bits(skb, 0, x25->calluserdata.cuddata, | ||
136 | skb->len); | ||
133 | x25->calluserdata.cudlength = skb->len; | 137 | x25->calluserdata.cudlength = skb->len; |
134 | } | 138 | } |
135 | if (!sock_flag(sk, SOCK_DEAD)) | 139 | if (!sock_flag(sk, SOCK_DEAD)) |
@@ -137,6 +141,9 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
137 | break; | 141 | break; |
138 | } | 142 | } |
139 | case X25_CLEAR_REQUEST: | 143 | case X25_CLEAR_REQUEST: |
144 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
145 | goto out_clear; | ||
146 | |||
140 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 147 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
141 | x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); | 148 | x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); |
142 | break; | 149 | break; |
@@ -164,6 +171,9 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
164 | switch (frametype) { | 171 | switch (frametype) { |
165 | 172 | ||
166 | case X25_CLEAR_REQUEST: | 173 | case X25_CLEAR_REQUEST: |
174 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
175 | goto out_clear; | ||
176 | |||
167 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 177 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
168 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 178 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
169 | break; | 179 | break; |
@@ -177,6 +187,11 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
177 | } | 187 | } |
178 | 188 | ||
179 | return 0; | 189 | return 0; |
190 | |||
191 | out_clear: | ||
192 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
193 | x25_start_t23timer(sk); | ||
194 | return 0; | ||
180 | } | 195 | } |
181 | 196 | ||
182 | /* | 197 | /* |
@@ -206,6 +221,9 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
206 | break; | 221 | break; |
207 | 222 | ||
208 | case X25_CLEAR_REQUEST: | 223 | case X25_CLEAR_REQUEST: |
224 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
225 | goto out_clear; | ||
226 | |||
209 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 227 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
210 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 228 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
211 | break; | 229 | break; |
@@ -304,6 +322,12 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
304 | } | 322 | } |
305 | 323 | ||
306 | return queued; | 324 | return queued; |
325 | |||
326 | out_clear: | ||
327 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
328 | x25->state = X25_STATE_2; | ||
329 | x25_start_t23timer(sk); | ||
330 | return 0; | ||
307 | } | 331 | } |
308 | 332 | ||
309 | /* | 333 | /* |
@@ -313,13 +337,13 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
313 | */ | 337 | */ |
314 | static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 338 | static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
315 | { | 339 | { |
340 | struct x25_sock *x25 = x25_sk(sk); | ||
341 | |||
316 | switch (frametype) { | 342 | switch (frametype) { |
317 | 343 | ||
318 | case X25_RESET_REQUEST: | 344 | case X25_RESET_REQUEST: |
319 | x25_write_internal(sk, X25_RESET_CONFIRMATION); | 345 | x25_write_internal(sk, X25_RESET_CONFIRMATION); |
320 | case X25_RESET_CONFIRMATION: { | 346 | case X25_RESET_CONFIRMATION: { |
321 | struct x25_sock *x25 = x25_sk(sk); | ||
322 | |||
323 | x25_stop_timer(sk); | 347 | x25_stop_timer(sk); |
324 | x25->condition = 0x00; | 348 | x25->condition = 0x00; |
325 | x25->va = 0; | 349 | x25->va = 0; |
@@ -331,6 +355,9 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
331 | break; | 355 | break; |
332 | } | 356 | } |
333 | case X25_CLEAR_REQUEST: | 357 | case X25_CLEAR_REQUEST: |
358 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
359 | goto out_clear; | ||
360 | |||
334 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 361 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
335 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 362 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
336 | break; | 363 | break; |
@@ -340,6 +367,12 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
340 | } | 367 | } |
341 | 368 | ||
342 | return 0; | 369 | return 0; |
370 | |||
371 | out_clear: | ||
372 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
373 | x25->state = X25_STATE_2; | ||
374 | x25_start_t23timer(sk); | ||
375 | return 0; | ||
343 | } | 376 | } |
344 | 377 | ||
345 | /* Higher level upcall for a LAPB frame */ | 378 | /* Higher level upcall for a LAPB frame */ |
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index 037958ff8eed..4acacf3c6617 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c | |||
@@ -90,6 +90,9 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb, | |||
90 | break; | 90 | break; |
91 | 91 | ||
92 | case X25_DIAGNOSTIC: | 92 | case X25_DIAGNOSTIC: |
93 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 4)) | ||
94 | break; | ||
95 | |||
93 | printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n", | 96 | printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n", |
94 | skb->data[3], skb->data[4], | 97 | skb->data[3], skb->data[4], |
95 | skb->data[5], skb->data[6]); | 98 | skb->data[5], skb->data[6]); |
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 24a342ebc7f5..5170d52bfd96 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c | |||
@@ -269,7 +269,11 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, | |||
269 | int *d, int *m) | 269 | int *d, int *m) |
270 | { | 270 | { |
271 | struct x25_sock *x25 = x25_sk(sk); | 271 | struct x25_sock *x25 = x25_sk(sk); |
272 | unsigned char *frame = skb->data; | 272 | unsigned char *frame; |
273 | |||
274 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
275 | return X25_ILLEGAL; | ||
276 | frame = skb->data; | ||
273 | 277 | ||
274 | *ns = *nr = *q = *d = *m = 0; | 278 | *ns = *nr = *q = *d = *m = 0; |
275 | 279 | ||
@@ -294,6 +298,10 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, | |||
294 | if (frame[2] == X25_RR || | 298 | if (frame[2] == X25_RR || |
295 | frame[2] == X25_RNR || | 299 | frame[2] == X25_RNR || |
296 | frame[2] == X25_REJ) { | 300 | frame[2] == X25_REJ) { |
301 | if (!pskb_may_pull(skb, X25_EXT_MIN_LEN)) | ||
302 | return X25_ILLEGAL; | ||
303 | frame = skb->data; | ||
304 | |||
297 | *nr = (frame[3] >> 1) & 0x7F; | 305 | *nr = (frame[3] >> 1) & 0x7F; |
298 | return frame[2]; | 306 | return frame[2]; |
299 | } | 307 | } |
@@ -308,6 +316,10 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, | |||
308 | 316 | ||
309 | if (x25->neighbour->extended) { | 317 | if (x25->neighbour->extended) { |
310 | if ((frame[2] & 0x01) == X25_DATA) { | 318 | if ((frame[2] & 0x01) == X25_DATA) { |
319 | if (!pskb_may_pull(skb, X25_EXT_MIN_LEN)) | ||
320 | return X25_ILLEGAL; | ||
321 | frame = skb->data; | ||
322 | |||
311 | *q = (frame[0] & X25_Q_BIT) == X25_Q_BIT; | 323 | *q = (frame[0] & X25_Q_BIT) == X25_Q_BIT; |
312 | *d = (frame[0] & X25_D_BIT) == X25_D_BIT; | 324 | *d = (frame[0] & X25_D_BIT) == X25_D_BIT; |
313 | *m = (frame[3] & X25_EXT_M_BIT) == X25_EXT_M_BIT; | 325 | *m = (frame[3] & X25_EXT_M_BIT) == X25_EXT_M_BIT; |