diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2010-09-24 08:03:37 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2010-09-24 08:03:37 -0400 |
| commit | 73e6d6c6467771838c1fc6949e6768a12ed72464 (patch) | |
| tree | 94dd60891869a0a275cd332c4e675cf0b101fcfa /net | |
| parent | 12e5272585901217e919da810c801e5084ee0cb1 (diff) | |
| parent | a850ea30374ebed32a0724742601861853fde869 (diff) | |
Merge branch 'master' into upstream
Diffstat (limited to 'net')
56 files changed, 420 insertions, 364 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 3d59c9bf8feb..3bccdd12a264 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -510,7 +510,8 @@ static int vlan_dev_open(struct net_device *dev) | |||
| 510 | if (vlan->flags & VLAN_FLAG_GVRP) | 510 | if (vlan->flags & VLAN_FLAG_GVRP) |
| 511 | vlan_gvrp_request_join(dev); | 511 | vlan_gvrp_request_join(dev); |
| 512 | 512 | ||
| 513 | netif_carrier_on(dev); | 513 | if (netif_carrier_ok(real_dev)) |
| 514 | netif_carrier_on(dev); | ||
| 514 | return 0; | 515 | return 0; |
| 515 | 516 | ||
| 516 | clear_allmulti: | 517 | clear_allmulti: |
diff --git a/net/9p/client.c b/net/9p/client.c index dc6f2f26d023..9eb72505308f 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -331,8 +331,10 @@ static void p9_tag_cleanup(struct p9_client *c) | |||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | if (c->tagpool) | 334 | if (c->tagpool) { |
| 335 | p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ | ||
| 335 | p9_idpool_destroy(c->tagpool); | 336 | p9_idpool_destroy(c->tagpool); |
| 337 | } | ||
| 336 | 338 | ||
| 337 | /* free requests associated with tags */ | 339 | /* free requests associated with tags */ |
| 338 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { | 340 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { |
| @@ -944,6 +946,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
| 944 | int16_t nwqids, count; | 946 | int16_t nwqids, count; |
| 945 | 947 | ||
| 946 | err = 0; | 948 | err = 0; |
| 949 | wqids = NULL; | ||
| 947 | clnt = oldfid->clnt; | 950 | clnt = oldfid->clnt; |
| 948 | if (clone) { | 951 | if (clone) { |
| 949 | fid = p9_fid_create(clnt); | 952 | fid = p9_fid_create(clnt); |
| @@ -994,9 +997,11 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
| 994 | else | 997 | else |
| 995 | fid->qid = oldfid->qid; | 998 | fid->qid = oldfid->qid; |
| 996 | 999 | ||
| 1000 | kfree(wqids); | ||
| 997 | return fid; | 1001 | return fid; |
| 998 | 1002 | ||
| 999 | clunk_fid: | 1003 | clunk_fid: |
| 1004 | kfree(wqids); | ||
| 1000 | p9_client_clunk(fid); | 1005 | p9_client_clunk(fid); |
| 1001 | fid = NULL; | 1006 | fid = NULL; |
| 1002 | 1007 | ||
diff --git a/net/Kconfig b/net/Kconfig index e330594d3709..e926884c1675 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
| @@ -217,7 +217,7 @@ source "net/dns_resolver/Kconfig" | |||
| 217 | 217 | ||
| 218 | config RPS | 218 | config RPS |
| 219 | boolean | 219 | boolean |
| 220 | depends on SMP && SYSFS | 220 | depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS |
| 221 | default y | 221 | default y |
| 222 | 222 | ||
| 223 | menu "Network testing" | 223 | menu "Network testing" |
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index 2ce79df00680..c7d81436213d 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c | |||
| @@ -112,8 +112,8 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25) | |||
| 112 | if (sk) { | 112 | if (sk) { |
| 113 | sock_hold(sk); | 113 | sock_hold(sk); |
| 114 | ax25_destroy_socket(ax25); | 114 | ax25_destroy_socket(ax25); |
| 115 | sock_put(sk); | ||
| 116 | bh_unlock_sock(sk); | 115 | bh_unlock_sock(sk); |
| 116 | sock_put(sk); | ||
| 117 | } else | 117 | } else |
| 118 | ax25_destroy_socket(ax25); | 118 | ax25_destroy_socket(ax25); |
| 119 | return; | 119 | return; |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 2c911c0759c2..137f23259a93 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -162,8 +162,8 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb) | |||
| 162 | if (tmp) { | 162 | if (tmp) { |
| 163 | memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info)); | 163 | memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info)); |
| 164 | atomic_set(&tmp->use, 1); | 164 | atomic_set(&tmp->use, 1); |
| 165 | nf_bridge_put(nf_bridge); | ||
| 166 | } | 165 | } |
| 166 | nf_bridge_put(nf_bridge); | ||
| 167 | nf_bridge = tmp; | 167 | nf_bridge = tmp; |
| 168 | } | 168 | } |
| 169 | return nf_bridge; | 169 | return nf_bridge; |
| @@ -761,9 +761,11 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) | |||
| 761 | { | 761 | { |
| 762 | if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) && | 762 | if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) && |
| 763 | skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && | 763 | skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && |
| 764 | !skb_is_gso(skb)) | 764 | !skb_is_gso(skb)) { |
| 765 | /* BUG: Should really parse the IP options here. */ | ||
| 766 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | ||
| 765 | return ip_fragment(skb, br_dev_queue_push_xmit); | 767 | return ip_fragment(skb, br_dev_queue_push_xmit); |
| 766 | else | 768 | } else |
| 767 | return br_dev_queue_push_xmit(skb); | 769 | return br_dev_queue_push_xmit(skb); |
| 768 | } | 770 | } |
| 769 | #else | 771 | #else |
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index eb1602022ac0..9a699242d104 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <linux/stddef.h> | 7 | #include <linux/stddef.h> |
| 8 | #include <linux/spinlock.h> | 8 | #include <linux/spinlock.h> |
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/unaligned/le_byteshift.h> | 10 | #include <asm/unaligned.h> |
| 11 | #include <net/caif/caif_layer.h> | 11 | #include <net/caif/caif_layer.h> |
| 12 | #include <net/caif/cfsrvl.h> | 12 | #include <net/caif/cfsrvl.h> |
| 13 | #include <net/caif/cfpkt.h> | 13 | #include <net/caif/cfpkt.h> |
diff --git a/net/core/dev.c b/net/core/dev.c index 3721fbb9a83c..660dd41aaaa6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2058,16 +2058,16 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
| 2058 | struct sk_buff *skb) | 2058 | struct sk_buff *skb) |
| 2059 | { | 2059 | { |
| 2060 | int queue_index; | 2060 | int queue_index; |
| 2061 | struct sock *sk = skb->sk; | 2061 | const struct net_device_ops *ops = dev->netdev_ops; |
| 2062 | 2062 | ||
| 2063 | queue_index = sk_tx_queue_get(sk); | 2063 | if (ops->ndo_select_queue) { |
| 2064 | if (queue_index < 0) { | 2064 | queue_index = ops->ndo_select_queue(dev, skb); |
| 2065 | const struct net_device_ops *ops = dev->netdev_ops; | 2065 | queue_index = dev_cap_txqueue(dev, queue_index); |
| 2066 | } else { | ||
| 2067 | struct sock *sk = skb->sk; | ||
| 2068 | queue_index = sk_tx_queue_get(sk); | ||
| 2069 | if (queue_index < 0) { | ||
| 2066 | 2070 | ||
| 2067 | if (ops->ndo_select_queue) { | ||
| 2068 | queue_index = ops->ndo_select_queue(dev, skb); | ||
| 2069 | queue_index = dev_cap_txqueue(dev, queue_index); | ||
| 2070 | } else { | ||
| 2071 | queue_index = 0; | 2071 | queue_index = 0; |
| 2072 | if (dev->real_num_tx_queues > 1) | 2072 | if (dev->real_num_tx_queues > 1) |
| 2073 | queue_index = skb_tx_hash(dev, skb); | 2073 | queue_index = skb_tx_hash(dev, skb); |
| @@ -4845,7 +4845,7 @@ static void rollback_registered_many(struct list_head *head) | |||
| 4845 | dev = list_first_entry(head, struct net_device, unreg_list); | 4845 | dev = list_first_entry(head, struct net_device, unreg_list); |
| 4846 | call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); | 4846 | call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); |
| 4847 | 4847 | ||
| 4848 | synchronize_net(); | 4848 | rcu_barrier(); |
| 4849 | 4849 | ||
| 4850 | list_for_each_entry(dev, head, unreg_list) | 4850 | list_for_each_entry(dev, head, unreg_list) |
| 4851 | dev_put(dev); | 4851 | dev_put(dev); |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 9fbe7f7429b0..6743146e4d6b 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
| @@ -232,7 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, | |||
| 232 | est->last_packets = bstats->packets; | 232 | est->last_packets = bstats->packets; |
| 233 | est->avpps = rate_est->pps<<10; | 233 | est->avpps = rate_est->pps<<10; |
| 234 | 234 | ||
| 235 | spin_lock(&est_tree_lock); | 235 | spin_lock_bh(&est_tree_lock); |
| 236 | if (!elist[idx].timer.function) { | 236 | if (!elist[idx].timer.function) { |
| 237 | INIT_LIST_HEAD(&elist[idx].list); | 237 | INIT_LIST_HEAD(&elist[idx].list); |
| 238 | setup_timer(&elist[idx].timer, est_timer, idx); | 238 | setup_timer(&elist[idx].timer, est_timer, idx); |
| @@ -243,7 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, | |||
| 243 | 243 | ||
| 244 | list_add_rcu(&est->list, &elist[idx].list); | 244 | list_add_rcu(&est->list, &elist[idx].list); |
| 245 | gen_add_node(est); | 245 | gen_add_node(est); |
| 246 | spin_unlock(&est_tree_lock); | 246 | spin_unlock_bh(&est_tree_lock); |
| 247 | 247 | ||
| 248 | return 0; | 248 | return 0; |
| 249 | } | 249 | } |
| @@ -270,7 +270,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, | |||
| 270 | { | 270 | { |
| 271 | struct gen_estimator *e; | 271 | struct gen_estimator *e; |
| 272 | 272 | ||
| 273 | spin_lock(&est_tree_lock); | 273 | spin_lock_bh(&est_tree_lock); |
| 274 | while ((e = gen_find_node(bstats, rate_est))) { | 274 | while ((e = gen_find_node(bstats, rate_est))) { |
| 275 | rb_erase(&e->node, &est_root); | 275 | rb_erase(&e->node, &est_root); |
| 276 | 276 | ||
| @@ -281,7 +281,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, | |||
| 281 | list_del_rcu(&e->list); | 281 | list_del_rcu(&e->list); |
| 282 | call_rcu(&e->e_rcu, __gen_kill_estimator); | 282 | call_rcu(&e->e_rcu, __gen_kill_estimator); |
| 283 | } | 283 | } |
| 284 | spin_unlock(&est_tree_lock); | 284 | spin_unlock_bh(&est_tree_lock); |
| 285 | } | 285 | } |
| 286 | EXPORT_SYMBOL(gen_kill_estimator); | 286 | EXPORT_SYMBOL(gen_kill_estimator); |
| 287 | 287 | ||
| @@ -320,9 +320,9 @@ bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, | |||
| 320 | 320 | ||
| 321 | ASSERT_RTNL(); | 321 | ASSERT_RTNL(); |
| 322 | 322 | ||
| 323 | spin_lock(&est_tree_lock); | 323 | spin_lock_bh(&est_tree_lock); |
| 324 | res = gen_find_node(bstats, rate_est) != NULL; | 324 | res = gen_find_node(bstats, rate_est) != NULL; |
| 325 | spin_unlock(&est_tree_lock); | 325 | spin_unlock_bh(&est_tree_lock); |
| 326 | 326 | ||
| 327 | return res; | 327 | return res; |
| 328 | } | 328 | } |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3a2513f0d0c3..c83b421341c0 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -2573,6 +2573,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
| 2573 | __copy_skb_header(nskb, skb); | 2573 | __copy_skb_header(nskb, skb); |
| 2574 | nskb->mac_len = skb->mac_len; | 2574 | nskb->mac_len = skb->mac_len; |
| 2575 | 2575 | ||
| 2576 | /* nskb and skb might have different headroom */ | ||
| 2577 | if (nskb->ip_summed == CHECKSUM_PARTIAL) | ||
| 2578 | nskb->csum_start += skb_headroom(nskb) - headroom; | ||
| 2579 | |||
| 2576 | skb_reset_mac_header(nskb); | 2580 | skb_reset_mac_header(nskb); |
| 2577 | skb_set_network_header(nskb, skb->mac_len); | 2581 | skb_set_network_header(nskb, skb->mac_len); |
| 2578 | nskb->transport_header = (nskb->network_header + | 2582 | nskb->transport_header = (nskb->network_header + |
| @@ -2703,7 +2707,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
| 2703 | return -E2BIG; | 2707 | return -E2BIG; |
| 2704 | 2708 | ||
| 2705 | headroom = skb_headroom(p); | 2709 | headroom = skb_headroom(p); |
| 2706 | nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p)); | 2710 | nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); |
| 2707 | if (unlikely(!nskb)) | 2711 | if (unlikely(!nskb)) |
| 2708 | return -ENOMEM; | 2712 | return -ENOMEM; |
| 2709 | 2713 | ||
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 7c3a7d191249..571f8950ed06 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
| @@ -46,7 +46,7 @@ config IP_ADVANCED_ROUTER | |||
| 46 | rp_filter on use: | 46 | rp_filter on use: |
| 47 | 47 | ||
| 48 | echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter | 48 | echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter |
| 49 | and | 49 | or |
| 50 | echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter | 50 | echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter |
| 51 | 51 | ||
| 52 | Note that some distributions enable it in startup scripts. | 52 | Note that some distributions enable it in startup scripts. |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index f0550941df7b..721a8a37b45c 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
| @@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
| 62 | } | 62 | } |
| 63 | if (!inet->inet_saddr) | 63 | if (!inet->inet_saddr) |
| 64 | inet->inet_saddr = rt->rt_src; /* Update source address */ | 64 | inet->inet_saddr = rt->rt_src; /* Update source address */ |
| 65 | if (!inet->inet_rcv_saddr) | 65 | if (!inet->inet_rcv_saddr) { |
| 66 | inet->inet_rcv_saddr = rt->rt_src; | 66 | inet->inet_rcv_saddr = rt->rt_src; |
| 67 | if (sk->sk_prot->rehash) | ||
| 68 | sk->sk_prot->rehash(sk); | ||
| 69 | } | ||
| 67 | inet->inet_daddr = rt->rt_dst; | 70 | inet->inet_daddr = rt->rt_dst; |
| 68 | inet->inet_dport = usin->sin_port; | 71 | inet->inet_dport = usin->sin_port; |
| 69 | sk->sk_state = TCP_ESTABLISHED; | 72 | sk->sk_state = TCP_ESTABLISHED; |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index a43968918350..7d02a9f999fa 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -246,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
| 246 | 246 | ||
| 247 | struct fib_result res; | 247 | struct fib_result res; |
| 248 | int no_addr, rpf, accept_local; | 248 | int no_addr, rpf, accept_local; |
| 249 | bool dev_match; | ||
| 249 | int ret; | 250 | int ret; |
| 250 | struct net *net; | 251 | struct net *net; |
| 251 | 252 | ||
| @@ -273,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
| 273 | } | 274 | } |
| 274 | *spec_dst = FIB_RES_PREFSRC(res); | 275 | *spec_dst = FIB_RES_PREFSRC(res); |
| 275 | fib_combine_itag(itag, &res); | 276 | fib_combine_itag(itag, &res); |
| 277 | dev_match = false; | ||
| 278 | |||
| 276 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 279 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
| 277 | if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1) | 280 | for (ret = 0; ret < res.fi->fib_nhs; ret++) { |
| 281 | struct fib_nh *nh = &res.fi->fib_nh[ret]; | ||
| 282 | |||
| 283 | if (nh->nh_dev == dev) { | ||
| 284 | dev_match = true; | ||
| 285 | break; | ||
| 286 | } | ||
| 287 | } | ||
| 278 | #else | 288 | #else |
| 279 | if (FIB_RES_DEV(res) == dev) | 289 | if (FIB_RES_DEV(res) == dev) |
| 290 | dev_match = true; | ||
| 280 | #endif | 291 | #endif |
| 281 | { | 292 | if (dev_match) { |
| 282 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; | 293 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; |
| 283 | fib_res_put(&res); | 294 | fib_res_put(&res); |
| 284 | return ret; | 295 | return ret; |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 79d057a939ba..4a8e370862bc 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -186,7 +186,9 @@ static inline struct tnode *node_parent_rcu(struct node *node) | |||
| 186 | { | 186 | { |
| 187 | struct tnode *ret = node_parent(node); | 187 | struct tnode *ret = node_parent(node); |
| 188 | 188 | ||
| 189 | return rcu_dereference(ret); | 189 | return rcu_dereference_check(ret, |
| 190 | rcu_read_lock_held() || | ||
| 191 | lockdep_rtnl_is_held()); | ||
| 190 | } | 192 | } |
| 191 | 193 | ||
| 192 | /* Same as rcu_assign_pointer | 194 | /* Same as rcu_assign_pointer |
| @@ -1753,7 +1755,9 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c) | |||
| 1753 | 1755 | ||
| 1754 | static struct leaf *trie_firstleaf(struct trie *t) | 1756 | static struct leaf *trie_firstleaf(struct trie *t) |
| 1755 | { | 1757 | { |
| 1756 | struct tnode *n = (struct tnode *) rcu_dereference(t->trie); | 1758 | struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie, |
| 1759 | rcu_read_lock_held() || | ||
| 1760 | lockdep_rtnl_is_held()); | ||
| 1757 | 1761 | ||
| 1758 | if (!n) | 1762 | if (!n) |
| 1759 | return NULL; | 1763 | return NULL; |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index a1ad0e7180d2..1fdcacd36ce7 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
| @@ -834,7 +834,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, | |||
| 834 | int mark = 0; | 834 | int mark = 0; |
| 835 | 835 | ||
| 836 | 836 | ||
| 837 | if (len == 8) { | 837 | if (len == 8 || IGMP_V2_SEEN(in_dev)) { |
| 838 | if (ih->code == 0) { | 838 | if (ih->code == 0) { |
| 839 | /* Alas, old v1 router presents here. */ | 839 | /* Alas, old v1 router presents here. */ |
| 840 | 840 | ||
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 6c40a8c46e79..64b70ad162e3 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -1129,6 +1129,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, | |||
| 1129 | case IP_HDRINCL: | 1129 | case IP_HDRINCL: |
| 1130 | val = inet->hdrincl; | 1130 | val = inet->hdrincl; |
| 1131 | break; | 1131 | break; |
| 1132 | case IP_NODEFRAG: | ||
| 1133 | val = inet->nodefrag; | ||
| 1134 | break; | ||
| 1132 | case IP_MTU_DISCOVER: | 1135 | case IP_MTU_DISCOVER: |
| 1133 | val = inet->pmtudisc; | 1136 | val = inet->pmtudisc; |
| 1134 | break; | 1137 | break; |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 51d6c3167975..e8f4f9a57f12 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
| @@ -1420,6 +1420,9 @@ static int translate_compat_table(const char *name, | |||
| 1420 | if (ret != 0) | 1420 | if (ret != 0) |
| 1421 | break; | 1421 | break; |
| 1422 | ++i; | 1422 | ++i; |
| 1423 | if (strcmp(arpt_get_target(iter1)->u.user.name, | ||
| 1424 | XT_ERROR_TARGET) == 0) | ||
| 1425 | ++newinfo->stacksize; | ||
| 1423 | } | 1426 | } |
| 1424 | if (ret) { | 1427 | if (ret) { |
| 1425 | /* | 1428 | /* |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 97b64b22c412..d163f2e3b2e9 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
| @@ -1751,6 +1751,9 @@ translate_compat_table(struct net *net, | |||
| 1751 | if (ret != 0) | 1751 | if (ret != 0) |
| 1752 | break; | 1752 | break; |
| 1753 | ++i; | 1753 | ++i; |
| 1754 | if (strcmp(ipt_get_target(iter1)->u.user.name, | ||
| 1755 | XT_ERROR_TARGET) == 0) | ||
| 1756 | ++newinfo->stacksize; | ||
| 1754 | } | 1757 | } |
| 1755 | if (ret) { | 1758 | if (ret) { |
| 1756 | /* | 1759 | /* |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3f56b6e6c6aa..6298f75d5e93 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -2738,6 +2738,11 @@ slow_output: | |||
| 2738 | } | 2738 | } |
| 2739 | EXPORT_SYMBOL_GPL(__ip_route_output_key); | 2739 | EXPORT_SYMBOL_GPL(__ip_route_output_key); |
| 2740 | 2740 | ||
| 2741 | static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie) | ||
| 2742 | { | ||
| 2743 | return NULL; | ||
| 2744 | } | ||
| 2745 | |||
| 2741 | static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | 2746 | static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) |
| 2742 | { | 2747 | { |
| 2743 | } | 2748 | } |
| @@ -2746,7 +2751,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { | |||
| 2746 | .family = AF_INET, | 2751 | .family = AF_INET, |
| 2747 | .protocol = cpu_to_be16(ETH_P_IP), | 2752 | .protocol = cpu_to_be16(ETH_P_IP), |
| 2748 | .destroy = ipv4_dst_destroy, | 2753 | .destroy = ipv4_dst_destroy, |
| 2749 | .check = ipv4_dst_check, | 2754 | .check = ipv4_blackhole_dst_check, |
| 2750 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, | 2755 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, |
| 2751 | .entries = ATOMIC_INIT(0), | 2756 | .entries = ATOMIC_INIT(0), |
| 2752 | }; | 2757 | }; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 176e11aaea77..3fb1428e526e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -451,7 +451,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
| 451 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) | 451 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) |
| 452 | mask |= POLLOUT | POLLWRNORM; | 452 | mask |= POLLOUT | POLLWRNORM; |
| 453 | } | 453 | } |
| 454 | } | 454 | } else |
| 455 | mask |= POLLOUT | POLLWRNORM; | ||
| 455 | 456 | ||
| 456 | if (tp->urg_data & TCP_URG_VALID) | 457 | if (tp->urg_data & TCP_URG_VALID) |
| 457 | mask |= POLLPRI; | 458 | mask |= POLLPRI; |
| @@ -2011,11 +2012,8 @@ adjudge_to_death: | |||
| 2011 | } | 2012 | } |
| 2012 | } | 2013 | } |
| 2013 | if (sk->sk_state != TCP_CLOSE) { | 2014 | if (sk->sk_state != TCP_CLOSE) { |
| 2014 | int orphan_count = percpu_counter_read_positive( | ||
| 2015 | sk->sk_prot->orphan_count); | ||
| 2016 | |||
| 2017 | sk_mem_reclaim(sk); | 2015 | sk_mem_reclaim(sk); |
| 2018 | if (tcp_too_many_orphans(sk, orphan_count)) { | 2016 | if (tcp_too_many_orphans(sk, 0)) { |
| 2019 | if (net_ratelimit()) | 2017 | if (net_ratelimit()) |
| 2020 | printk(KERN_INFO "TCP: too many of orphaned " | 2018 | printk(KERN_INFO "TCP: too many of orphaned " |
| 2021 | "sockets\n"); | 2019 | "sockets\n"); |
| @@ -3212,7 +3210,7 @@ void __init tcp_init(void) | |||
| 3212 | { | 3210 | { |
| 3213 | struct sk_buff *skb = NULL; | 3211 | struct sk_buff *skb = NULL; |
| 3214 | unsigned long nr_pages, limit; | 3212 | unsigned long nr_pages, limit; |
| 3215 | int order, i, max_share; | 3213 | int i, max_share, cnt; |
| 3216 | unsigned long jiffy = jiffies; | 3214 | unsigned long jiffy = jiffies; |
| 3217 | 3215 | ||
| 3218 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); | 3216 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); |
| @@ -3261,22 +3259,12 @@ void __init tcp_init(void) | |||
| 3261 | INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain); | 3259 | INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain); |
| 3262 | } | 3260 | } |
| 3263 | 3261 | ||
| 3264 | /* Try to be a bit smarter and adjust defaults depending | 3262 | |
| 3265 | * on available memory. | 3263 | cnt = tcp_hashinfo.ehash_mask + 1; |
| 3266 | */ | 3264 | |
| 3267 | for (order = 0; ((1 << order) << PAGE_SHIFT) < | 3265 | tcp_death_row.sysctl_max_tw_buckets = cnt / 2; |
| 3268 | (tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket)); | 3266 | sysctl_tcp_max_orphans = cnt / 2; |
| 3269 | order++) | 3267 | sysctl_max_syn_backlog = max(128, cnt / 256); |
| 3270 | ; | ||
| 3271 | if (order >= 4) { | ||
| 3272 | tcp_death_row.sysctl_max_tw_buckets = 180000; | ||
| 3273 | sysctl_tcp_max_orphans = 4096 << (order - 4); | ||
| 3274 | sysctl_max_syn_backlog = 1024; | ||
| 3275 | } else if (order < 3) { | ||
| 3276 | tcp_death_row.sysctl_max_tw_buckets >>= (3 - order); | ||
| 3277 | sysctl_tcp_max_orphans >>= (3 - order); | ||
| 3278 | sysctl_max_syn_backlog = 128; | ||
| 3279 | } | ||
| 3280 | 3268 | ||
| 3281 | /* Set the pressure threshold to be a fraction of global memory that | 3269 | /* Set the pressure threshold to be a fraction of global memory that |
| 3282 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of | 3270 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 0ec9bd0ae94f..850c737e08e2 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -196,10 +196,10 @@ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen) | |||
| 196 | int tcp_set_allowed_congestion_control(char *val) | 196 | int tcp_set_allowed_congestion_control(char *val) |
| 197 | { | 197 | { |
| 198 | struct tcp_congestion_ops *ca; | 198 | struct tcp_congestion_ops *ca; |
| 199 | char *clone, *name; | 199 | char *saved_clone, *clone, *name; |
| 200 | int ret = 0; | 200 | int ret = 0; |
| 201 | 201 | ||
| 202 | clone = kstrdup(val, GFP_USER); | 202 | saved_clone = clone = kstrdup(val, GFP_USER); |
| 203 | if (!clone) | 203 | if (!clone) |
| 204 | return -ENOMEM; | 204 | return -ENOMEM; |
| 205 | 205 | ||
| @@ -226,6 +226,7 @@ int tcp_set_allowed_congestion_control(char *val) | |||
| 226 | } | 226 | } |
| 227 | out: | 227 | out: |
| 228 | spin_unlock(&tcp_cong_list_lock); | 228 | spin_unlock(&tcp_cong_list_lock); |
| 229 | kfree(saved_clone); | ||
| 229 | 230 | ||
| 230 | return ret; | 231 | return ret; |
| 231 | } | 232 | } |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 808bb920c9f5..c35b469e851c 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
| @@ -66,18 +66,18 @@ static void tcp_write_err(struct sock *sk) | |||
| 66 | static int tcp_out_of_resources(struct sock *sk, int do_reset) | 66 | static int tcp_out_of_resources(struct sock *sk, int do_reset) |
| 67 | { | 67 | { |
| 68 | struct tcp_sock *tp = tcp_sk(sk); | 68 | struct tcp_sock *tp = tcp_sk(sk); |
| 69 | int orphans = percpu_counter_read_positive(&tcp_orphan_count); | 69 | int shift = 0; |
| 70 | 70 | ||
| 71 | /* If peer does not open window for long time, or did not transmit | 71 | /* If peer does not open window for long time, or did not transmit |
| 72 | * anything for long time, penalize it. */ | 72 | * anything for long time, penalize it. */ |
| 73 | if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset) | 73 | if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset) |
| 74 | orphans <<= 1; | 74 | shift++; |
| 75 | 75 | ||
| 76 | /* If some dubious ICMP arrived, penalize even more. */ | 76 | /* If some dubious ICMP arrived, penalize even more. */ |
| 77 | if (sk->sk_err_soft) | 77 | if (sk->sk_err_soft) |
| 78 | orphans <<= 1; | 78 | shift++; |
| 79 | 79 | ||
| 80 | if (tcp_too_many_orphans(sk, orphans)) { | 80 | if (tcp_too_many_orphans(sk, shift)) { |
| 81 | if (net_ratelimit()) | 81 | if (net_ratelimit()) |
| 82 | printk(KERN_INFO "Out of socket memory\n"); | 82 | printk(KERN_INFO "Out of socket memory\n"); |
| 83 | 83 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 32e0bef60d0a..fb23c2e63b52 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk) | |||
| 1260 | } | 1260 | } |
| 1261 | EXPORT_SYMBOL(udp_lib_unhash); | 1261 | EXPORT_SYMBOL(udp_lib_unhash); |
| 1262 | 1262 | ||
| 1263 | /* | ||
| 1264 | * inet_rcv_saddr was changed, we must rehash secondary hash | ||
| 1265 | */ | ||
| 1266 | void udp_lib_rehash(struct sock *sk, u16 newhash) | ||
| 1267 | { | ||
| 1268 | if (sk_hashed(sk)) { | ||
| 1269 | struct udp_table *udptable = sk->sk_prot->h.udp_table; | ||
| 1270 | struct udp_hslot *hslot, *hslot2, *nhslot2; | ||
| 1271 | |||
| 1272 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | ||
| 1273 | nhslot2 = udp_hashslot2(udptable, newhash); | ||
| 1274 | udp_sk(sk)->udp_portaddr_hash = newhash; | ||
| 1275 | if (hslot2 != nhslot2) { | ||
| 1276 | hslot = udp_hashslot(udptable, sock_net(sk), | ||
| 1277 | udp_sk(sk)->udp_port_hash); | ||
| 1278 | /* we must lock primary chain too */ | ||
| 1279 | spin_lock_bh(&hslot->lock); | ||
| 1280 | |||
| 1281 | spin_lock(&hslot2->lock); | ||
| 1282 | hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); | ||
| 1283 | hslot2->count--; | ||
| 1284 | spin_unlock(&hslot2->lock); | ||
| 1285 | |||
| 1286 | spin_lock(&nhslot2->lock); | ||
| 1287 | hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, | ||
| 1288 | &nhslot2->head); | ||
| 1289 | nhslot2->count++; | ||
| 1290 | spin_unlock(&nhslot2->lock); | ||
| 1291 | |||
| 1292 | spin_unlock_bh(&hslot->lock); | ||
| 1293 | } | ||
| 1294 | } | ||
| 1295 | } | ||
| 1296 | EXPORT_SYMBOL(udp_lib_rehash); | ||
| 1297 | |||
| 1298 | static void udp_v4_rehash(struct sock *sk) | ||
| 1299 | { | ||
| 1300 | u16 new_hash = udp4_portaddr_hash(sock_net(sk), | ||
| 1301 | inet_sk(sk)->inet_rcv_saddr, | ||
| 1302 | inet_sk(sk)->inet_num); | ||
| 1303 | udp_lib_rehash(sk, new_hash); | ||
| 1304 | } | ||
| 1305 | |||
| 1263 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1306 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 1264 | { | 1307 | { |
| 1265 | int rc; | 1308 | int rc; |
| @@ -1843,6 +1886,7 @@ struct proto udp_prot = { | |||
| 1843 | .backlog_rcv = __udp_queue_rcv_skb, | 1886 | .backlog_rcv = __udp_queue_rcv_skb, |
| 1844 | .hash = udp_lib_hash, | 1887 | .hash = udp_lib_hash, |
| 1845 | .unhash = udp_lib_unhash, | 1888 | .unhash = udp_lib_unhash, |
| 1889 | .rehash = udp_v4_rehash, | ||
| 1846 | .get_port = udp_v4_get_port, | 1890 | .get_port = udp_v4_get_port, |
| 1847 | .memory_allocated = &udp_memory_allocated, | 1891 | .memory_allocated = &udp_memory_allocated, |
| 1848 | .sysctl_mem = sysctl_udp_mem, | 1892 | .sysctl_mem = sysctl_udp_mem, |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 7d929a22cbc2..ef371aa01ac5 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -105,9 +105,12 @@ ipv4_connected: | |||
| 105 | if (ipv6_addr_any(&np->saddr)) | 105 | if (ipv6_addr_any(&np->saddr)) |
| 106 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); | 106 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); |
| 107 | 107 | ||
| 108 | if (ipv6_addr_any(&np->rcv_saddr)) | 108 | if (ipv6_addr_any(&np->rcv_saddr)) { |
| 109 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, | 109 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, |
| 110 | &np->rcv_saddr); | 110 | &np->rcv_saddr); |
| 111 | if (sk->sk_prot->rehash) | ||
| 112 | sk->sk_prot->rehash(sk); | ||
| 113 | } | ||
| 111 | 114 | ||
| 112 | goto out; | 115 | goto out; |
| 113 | } | 116 | } |
| @@ -181,6 +184,8 @@ ipv4_connected: | |||
| 181 | if (ipv6_addr_any(&np->rcv_saddr)) { | 184 | if (ipv6_addr_any(&np->rcv_saddr)) { |
| 182 | ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); | 185 | ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); |
| 183 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 186 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
| 187 | if (sk->sk_prot->rehash) | ||
| 188 | sk->sk_prot->rehash(sk); | ||
| 184 | } | 189 | } |
| 185 | 190 | ||
| 186 | ip6_dst_store(sk, dst, | 191 | ip6_dst_store(sk, dst, |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 29a7bca29e3f..8e754be92c24 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -1766,6 +1766,9 @@ translate_compat_table(struct net *net, | |||
| 1766 | if (ret != 0) | 1766 | if (ret != 0) |
| 1767 | break; | 1767 | break; |
| 1768 | ++i; | 1768 | ++i; |
| 1769 | if (strcmp(ip6t_get_target(iter1)->u.user.name, | ||
| 1770 | XT_ERROR_TARGET) == 0) | ||
| 1771 | ++newinfo->stacksize; | ||
| 1769 | } | 1772 | } |
| 1770 | if (ret) { | 1773 | if (ret) { |
| 1771 | /* | 1774 | /* |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 13ef5bc05cf5..578f3c1a16db 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb) | |||
| 113 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | 113 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | /* Memory Tracking Functions. */ | ||
| 117 | static void frag_kfree_skb(struct sk_buff *skb) | ||
| 118 | { | ||
| 119 | atomic_sub(skb->truesize, &nf_init_frags.mem); | ||
| 120 | nf_skb_free(skb); | ||
| 121 | kfree_skb(skb); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* Destruction primitives. */ | 116 | /* Destruction primitives. */ |
| 125 | 117 | ||
| 126 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) | 118 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) |
| @@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 282 | } | 274 | } |
| 283 | 275 | ||
| 284 | found: | 276 | found: |
| 285 | /* We found where to put this one. Check for overlap with | 277 | /* RFC5722, Section 4: |
| 286 | * preceding fragment, and, if needed, align things so that | 278 | * When reassembling an IPv6 datagram, if |
| 287 | * any overlaps are eliminated. | 279 | * one or more its constituent fragments is determined to be an |
| 288 | */ | 280 | * overlapping fragment, the entire datagram (and any constituent |
| 289 | if (prev) { | 281 | * fragments, including those not yet received) MUST be silently |
| 290 | int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset; | 282 | * discarded. |
| 291 | |||
| 292 | if (i > 0) { | ||
| 293 | offset += i; | ||
| 294 | if (end <= offset) { | ||
| 295 | pr_debug("overlap\n"); | ||
| 296 | goto err; | ||
| 297 | } | ||
| 298 | if (!pskb_pull(skb, i)) { | ||
| 299 | pr_debug("Can't pull\n"); | ||
| 300 | goto err; | ||
| 301 | } | ||
| 302 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
| 303 | skb->ip_summed = CHECKSUM_NONE; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /* Look for overlap with succeeding segments. | ||
| 308 | * If we can merge fragments, do it. | ||
| 309 | */ | 283 | */ |
| 310 | while (next && NFCT_FRAG6_CB(next)->offset < end) { | ||
| 311 | /* overlap is 'i' bytes */ | ||
| 312 | int i = end - NFCT_FRAG6_CB(next)->offset; | ||
| 313 | |||
| 314 | if (i < next->len) { | ||
| 315 | /* Eat head of the next overlapped fragment | ||
| 316 | * and leave the loop. The next ones cannot overlap. | ||
| 317 | */ | ||
| 318 | pr_debug("Eat head of the overlapped parts.: %d", i); | ||
| 319 | if (!pskb_pull(next, i)) | ||
| 320 | goto err; | ||
| 321 | 284 | ||
| 322 | /* next fragment */ | 285 | /* Check for overlap with preceding fragment. */ |
| 323 | NFCT_FRAG6_CB(next)->offset += i; | 286 | if (prev && |
| 324 | fq->q.meat -= i; | 287 | (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0) |
| 325 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 288 | goto discard_fq; |
| 326 | next->ip_summed = CHECKSUM_NONE; | ||
| 327 | break; | ||
| 328 | } else { | ||
| 329 | struct sk_buff *free_it = next; | ||
| 330 | |||
| 331 | /* Old fragmnet is completely overridden with | ||
| 332 | * new one drop it. | ||
| 333 | */ | ||
| 334 | next = next->next; | ||
| 335 | 289 | ||
| 336 | if (prev) | 290 | /* Look for overlap with succeeding segment. */ |
| 337 | prev->next = next; | 291 | if (next && NFCT_FRAG6_CB(next)->offset < end) |
| 338 | else | 292 | goto discard_fq; |
| 339 | fq->q.fragments = next; | ||
| 340 | |||
| 341 | fq->q.meat -= free_it->len; | ||
| 342 | frag_kfree_skb(free_it); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | 293 | ||
| 346 | NFCT_FRAG6_CB(skb)->offset = offset; | 294 | NFCT_FRAG6_CB(skb)->offset = offset; |
| 347 | 295 | ||
| @@ -371,6 +319,8 @@ found: | |||
| 371 | write_unlock(&nf_frags.lock); | 319 | write_unlock(&nf_frags.lock); |
| 372 | return 0; | 320 | return 0; |
| 373 | 321 | ||
| 322 | discard_fq: | ||
| 323 | fq_kill(fq); | ||
| 374 | err: | 324 | err: |
| 375 | return -1; | 325 | return -1; |
| 376 | } | 326 | } |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 545c4141b755..64cfef1b0a4c 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -149,13 +149,6 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a) | |||
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL(ip6_frag_match); | 150 | EXPORT_SYMBOL(ip6_frag_match); |
| 151 | 151 | ||
| 152 | /* Memory Tracking Functions. */ | ||
| 153 | static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb) | ||
| 154 | { | ||
| 155 | atomic_sub(skb->truesize, &nf->mem); | ||
| 156 | kfree_skb(skb); | ||
| 157 | } | ||
| 158 | |||
| 159 | void ip6_frag_init(struct inet_frag_queue *q, void *a) | 152 | void ip6_frag_init(struct inet_frag_queue *q, void *a) |
| 160 | { | 153 | { |
| 161 | struct frag_queue *fq = container_of(q, struct frag_queue, q); | 154 | struct frag_queue *fq = container_of(q, struct frag_queue, q); |
| @@ -346,58 +339,22 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 346 | } | 339 | } |
| 347 | 340 | ||
| 348 | found: | 341 | found: |
| 349 | /* We found where to put this one. Check for overlap with | 342 | /* RFC5722, Section 4: |
| 350 | * preceding fragment, and, if needed, align things so that | 343 | * When reassembling an IPv6 datagram, if |
| 351 | * any overlaps are eliminated. | 344 | * one or more its constituent fragments is determined to be an |
| 345 | * overlapping fragment, the entire datagram (and any constituent | ||
| 346 | * fragments, including those not yet received) MUST be silently | ||
| 347 | * discarded. | ||
| 352 | */ | 348 | */ |
| 353 | if (prev) { | ||
| 354 | int i = (FRAG6_CB(prev)->offset + prev->len) - offset; | ||
| 355 | 349 | ||
| 356 | if (i > 0) { | 350 | /* Check for overlap with preceding fragment. */ |
| 357 | offset += i; | 351 | if (prev && |
| 358 | if (end <= offset) | 352 | (FRAG6_CB(prev)->offset + prev->len) - offset > 0) |
| 359 | goto err; | 353 | goto discard_fq; |
| 360 | if (!pskb_pull(skb, i)) | ||
| 361 | goto err; | ||
| 362 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
| 363 | skb->ip_summed = CHECKSUM_NONE; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | 354 | ||
| 367 | /* Look for overlap with succeeding segments. | 355 | /* Look for overlap with succeeding segment. */ |
| 368 | * If we can merge fragments, do it. | 356 | if (next && FRAG6_CB(next)->offset < end) |
| 369 | */ | 357 | goto discard_fq; |
| 370 | while (next && FRAG6_CB(next)->offset < end) { | ||
| 371 | int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */ | ||
| 372 | |||
| 373 | if (i < next->len) { | ||
| 374 | /* Eat head of the next overlapped fragment | ||
| 375 | * and leave the loop. The next ones cannot overlap. | ||
| 376 | */ | ||
| 377 | if (!pskb_pull(next, i)) | ||
| 378 | goto err; | ||
| 379 | FRAG6_CB(next)->offset += i; /* next fragment */ | ||
| 380 | fq->q.meat -= i; | ||
| 381 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | ||
| 382 | next->ip_summed = CHECKSUM_NONE; | ||
| 383 | break; | ||
| 384 | } else { | ||
| 385 | struct sk_buff *free_it = next; | ||
| 386 | |||
| 387 | /* Old fragment is completely overridden with | ||
| 388 | * new one drop it. | ||
| 389 | */ | ||
| 390 | next = next->next; | ||
| 391 | |||
| 392 | if (prev) | ||
| 393 | prev->next = next; | ||
| 394 | else | ||
| 395 | fq->q.fragments = next; | ||
| 396 | |||
| 397 | fq->q.meat -= free_it->len; | ||
| 398 | frag_kfree_skb(fq->q.net, free_it); | ||
| 399 | } | ||
| 400 | } | ||
| 401 | 358 | ||
| 402 | FRAG6_CB(skb)->offset = offset; | 359 | FRAG6_CB(skb)->offset = offset; |
| 403 | 360 | ||
| @@ -436,6 +393,8 @@ found: | |||
| 436 | write_unlock(&ip6_frags.lock); | 393 | write_unlock(&ip6_frags.lock); |
| 437 | return -1; | 394 | return -1; |
| 438 | 395 | ||
| 396 | discard_fq: | ||
| 397 | fq_kill(fq); | ||
| 439 | err: | 398 | err: |
| 440 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 399 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
| 441 | IPSTATS_MIB_REASMFAILS); | 400 | IPSTATS_MIB_REASMFAILS); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1dd1affdead2..5acb3560ff15 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
| 111 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); | 111 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static void udp_v6_rehash(struct sock *sk) | ||
| 115 | { | ||
| 116 | u16 new_hash = udp6_portaddr_hash(sock_net(sk), | ||
| 117 | &inet6_sk(sk)->rcv_saddr, | ||
| 118 | inet_sk(sk)->inet_num); | ||
| 119 | |||
| 120 | udp_lib_rehash(sk, new_hash); | ||
| 121 | } | ||
| 122 | |||
| 114 | static inline int compute_score(struct sock *sk, struct net *net, | 123 | static inline int compute_score(struct sock *sk, struct net *net, |
| 115 | unsigned short hnum, | 124 | unsigned short hnum, |
| 116 | struct in6_addr *saddr, __be16 sport, | 125 | struct in6_addr *saddr, __be16 sport, |
| @@ -1447,6 +1456,7 @@ struct proto udpv6_prot = { | |||
| 1447 | .backlog_rcv = udpv6_queue_rcv_skb, | 1456 | .backlog_rcv = udpv6_queue_rcv_skb, |
| 1448 | .hash = udp_lib_hash, | 1457 | .hash = udp_lib_hash, |
| 1449 | .unhash = udp_lib_unhash, | 1458 | .unhash = udp_lib_unhash, |
| 1459 | .rehash = udp_v6_rehash, | ||
| 1450 | .get_port = udp_v6_get_port, | 1460 | .get_port = udp_v6_get_port, |
| 1451 | .memory_allocated = &udp_memory_allocated, | 1461 | .memory_allocated = &udp_memory_allocated, |
| 1452 | .sysctl_mem = sysctl_udp_mem, | 1462 | .sysctl_mem = sysctl_udp_mem, |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 79986a674f6e..fd55b5135de5 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
| @@ -824,8 +824,8 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 824 | 824 | ||
| 825 | err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); | 825 | err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); |
| 826 | if (err < 0) { | 826 | if (err < 0) { |
| 827 | kfree(self->ias_obj->name); | 827 | irias_delete_object(self->ias_obj); |
| 828 | kfree(self->ias_obj); | 828 | self->ias_obj = NULL; |
| 829 | goto out; | 829 | goto out; |
| 830 | } | 830 | } |
| 831 | 831 | ||
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index a788f9e9427d..6130f9d9dbe1 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
| @@ -1102,7 +1102,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) | |||
| 1102 | memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */ | 1102 | memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */ |
| 1103 | le16_to_cpus(&val_len); n+=2; | 1103 | le16_to_cpus(&val_len); n+=2; |
| 1104 | 1104 | ||
| 1105 | if (val_len > 1016) { | 1105 | if (val_len >= 1016) { |
| 1106 | IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ ); | 1106 | IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ ); |
| 1107 | return -RSP_INVALID_COMMAND_FORMAT; | 1107 | return -RSP_INVALID_COMMAND_FORMAT; |
| 1108 | } | 1108 | } |
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 9616c32d1076..5bb8353105cc 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c | |||
| @@ -169,6 +169,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, | |||
| 169 | { | 169 | { |
| 170 | struct irlan_cb *self = netdev_priv(dev); | 170 | struct irlan_cb *self = netdev_priv(dev); |
| 171 | int ret; | 171 | int ret; |
| 172 | unsigned int len; | ||
| 172 | 173 | ||
| 173 | /* skb headroom large enough to contain all IrDA-headers? */ | 174 | /* skb headroom large enough to contain all IrDA-headers? */ |
| 174 | if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) { | 175 | if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) { |
| @@ -188,6 +189,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, | |||
| 188 | 189 | ||
| 189 | dev->trans_start = jiffies; | 190 | dev->trans_start = jiffies; |
| 190 | 191 | ||
| 192 | len = skb->len; | ||
| 191 | /* Now queue the packet in the transport layer */ | 193 | /* Now queue the packet in the transport layer */ |
| 192 | if (self->use_udata) | 194 | if (self->use_udata) |
| 193 | ret = irttp_udata_request(self->tsap_data, skb); | 195 | ret = irttp_udata_request(self->tsap_data, skb); |
| @@ -209,7 +211,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, | |||
| 209 | self->stats.tx_dropped++; | 211 | self->stats.tx_dropped++; |
| 210 | } else { | 212 | } else { |
| 211 | self->stats.tx_packets++; | 213 | self->stats.tx_packets++; |
| 212 | self->stats.tx_bytes += skb->len; | 214 | self->stats.tx_bytes += len; |
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | return NETDEV_TX_OK; | 217 | return NETDEV_TX_OK; |
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 58c6c4cda73b..1ae697681bc7 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
| @@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, | |||
| 132 | printk("\n"); | 132 | printk("\n"); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | if (data_len < ETH_HLEN) | 135 | if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) |
| 136 | goto error; | 136 | goto error; |
| 137 | 137 | ||
| 138 | secpath_reset(skb); | 138 | secpath_reset(skb); |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 023ba820236f..582612998211 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
| @@ -1024,7 +1024,8 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, | |||
| 1024 | { | 1024 | { |
| 1025 | struct sock *sk = sock->sk; | 1025 | struct sock *sk = sock->sk; |
| 1026 | struct llc_sock *llc = llc_sk(sk); | 1026 | struct llc_sock *llc = llc_sk(sk); |
| 1027 | int rc = -EINVAL, opt; | 1027 | unsigned int opt; |
| 1028 | int rc = -EINVAL; | ||
| 1028 | 1029 | ||
| 1029 | lock_sock(sk); | 1030 | lock_sock(sk); |
| 1030 | if (unlikely(level != SOL_LLC || optlen != sizeof(int))) | 1031 | if (unlikely(level != SOL_LLC || optlen != sizeof(int))) |
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index e4dae0244d76..cf4aea3ba30f 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c | |||
| @@ -689,7 +689,7 @@ static void llc_station_rcv(struct sk_buff *skb) | |||
| 689 | 689 | ||
| 690 | int __init llc_station_init(void) | 690 | int __init llc_station_init(void) |
| 691 | { | 691 | { |
| 692 | u16 rc = -ENOBUFS; | 692 | int rc = -ENOBUFS; |
| 693 | struct sk_buff *skb; | 693 | struct sk_buff *skb; |
| 694 | struct llc_station_state_ev *ev; | 694 | struct llc_station_state_ev *ev; |
| 695 | 695 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 798a91b100cc..ded5c3843e06 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -732,6 +732,12 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
| 732 | 732 | ||
| 733 | rtnl_unlock(); | 733 | rtnl_unlock(); |
| 734 | 734 | ||
| 735 | /* | ||
| 736 | * Now all work items will be gone, but the | ||
| 737 | * timer might still be armed, so delete it | ||
| 738 | */ | ||
| 739 | del_timer_sync(&local->work_timer); | ||
| 740 | |||
| 735 | cancel_work_sync(&local->reconfig_filter); | 741 | cancel_work_sync(&local->reconfig_filter); |
| 736 | 742 | ||
| 737 | ieee80211_clear_tx_pending(local); | 743 | ieee80211_clear_tx_pending(local); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 4f8ddba48011..4c2f89df5cce 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -924,6 +924,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
| 924 | 924 | ||
| 925 | ip_vs_out_stats(cp, skb); | 925 | ip_vs_out_stats(cp, skb); |
| 926 | ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); | 926 | ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); |
| 927 | ip_vs_update_conntrack(skb, cp, 0); | ||
| 927 | ip_vs_conn_put(cp); | 928 | ip_vs_conn_put(cp); |
| 928 | 929 | ||
| 929 | skb->ipvs_property = 1; | 930 | skb->ipvs_property = 1; |
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index f228a17ec649..7e9af5b76d9e 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include <linux/netfilter.h> | 45 | #include <linux/netfilter.h> |
| 46 | #include <net/netfilter/nf_conntrack.h> | 46 | #include <net/netfilter/nf_conntrack.h> |
| 47 | #include <net/netfilter/nf_conntrack_expect.h> | 47 | #include <net/netfilter/nf_conntrack_expect.h> |
| 48 | #include <net/netfilter/nf_nat.h> | ||
| 48 | #include <net/netfilter/nf_nat_helper.h> | 49 | #include <net/netfilter/nf_nat_helper.h> |
| 49 | #include <linux/gfp.h> | 50 | #include <linux/gfp.h> |
| 50 | #include <net/protocol.h> | 51 | #include <net/protocol.h> |
| @@ -359,7 +360,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 359 | buf_len = strlen(buf); | 360 | buf_len = strlen(buf); |
| 360 | 361 | ||
| 361 | ct = nf_ct_get(skb, &ctinfo); | 362 | ct = nf_ct_get(skb, &ctinfo); |
| 362 | if (ct && !nf_ct_is_untracked(ct)) { | 363 | if (ct && !nf_ct_is_untracked(ct) && nfct_nat(ct)) { |
| 363 | /* If mangling fails this function will return 0 | 364 | /* If mangling fails this function will return 0 |
| 364 | * which will cause the packet to be dropped. | 365 | * which will cause the packet to be dropped. |
| 365 | * Mangling can only fail under memory pressure, | 366 | * Mangling can only fail under memory pressure, |
| @@ -409,7 +410,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 409 | union nf_inet_addr to; | 410 | union nf_inet_addr to; |
| 410 | __be16 port; | 411 | __be16 port; |
| 411 | struct ip_vs_conn *n_cp; | 412 | struct ip_vs_conn *n_cp; |
| 412 | struct nf_conn *ct; | ||
| 413 | 413 | ||
| 414 | #ifdef CONFIG_IP_VS_IPV6 | 414 | #ifdef CONFIG_IP_VS_IPV6 |
| 415 | /* This application helper doesn't work with IPv6 yet, | 415 | /* This application helper doesn't work with IPv6 yet, |
| @@ -496,11 +496,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 496 | ip_vs_control_add(n_cp, cp); | 496 | ip_vs_control_add(n_cp, cp); |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | ct = (struct nf_conn *)skb->nfct; | ||
| 500 | if (ct && ct != &nf_conntrack_untracked) | ||
| 501 | ip_vs_expect_related(skb, ct, n_cp, | ||
| 502 | IPPROTO_TCP, &n_cp->dport, 1); | ||
| 503 | |||
| 504 | /* | 499 | /* |
| 505 | * Move tunnel to listen state | 500 | * Move tunnel to listen state |
| 506 | */ | 501 | */ |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 21e1a5e9b9d3..49df6bea6a2d 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
| @@ -349,8 +349,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 349 | } | 349 | } |
| 350 | #endif | 350 | #endif |
| 351 | 351 | ||
| 352 | static void | 352 | void |
| 353 | ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp) | 353 | ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin) |
| 354 | { | 354 | { |
| 355 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; | 355 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; |
| 356 | struct nf_conntrack_tuple new_tuple; | 356 | struct nf_conntrack_tuple new_tuple; |
| @@ -365,11 +365,17 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp) | |||
| 365 | * real-server we will see RIP->DIP. | 365 | * real-server we will see RIP->DIP. |
| 366 | */ | 366 | */ |
| 367 | new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; | 367 | new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
| 368 | new_tuple.src.u3 = cp->daddr; | 368 | if (outin) |
| 369 | new_tuple.src.u3 = cp->daddr; | ||
| 370 | else | ||
| 371 | new_tuple.dst.u3 = cp->vaddr; | ||
| 369 | /* | 372 | /* |
| 370 | * This will also take care of UDP and other protocols. | 373 | * This will also take care of UDP and other protocols. |
| 371 | */ | 374 | */ |
| 372 | new_tuple.src.u.tcp.port = cp->dport; | 375 | if (outin) |
| 376 | new_tuple.src.u.tcp.port = cp->dport; | ||
| 377 | else | ||
| 378 | new_tuple.dst.u.tcp.port = cp->vport; | ||
| 373 | nf_conntrack_alter_reply(ct, &new_tuple); | 379 | nf_conntrack_alter_reply(ct, &new_tuple); |
| 374 | } | 380 | } |
| 375 | 381 | ||
| @@ -428,7 +434,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 428 | 434 | ||
| 429 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); | 435 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); |
| 430 | 436 | ||
| 431 | ip_vs_update_conntrack(skb, cp); | 437 | ip_vs_update_conntrack(skb, cp, 1); |
| 432 | 438 | ||
| 433 | /* FIXME: when application helper enlarges the packet and the length | 439 | /* FIXME: when application helper enlarges the packet and the length |
| 434 | is larger than the MTU of outgoing device, there will be still | 440 | is larger than the MTU of outgoing device, there will be still |
| @@ -506,7 +512,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 506 | 512 | ||
| 507 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); | 513 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); |
| 508 | 514 | ||
| 509 | ip_vs_update_conntrack(skb, cp); | 515 | ip_vs_update_conntrack(skb, cp, 1); |
| 510 | 516 | ||
| 511 | /* FIXME: when application helper enlarges the packet and the length | 517 | /* FIXME: when application helper enlarges the packet and the length |
| 512 | is larger than the MTU of outgoing device, there will be still | 518 | is larger than the MTU of outgoing device, there will be still |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 8648a9922aab..cd96ed3ccee4 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1406,7 +1406,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1406 | struct netlink_sock *nlk = nlk_sk(sk); | 1406 | struct netlink_sock *nlk = nlk_sk(sk); |
| 1407 | int noblock = flags&MSG_DONTWAIT; | 1407 | int noblock = flags&MSG_DONTWAIT; |
| 1408 | size_t copied; | 1408 | size_t copied; |
| 1409 | struct sk_buff *skb, *frag __maybe_unused = NULL; | 1409 | struct sk_buff *skb, *data_skb; |
| 1410 | int err; | 1410 | int err; |
| 1411 | 1411 | ||
| 1412 | if (flags&MSG_OOB) | 1412 | if (flags&MSG_OOB) |
| @@ -1418,45 +1418,35 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1418 | if (skb == NULL) | 1418 | if (skb == NULL) |
| 1419 | goto out; | 1419 | goto out; |
| 1420 | 1420 | ||
| 1421 | data_skb = skb; | ||
| 1422 | |||
| 1421 | #ifdef CONFIG_COMPAT_NETLINK_MESSAGES | 1423 | #ifdef CONFIG_COMPAT_NETLINK_MESSAGES |
| 1422 | if (unlikely(skb_shinfo(skb)->frag_list)) { | 1424 | if (unlikely(skb_shinfo(skb)->frag_list)) { |
| 1423 | bool need_compat = !!(flags & MSG_CMSG_COMPAT); | ||
| 1424 | |||
| 1425 | /* | 1425 | /* |
| 1426 | * If this skb has a frag_list, then here that means that | 1426 | * If this skb has a frag_list, then here that means that we |
| 1427 | * we will have to use the frag_list skb for compat tasks | 1427 | * will have to use the frag_list skb's data for compat tasks |
| 1428 | * and the regular skb for non-compat tasks. | 1428 | * and the regular skb's data for normal (non-compat) tasks. |
| 1429 | * | 1429 | * |
| 1430 | * The skb might (and likely will) be cloned, so we can't | 1430 | * If we need to send the compat skb, assign it to the |
| 1431 | * just reset frag_list and go on with things -- we need to | 1431 | * 'data_skb' variable so that it will be used below for data |
| 1432 | * keep that. For the compat case that's easy -- simply get | 1432 | * copying. We keep 'skb' for everything else, including |
| 1433 | * a reference to the compat skb and free the regular one | 1433 | * freeing both later. |
| 1434 | * including the frag. For the non-compat case, we need to | ||
| 1435 | * avoid sending the frag to the user -- so assign NULL but | ||
| 1436 | * restore it below before freeing the skb. | ||
| 1437 | */ | 1434 | */ |
| 1438 | if (need_compat) { | 1435 | if (flags & MSG_CMSG_COMPAT) |
| 1439 | struct sk_buff *compskb = skb_shinfo(skb)->frag_list; | 1436 | data_skb = skb_shinfo(skb)->frag_list; |
| 1440 | skb_get(compskb); | ||
| 1441 | kfree_skb(skb); | ||
| 1442 | skb = compskb; | ||
| 1443 | } else { | ||
| 1444 | frag = skb_shinfo(skb)->frag_list; | ||
| 1445 | skb_shinfo(skb)->frag_list = NULL; | ||
| 1446 | } | ||
| 1447 | } | 1437 | } |
| 1448 | #endif | 1438 | #endif |
| 1449 | 1439 | ||
| 1450 | msg->msg_namelen = 0; | 1440 | msg->msg_namelen = 0; |
| 1451 | 1441 | ||
| 1452 | copied = skb->len; | 1442 | copied = data_skb->len; |
| 1453 | if (len < copied) { | 1443 | if (len < copied) { |
| 1454 | msg->msg_flags |= MSG_TRUNC; | 1444 | msg->msg_flags |= MSG_TRUNC; |
| 1455 | copied = len; | 1445 | copied = len; |
| 1456 | } | 1446 | } |
| 1457 | 1447 | ||
| 1458 | skb_reset_transport_header(skb); | 1448 | skb_reset_transport_header(data_skb); |
| 1459 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 1449 | err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied); |
| 1460 | 1450 | ||
| 1461 | if (msg->msg_name) { | 1451 | if (msg->msg_name) { |
| 1462 | struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; | 1452 | struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; |
| @@ -1476,11 +1466,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1476 | } | 1466 | } |
| 1477 | siocb->scm->creds = *NETLINK_CREDS(skb); | 1467 | siocb->scm->creds = *NETLINK_CREDS(skb); |
| 1478 | if (flags & MSG_TRUNC) | 1468 | if (flags & MSG_TRUNC) |
| 1479 | copied = skb->len; | 1469 | copied = data_skb->len; |
| 1480 | |||
| 1481 | #ifdef CONFIG_COMPAT_NETLINK_MESSAGES | ||
| 1482 | skb_shinfo(skb)->frag_list = frag; | ||
| 1483 | #endif | ||
| 1484 | 1470 | ||
| 1485 | skb_free_datagram(sk, skb); | 1471 | skb_free_datagram(sk, skb); |
| 1486 | 1472 | ||
| @@ -2116,6 +2102,26 @@ static void __net_exit netlink_net_exit(struct net *net) | |||
| 2116 | #endif | 2102 | #endif |
| 2117 | } | 2103 | } |
| 2118 | 2104 | ||
| 2105 | static void __init netlink_add_usersock_entry(void) | ||
| 2106 | { | ||
| 2107 | unsigned long *listeners; | ||
| 2108 | int groups = 32; | ||
| 2109 | |||
| 2110 | listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head), | ||
| 2111 | GFP_KERNEL); | ||
| 2112 | if (!listeners) | ||
| 2113 | panic("netlink_add_usersock_entry: Cannot allocate listneres\n"); | ||
| 2114 | |||
| 2115 | netlink_table_grab(); | ||
| 2116 | |||
| 2117 | nl_table[NETLINK_USERSOCK].groups = groups; | ||
| 2118 | nl_table[NETLINK_USERSOCK].listeners = listeners; | ||
| 2119 | nl_table[NETLINK_USERSOCK].module = THIS_MODULE; | ||
| 2120 | nl_table[NETLINK_USERSOCK].registered = 1; | ||
| 2121 | |||
| 2122 | netlink_table_ungrab(); | ||
| 2123 | } | ||
| 2124 | |||
| 2119 | static struct pernet_operations __net_initdata netlink_net_ops = { | 2125 | static struct pernet_operations __net_initdata netlink_net_ops = { |
| 2120 | .init = netlink_net_init, | 2126 | .init = netlink_net_init, |
| 2121 | .exit = netlink_net_exit, | 2127 | .exit = netlink_net_exit, |
| @@ -2164,6 +2170,8 @@ static int __init netlink_proto_init(void) | |||
| 2164 | hash->rehash_time = jiffies; | 2170 | hash->rehash_time = jiffies; |
| 2165 | } | 2171 | } |
| 2166 | 2172 | ||
| 2173 | netlink_add_usersock_entry(); | ||
| 2174 | |||
| 2167 | sock_register(&netlink_family_ops); | 2175 | sock_register(&netlink_family_ops); |
| 2168 | register_pernet_subsys(&netlink_net_ops); | 2176 | register_pernet_subsys(&netlink_net_ops); |
| 2169 | /* The netlink device handler may be needed early. */ | 2177 | /* The netlink device handler may be needed early. */ |
diff --git a/net/rds/recv.c b/net/rds/recv.c index 795a00b7f2cb..c93588c2d553 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
| @@ -297,7 +297,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, | |||
| 297 | int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msghdr) | 297 | int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msghdr) |
| 298 | { | 298 | { |
| 299 | struct rds_notifier *notifier; | 299 | struct rds_notifier *notifier; |
| 300 | struct rds_rdma_notify cmsg; | 300 | struct rds_rdma_notify cmsg = { 0 }; /* fill holes with zero */ |
| 301 | unsigned int count = 0, max_messages = ~0U; | 301 | unsigned int count = 0, max_messages = ~0U; |
| 302 | unsigned long flags; | 302 | unsigned long flags; |
| 303 | LIST_HEAD(copy); | 303 | LIST_HEAD(copy); |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 537a48732e9e..7ebf7439b478 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
| @@ -350,22 +350,19 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
| 350 | { | 350 | { |
| 351 | unsigned char *b = skb_tail_pointer(skb); | 351 | unsigned char *b = skb_tail_pointer(skb); |
| 352 | struct tcf_police *police = a->priv; | 352 | struct tcf_police *police = a->priv; |
| 353 | struct tc_police opt; | 353 | struct tc_police opt = { |
| 354 | 354 | .index = police->tcf_index, | |
| 355 | opt.index = police->tcf_index; | 355 | .action = police->tcf_action, |
| 356 | opt.action = police->tcf_action; | 356 | .mtu = police->tcfp_mtu, |
| 357 | opt.mtu = police->tcfp_mtu; | 357 | .burst = police->tcfp_burst, |
| 358 | opt.burst = police->tcfp_burst; | 358 | .refcnt = police->tcf_refcnt - ref, |
| 359 | opt.refcnt = police->tcf_refcnt - ref; | 359 | .bindcnt = police->tcf_bindcnt - bind, |
| 360 | opt.bindcnt = police->tcf_bindcnt - bind; | 360 | }; |
| 361 | |||
| 361 | if (police->tcfp_R_tab) | 362 | if (police->tcfp_R_tab) |
| 362 | opt.rate = police->tcfp_R_tab->rate; | 363 | opt.rate = police->tcfp_R_tab->rate; |
| 363 | else | ||
| 364 | memset(&opt.rate, 0, sizeof(opt.rate)); | ||
| 365 | if (police->tcfp_P_tab) | 364 | if (police->tcfp_P_tab) |
| 366 | opt.peakrate = police->tcfp_P_tab->rate; | 365 | opt.peakrate = police->tcfp_P_tab->rate; |
| 367 | else | ||
| 368 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | ||
| 369 | NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); | 366 | NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); |
| 370 | if (police->tcfp_result) | 367 | if (police->tcfp_result) |
| 371 | NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result); | 368 | NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result); |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 340662789529..6318e1136b83 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
| @@ -255,10 +255,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
| 255 | error = -EINVAL; | 255 | error = -EINVAL; |
| 256 | goto err_out; | 256 | goto err_out; |
| 257 | } | 257 | } |
| 258 | if (!list_empty(&flow->list)) { | ||
| 259 | error = -EEXIST; | ||
| 260 | goto err_out; | ||
| 261 | } | ||
| 262 | } else { | 258 | } else { |
| 263 | int i; | 259 | int i; |
| 264 | unsigned long cl; | 260 | unsigned long cl; |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index abd904be4287..47496098d35c 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
| @@ -761,8 +761,8 @@ init_vf(struct hfsc_class *cl, unsigned int len) | |||
| 761 | if (f != cl->cl_f) { | 761 | if (f != cl->cl_f) { |
| 762 | cl->cl_f = f; | 762 | cl->cl_f = f; |
| 763 | cftree_update(cl); | 763 | cftree_update(cl); |
| 764 | update_cfmin(cl->cl_parent); | ||
| 765 | } | 764 | } |
| 765 | update_cfmin(cl->cl_parent); | ||
| 766 | } | 766 | } |
| 767 | } | 767 | } |
| 768 | 768 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index a646681f5acd..bcc4590ccaf2 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
| @@ -92,7 +92,6 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, | |||
| 92 | SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, | 92 | SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, |
| 93 | packet, vtag); | 93 | packet, vtag); |
| 94 | 94 | ||
| 95 | sctp_packet_reset(packet); | ||
| 96 | packet->vtag = vtag; | 95 | packet->vtag = vtag; |
| 97 | 96 | ||
| 98 | if (ecn_capable && sctp_packet_empty(packet)) { | 97 | if (ecn_capable && sctp_packet_empty(packet)) { |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 24b2cd555637..d344dc481ccc 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -1232,6 +1232,18 @@ out: | |||
| 1232 | return 0; | 1232 | return 0; |
| 1233 | } | 1233 | } |
| 1234 | 1234 | ||
| 1235 | static bool list_has_sctp_addr(const struct list_head *list, | ||
| 1236 | union sctp_addr *ipaddr) | ||
| 1237 | { | ||
| 1238 | struct sctp_transport *addr; | ||
| 1239 | |||
| 1240 | list_for_each_entry(addr, list, transports) { | ||
| 1241 | if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr)) | ||
| 1242 | return true; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | return false; | ||
| 1246 | } | ||
| 1235 | /* A restart is occurring, check to make sure no new addresses | 1247 | /* A restart is occurring, check to make sure no new addresses |
| 1236 | * are being added as we may be under a takeover attack. | 1248 | * are being added as we may be under a takeover attack. |
| 1237 | */ | 1249 | */ |
| @@ -1240,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
| 1240 | struct sctp_chunk *init, | 1252 | struct sctp_chunk *init, |
| 1241 | sctp_cmd_seq_t *commands) | 1253 | sctp_cmd_seq_t *commands) |
| 1242 | { | 1254 | { |
| 1243 | struct sctp_transport *new_addr, *addr; | 1255 | struct sctp_transport *new_addr; |
| 1244 | int found; | 1256 | int ret = 1; |
| 1245 | 1257 | ||
| 1246 | /* Implementor's Guide - Sectin 5.2.2 | 1258 | /* Implementor's Guide - Section 5.2.2 |
| 1247 | * ... | 1259 | * ... |
| 1248 | * Before responding the endpoint MUST check to see if the | 1260 | * Before responding the endpoint MUST check to see if the |
| 1249 | * unexpected INIT adds new addresses to the association. If new | 1261 | * unexpected INIT adds new addresses to the association. If new |
| @@ -1254,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
| 1254 | /* Search through all current addresses and make sure | 1266 | /* Search through all current addresses and make sure |
| 1255 | * we aren't adding any new ones. | 1267 | * we aren't adding any new ones. |
| 1256 | */ | 1268 | */ |
| 1257 | new_addr = NULL; | ||
| 1258 | found = 0; | ||
| 1259 | |||
| 1260 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, | 1269 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, |
| 1261 | transports) { | 1270 | transports) { |
| 1262 | found = 0; | 1271 | if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, |
| 1263 | list_for_each_entry(addr, &asoc->peer.transport_addr_list, | 1272 | &new_addr->ipaddr)) { |
| 1264 | transports) { | 1273 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, |
| 1265 | if (sctp_cmp_addr_exact(&new_addr->ipaddr, | 1274 | commands); |
| 1266 | &addr->ipaddr)) { | 1275 | ret = 0; |
| 1267 | found = 1; | ||
| 1268 | break; | ||
| 1269 | } | ||
| 1270 | } | ||
| 1271 | if (!found) | ||
| 1272 | break; | 1276 | break; |
| 1273 | } | 1277 | } |
| 1274 | |||
| 1275 | /* If a new address was added, ABORT the sender. */ | ||
| 1276 | if (!found && new_addr) { | ||
| 1277 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands); | ||
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| 1280 | /* Return success if all addresses were found. */ | 1280 | /* Return success if all addresses were found. */ |
| 1281 | return found; | 1281 | return ret; |
| 1282 | } | 1282 | } |
| 1283 | 1283 | ||
| 1284 | /* Populate the verification/tie tags based on overlapping INIT | 1284 | /* Populate the verification/tie tags based on overlapping INIT |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 36cb66022a27..e9eaaf7d43c1 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
| @@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
| 38 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
| 39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
| 40 | 40 | ||
| 41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (14) |
| 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
| 43 | { | 43 | { |
| 44 | unsigned long num; | 44 | unsigned long num; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index dcfc66bab2bb..12c485982814 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) | |||
| 745 | struct rpc_inode *rpci = RPC_I(inode); | 745 | struct rpc_inode *rpci = RPC_I(inode); |
| 746 | struct gss_upcall_msg *gss_msg; | 746 | struct gss_upcall_msg *gss_msg; |
| 747 | 747 | ||
| 748 | restart: | ||
| 748 | spin_lock(&inode->i_lock); | 749 | spin_lock(&inode->i_lock); |
| 749 | while (!list_empty(&rpci->in_downcall)) { | 750 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { |
| 750 | 751 | ||
| 751 | gss_msg = list_entry(rpci->in_downcall.next, | 752 | if (!list_empty(&gss_msg->msg.list)) |
| 752 | struct gss_upcall_msg, list); | 753 | continue; |
| 753 | gss_msg->msg.errno = -EPIPE; | 754 | gss_msg->msg.errno = -EPIPE; |
| 754 | atomic_inc(&gss_msg->count); | 755 | atomic_inc(&gss_msg->count); |
| 755 | __gss_unhash_msg(gss_msg); | 756 | __gss_unhash_msg(gss_msg); |
| 756 | spin_unlock(&inode->i_lock); | 757 | spin_unlock(&inode->i_lock); |
| 757 | gss_release_msg(gss_msg); | 758 | gss_release_msg(gss_msg); |
| 758 | spin_lock(&inode->i_lock); | 759 | goto restart; |
| 759 | } | 760 | } |
| 760 | spin_unlock(&inode->i_lock); | 761 | spin_unlock(&inode->i_lock); |
| 761 | 762 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 032644610524..778e5dfc5144 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
| @@ -237,6 +237,7 @@ get_key(const void *p, const void *end, | |||
| 237 | if (!supported_gss_krb5_enctype(alg)) { | 237 | if (!supported_gss_krb5_enctype(alg)) { |
| 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " | 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " |
| 239 | "encryption key algorithm %d\n", alg); | 239 | "encryption key algorithm %d\n", alg); |
| 240 | p = ERR_PTR(-EINVAL); | ||
| 240 | goto out_err; | 241 | goto out_err; |
| 241 | } | 242 | } |
| 242 | p = simple_get_netobj(p, end, &key); | 243 | p = simple_get_netobj(p, end, &key); |
| @@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
| 282 | ctx->enctype = ENCTYPE_DES_CBC_RAW; | 283 | ctx->enctype = ENCTYPE_DES_CBC_RAW; |
| 283 | 284 | ||
| 284 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); | 285 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); |
| 285 | if (ctx->gk5e == NULL) | 286 | if (ctx->gk5e == NULL) { |
| 287 | p = ERR_PTR(-EINVAL); | ||
| 286 | goto out_err; | 288 | goto out_err; |
| 289 | } | ||
| 287 | 290 | ||
| 288 | /* The downcall format was designed before we completely understood | 291 | /* The downcall format was designed before we completely understood |
| 289 | * the uses of the context fields; so it includes some stuff we | 292 | * the uses of the context fields; so it includes some stuff we |
| 290 | * just give some minimal sanity-checking, and some we ignore | 293 | * just give some minimal sanity-checking, and some we ignore |
| 291 | * completely (like the next twenty bytes): */ | 294 | * completely (like the next twenty bytes): */ |
| 292 | if (unlikely(p + 20 > end || p + 20 < p)) | 295 | if (unlikely(p + 20 > end || p + 20 < p)) { |
| 296 | p = ERR_PTR(-EFAULT); | ||
| 293 | goto out_err; | 297 | goto out_err; |
| 298 | } | ||
| 294 | p += 20; | 299 | p += 20; |
| 295 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); | 300 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); |
| 296 | if (IS_ERR(p)) | 301 | if (IS_ERR(p)) |
| @@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, | |||
| 619 | if (ctx->seq_send64 != ctx->seq_send) { | 624 | if (ctx->seq_send64 != ctx->seq_send) { |
| 620 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, | 625 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, |
| 621 | (long unsigned)ctx->seq_send64, ctx->seq_send); | 626 | (long unsigned)ctx->seq_send64, ctx->seq_send); |
| 627 | p = ERR_PTR(-EINVAL); | ||
| 622 | goto out_err; | 628 | goto out_err; |
| 623 | } | 629 | } |
| 624 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); | 630 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index dc3f1f5ed865..adade3d313f2 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
| @@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 100 | if (version != 1) { | 100 | if (version != 1) { |
| 101 | dprintk("RPC: unknown spkm3 token format: " | 101 | dprintk("RPC: unknown spkm3 token format: " |
| 102 | "obsolete nfs-utils?\n"); | 102 | "obsolete nfs-utils?\n"); |
| 103 | p = ERR_PTR(-EINVAL); | ||
| 103 | goto out_err_free_ctx; | 104 | goto out_err_free_ctx; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| @@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 135 | if (IS_ERR(p)) | 136 | if (IS_ERR(p)) |
| 136 | goto out_err_free_intg_alg; | 137 | goto out_err_free_intg_alg; |
| 137 | 138 | ||
| 138 | if (p != end) | 139 | if (p != end) { |
| 140 | p = ERR_PTR(-EFAULT); | ||
| 139 | goto out_err_free_intg_key; | 141 | goto out_err_free_intg_key; |
| 142 | } | ||
| 140 | 143 | ||
| 141 | ctx_id->internal_ctx_id = ctx; | 144 | ctx_id->internal_ctx_id = ctx; |
| 142 | 145 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2388d83b68ff..fa5549079d79 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
| 226 | goto out_no_principal; | 226 | goto out_no_principal; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | kref_init(&clnt->cl_kref); | 229 | atomic_set(&clnt->cl_count, 1); |
| 230 | 230 | ||
| 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
| 232 | if (err < 0) | 232 | if (err < 0) |
| @@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
| 390 | if (new->cl_principal == NULL) | 390 | if (new->cl_principal == NULL) |
| 391 | goto out_no_principal; | 391 | goto out_no_principal; |
| 392 | } | 392 | } |
| 393 | kref_init(&new->cl_kref); | 393 | atomic_set(&new->cl_count, 1); |
| 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
| 395 | if (err != 0) | 395 | if (err != 0) |
| 396 | goto out_no_path; | 396 | goto out_no_path; |
| 397 | if (new->cl_auth) | 397 | if (new->cl_auth) |
| 398 | atomic_inc(&new->cl_auth->au_count); | 398 | atomic_inc(&new->cl_auth->au_count); |
| 399 | xprt_get(clnt->cl_xprt); | 399 | xprt_get(clnt->cl_xprt); |
| 400 | kref_get(&clnt->cl_kref); | 400 | atomic_inc(&clnt->cl_count); |
| 401 | rpc_register_client(new); | 401 | rpc_register_client(new); |
| 402 | rpciod_up(); | 402 | rpciod_up(); |
| 403 | return new; | 403 | return new; |
| @@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
| 465 | * Free an RPC client | 465 | * Free an RPC client |
| 466 | */ | 466 | */ |
| 467 | static void | 467 | static void |
| 468 | rpc_free_client(struct kref *kref) | 468 | rpc_free_client(struct rpc_clnt *clnt) |
| 469 | { | 469 | { |
| 470 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 471 | |||
| 472 | dprintk("RPC: destroying %s client for %s\n", | 470 | dprintk("RPC: destroying %s client for %s\n", |
| 473 | clnt->cl_protname, clnt->cl_server); | 471 | clnt->cl_protname, clnt->cl_server); |
| 474 | if (!IS_ERR(clnt->cl_path.dentry)) { | 472 | if (!IS_ERR(clnt->cl_path.dentry)) { |
| @@ -495,12 +493,10 @@ out_free: | |||
| 495 | * Free an RPC client | 493 | * Free an RPC client |
| 496 | */ | 494 | */ |
| 497 | static void | 495 | static void |
| 498 | rpc_free_auth(struct kref *kref) | 496 | rpc_free_auth(struct rpc_clnt *clnt) |
| 499 | { | 497 | { |
| 500 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 501 | |||
| 502 | if (clnt->cl_auth == NULL) { | 498 | if (clnt->cl_auth == NULL) { |
| 503 | rpc_free_client(kref); | 499 | rpc_free_client(clnt); |
| 504 | return; | 500 | return; |
| 505 | } | 501 | } |
| 506 | 502 | ||
| @@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) | |||
| 509 | * release remaining GSS contexts. This mechanism ensures | 505 | * release remaining GSS contexts. This mechanism ensures |
| 510 | * that it can do so safely. | 506 | * that it can do so safely. |
| 511 | */ | 507 | */ |
| 512 | kref_init(kref); | 508 | atomic_inc(&clnt->cl_count); |
| 513 | rpcauth_release(clnt->cl_auth); | 509 | rpcauth_release(clnt->cl_auth); |
| 514 | clnt->cl_auth = NULL; | 510 | clnt->cl_auth = NULL; |
| 515 | kref_put(kref, rpc_free_client); | 511 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 512 | rpc_free_client(clnt); | ||
| 516 | } | 513 | } |
| 517 | 514 | ||
| 518 | /* | 515 | /* |
| @@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
| 525 | 522 | ||
| 526 | if (list_empty(&clnt->cl_tasks)) | 523 | if (list_empty(&clnt->cl_tasks)) |
| 527 | wake_up(&destroy_wait); | 524 | wake_up(&destroy_wait); |
| 528 | kref_put(&clnt->cl_kref, rpc_free_auth); | 525 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 526 | rpc_free_auth(clnt); | ||
| 529 | } | 527 | } |
| 530 | 528 | ||
| 531 | /** | 529 | /** |
| @@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
| 588 | if (clnt != NULL) { | 586 | if (clnt != NULL) { |
| 589 | rpc_task_release_client(task); | 587 | rpc_task_release_client(task); |
| 590 | task->tk_client = clnt; | 588 | task->tk_client = clnt; |
| 591 | kref_get(&clnt->cl_kref); | 589 | atomic_inc(&clnt->cl_count); |
| 592 | if (clnt->cl_softrtry) | 590 | if (clnt->cl_softrtry) |
| 593 | task->tk_flags |= RPC_TASK_SOFT; | 591 | task->tk_flags |= RPC_TASK_SOFT; |
| 594 | /* Add to the client's list of all tasks */ | 592 | /* Add to the client's list of all tasks */ |
| @@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task) | |||
| 931 | task->tk_status = 0; | 929 | task->tk_status = 0; |
| 932 | if (status >= 0) { | 930 | if (status >= 0) { |
| 933 | if (task->tk_rqstp) { | 931 | if (task->tk_rqstp) { |
| 934 | task->tk_action = call_allocate; | 932 | task->tk_action = call_refresh; |
| 935 | return; | 933 | return; |
| 936 | } | 934 | } |
| 937 | 935 | ||
| @@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task) | |||
| 966 | } | 964 | } |
| 967 | 965 | ||
| 968 | /* | 966 | /* |
| 969 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. | 967 | * 2. Bind and/or refresh the credentials |
| 968 | */ | ||
| 969 | static void | ||
| 970 | call_refresh(struct rpc_task *task) | ||
| 971 | { | ||
| 972 | dprint_status(task); | ||
| 973 | |||
| 974 | task->tk_action = call_refreshresult; | ||
| 975 | task->tk_status = 0; | ||
| 976 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 977 | rpcauth_refreshcred(task); | ||
| 978 | } | ||
| 979 | |||
| 980 | /* | ||
| 981 | * 2a. Process the results of a credential refresh | ||
| 982 | */ | ||
| 983 | static void | ||
| 984 | call_refreshresult(struct rpc_task *task) | ||
| 985 | { | ||
| 986 | int status = task->tk_status; | ||
| 987 | |||
| 988 | dprint_status(task); | ||
| 989 | |||
| 990 | task->tk_status = 0; | ||
| 991 | task->tk_action = call_allocate; | ||
| 992 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 993 | return; | ||
| 994 | switch (status) { | ||
| 995 | case -EACCES: | ||
| 996 | rpc_exit(task, -EACCES); | ||
| 997 | return; | ||
| 998 | case -ENOMEM: | ||
| 999 | rpc_exit(task, -ENOMEM); | ||
| 1000 | return; | ||
| 1001 | case -ETIMEDOUT: | ||
| 1002 | rpc_delay(task, 3*HZ); | ||
| 1003 | } | ||
| 1004 | task->tk_action = call_refresh; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. | ||
| 970 | * (Note: buffer memory is freed in xprt_release). | 1009 | * (Note: buffer memory is freed in xprt_release). |
| 971 | */ | 1010 | */ |
| 972 | static void | 1011 | static void |
| 973 | call_allocate(struct rpc_task *task) | 1012 | call_allocate(struct rpc_task *task) |
| 974 | { | 1013 | { |
| 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; | 1014 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; |
| 976 | struct rpc_rqst *req = task->tk_rqstp; | 1015 | struct rpc_rqst *req = task->tk_rqstp; |
| 977 | struct rpc_xprt *xprt = task->tk_xprt; | 1016 | struct rpc_xprt *xprt = task->tk_xprt; |
| 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1017 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
| @@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task) | |||
| 980 | dprint_status(task); | 1019 | dprint_status(task); |
| 981 | 1020 | ||
| 982 | task->tk_status = 0; | 1021 | task->tk_status = 0; |
| 983 | task->tk_action = call_refresh; | 1022 | task->tk_action = call_bind; |
| 984 | 1023 | ||
| 985 | if (req->rq_buffer) | 1024 | if (req->rq_buffer) |
| 986 | return; | 1025 | return; |
| @@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task) | |||
| 1017 | rpc_exit(task, -ERESTARTSYS); | 1056 | rpc_exit(task, -ERESTARTSYS); |
| 1018 | } | 1057 | } |
| 1019 | 1058 | ||
| 1020 | /* | ||
| 1021 | * 2a. Bind and/or refresh the credentials | ||
| 1022 | */ | ||
| 1023 | static void | ||
| 1024 | call_refresh(struct rpc_task *task) | ||
| 1025 | { | ||
| 1026 | dprint_status(task); | ||
| 1027 | |||
| 1028 | task->tk_action = call_refreshresult; | ||
| 1029 | task->tk_status = 0; | ||
| 1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 1031 | rpcauth_refreshcred(task); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | /* | ||
| 1035 | * 2b. Process the results of a credential refresh | ||
| 1036 | */ | ||
| 1037 | static void | ||
| 1038 | call_refreshresult(struct rpc_task *task) | ||
| 1039 | { | ||
| 1040 | int status = task->tk_status; | ||
| 1041 | |||
| 1042 | dprint_status(task); | ||
| 1043 | |||
| 1044 | task->tk_status = 0; | ||
| 1045 | task->tk_action = call_bind; | ||
| 1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 1047 | return; | ||
| 1048 | switch (status) { | ||
| 1049 | case -EACCES: | ||
| 1050 | rpc_exit(task, -EACCES); | ||
| 1051 | return; | ||
| 1052 | case -ENOMEM: | ||
| 1053 | rpc_exit(task, -ENOMEM); | ||
| 1054 | return; | ||
| 1055 | case -ETIMEDOUT: | ||
| 1056 | rpc_delay(task, 3*HZ); | ||
| 1057 | } | ||
| 1058 | task->tk_action = call_refresh; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | static inline int | 1059 | static inline int |
| 1062 | rpc_task_need_encode(struct rpc_task *task) | 1060 | rpc_task_need_encode(struct rpc_task *task) |
| 1063 | { | 1061 | { |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf45d3e..8c8eef2b8f26 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
| 48 | return; | 48 | return; |
| 49 | do { | 49 | do { |
| 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
| 51 | list_del(&msg->list); | 51 | list_del_init(&msg->list); |
| 52 | msg->errno = err; | 52 | msg->errno = err; |
| 53 | destroy_msg(msg); | 53 | destroy_msg(msg); |
| 54 | } while (!list_empty(head)); | 54 | } while (!list_empty(head)); |
| @@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
| 208 | if (msg != NULL) { | 208 | if (msg != NULL) { |
| 209 | spin_lock(&inode->i_lock); | 209 | spin_lock(&inode->i_lock); |
| 210 | msg->errno = -EAGAIN; | 210 | msg->errno = -EAGAIN; |
| 211 | list_del(&msg->list); | 211 | list_del_init(&msg->list); |
| 212 | spin_unlock(&inode->i_lock); | 212 | spin_unlock(&inode->i_lock); |
| 213 | rpci->ops->destroy_msg(msg); | 213 | rpci->ops->destroy_msg(msg); |
| 214 | } | 214 | } |
| @@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
| 268 | if (res < 0 || msg->len == msg->copied) { | 268 | if (res < 0 || msg->len == msg->copied) { |
| 269 | filp->private_data = NULL; | 269 | filp->private_data = NULL; |
| 270 | spin_lock(&inode->i_lock); | 270 | spin_lock(&inode->i_lock); |
| 271 | list_del(&msg->list); | 271 | list_del_init(&msg->list); |
| 272 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
| 273 | rpci->ops->destroy_msg(msg); | 273 | rpci->ops->destroy_msg(msg); |
| 274 | } | 274 | } |
| @@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) | |||
| 371 | static int | 371 | static int |
| 372 | rpc_info_open(struct inode *inode, struct file *file) | 372 | rpc_info_open(struct inode *inode, struct file *file) |
| 373 | { | 373 | { |
| 374 | struct rpc_clnt *clnt; | 374 | struct rpc_clnt *clnt = NULL; |
| 375 | int ret = single_open(file, rpc_show_info, NULL); | 375 | int ret = single_open(file, rpc_show_info, NULL); |
| 376 | 376 | ||
| 377 | if (!ret) { | 377 | if (!ret) { |
| 378 | struct seq_file *m = file->private_data; | 378 | struct seq_file *m = file->private_data; |
| 379 | mutex_lock(&inode->i_mutex); | 379 | |
| 380 | clnt = RPC_I(inode)->private; | 380 | spin_lock(&file->f_path.dentry->d_lock); |
| 381 | if (clnt) { | 381 | if (!d_unhashed(file->f_path.dentry)) |
| 382 | kref_get(&clnt->cl_kref); | 382 | clnt = RPC_I(inode)->private; |
| 383 | if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { | ||
| 384 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 383 | m->private = clnt; | 385 | m->private = clnt; |
| 384 | } else { | 386 | } else { |
| 387 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 385 | single_release(inode, file); | 388 | single_release(inode, file); |
| 386 | ret = -EINVAL; | 389 | ret = -EINVAL; |
| 387 | } | 390 | } |
| 388 | mutex_unlock(&inode->i_mutex); | ||
| 389 | } | 391 | } |
| 390 | return ret; | 392 | return ret; |
| 391 | } | 393 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4414a18c63b4..0b39b2451ea5 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -692,6 +692,7 @@ static int unix_autobind(struct socket *sock) | |||
| 692 | static u32 ordernum = 1; | 692 | static u32 ordernum = 1; |
| 693 | struct unix_address *addr; | 693 | struct unix_address *addr; |
| 694 | int err; | 694 | int err; |
| 695 | unsigned int retries = 0; | ||
| 695 | 696 | ||
| 696 | mutex_lock(&u->readlock); | 697 | mutex_lock(&u->readlock); |
| 697 | 698 | ||
| @@ -717,9 +718,17 @@ retry: | |||
| 717 | if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, | 718 | if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, |
| 718 | addr->hash)) { | 719 | addr->hash)) { |
| 719 | spin_unlock(&unix_table_lock); | 720 | spin_unlock(&unix_table_lock); |
| 720 | /* Sanity yield. It is unusual case, but yet... */ | 721 | /* |
| 721 | if (!(ordernum&0xFF)) | 722 | * __unix_find_socket_byname() may take long time if many names |
| 722 | yield(); | 723 | * are already in use. |
| 724 | */ | ||
| 725 | cond_resched(); | ||
| 726 | /* Give up if all names seems to be in use. */ | ||
| 727 | if (retries++ == 0xFFFFF) { | ||
| 728 | err = -ENOSPC; | ||
| 729 | kfree(addr); | ||
| 730 | goto out; | ||
| 731 | } | ||
| 723 | goto retry; | 732 | goto retry; |
| 724 | } | 733 | } |
| 725 | addr->hash ^= sk->sk_type; | 734 | addr->hash ^= sk->sk_type; |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 541e2fff5e9c..d6d046b9f6f2 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -475,12 +475,10 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 475 | mutex_lock(&cfg80211_mutex); | 475 | mutex_lock(&cfg80211_mutex); |
| 476 | 476 | ||
| 477 | res = device_add(&rdev->wiphy.dev); | 477 | res = device_add(&rdev->wiphy.dev); |
| 478 | if (res) | 478 | if (res) { |
| 479 | goto out_unlock; | 479 | mutex_unlock(&cfg80211_mutex); |
| 480 | 480 | return res; | |
| 481 | res = rfkill_register(rdev->rfkill); | 481 | } |
| 482 | if (res) | ||
| 483 | goto out_rm_dev; | ||
| 484 | 482 | ||
| 485 | /* set up regulatory info */ | 483 | /* set up regulatory info */ |
| 486 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); | 484 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); |
| @@ -509,13 +507,18 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 509 | cfg80211_debugfs_rdev_add(rdev); | 507 | cfg80211_debugfs_rdev_add(rdev); |
| 510 | mutex_unlock(&cfg80211_mutex); | 508 | mutex_unlock(&cfg80211_mutex); |
| 511 | 509 | ||
| 510 | /* | ||
| 511 | * due to a locking dependency this has to be outside of the | ||
| 512 | * cfg80211_mutex lock | ||
| 513 | */ | ||
| 514 | res = rfkill_register(rdev->rfkill); | ||
| 515 | if (res) | ||
| 516 | goto out_rm_dev; | ||
| 517 | |||
| 512 | return 0; | 518 | return 0; |
| 513 | 519 | ||
| 514 | out_rm_dev: | 520 | out_rm_dev: |
| 515 | device_del(&rdev->wiphy.dev); | 521 | device_del(&rdev->wiphy.dev); |
| 516 | |||
| 517 | out_unlock: | ||
| 518 | mutex_unlock(&cfg80211_mutex); | ||
| 519 | return res; | 522 | return res; |
| 520 | } | 523 | } |
| 521 | EXPORT_SYMBOL(wiphy_register); | 524 | EXPORT_SYMBOL(wiphy_register); |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index bb5e0a5ecfa1..7e5c3a45f811 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
| @@ -1420,6 +1420,9 @@ int cfg80211_wext_giwessid(struct net_device *dev, | |||
| 1420 | { | 1420 | { |
| 1421 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1421 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 1422 | 1422 | ||
| 1423 | data->flags = 0; | ||
| 1424 | data->length = 0; | ||
| 1425 | |||
| 1423 | switch (wdev->iftype) { | 1426 | switch (wdev->iftype) { |
| 1424 | case NL80211_IFTYPE_ADHOC: | 1427 | case NL80211_IFTYPE_ADHOC: |
| 1425 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | 1428 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); |
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 0ef17bc42bac..8f5116f5af19 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c | |||
| @@ -782,6 +782,22 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, | |||
| 782 | } | 782 | } |
| 783 | } | 783 | } |
| 784 | 784 | ||
| 785 | if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) { | ||
| 786 | /* | ||
| 787 | * If this is a GET, but not NOMAX, it means that the extra | ||
| 788 | * data is not bounded by userspace, but by max_tokens. Thus | ||
| 789 | * set the length to max_tokens. This matches the extra data | ||
| 790 | * allocation. | ||
| 791 | * The driver should fill it with the number of tokens it | ||
| 792 | * provided, and it may check iwp->length rather than having | ||
| 793 | * knowledge of max_tokens. If the driver doesn't change the | ||
| 794 | * iwp->length, this ioctl just copies back max_token tokens | ||
| 795 | * filled with zeroes. Hopefully the driver isn't claiming | ||
| 796 | * them to be valid data. | ||
| 797 | */ | ||
| 798 | iwp->length = descr->max_tokens; | ||
| 799 | } | ||
| 800 | |||
| 785 | err = handler(dev, info, (union iwreq_data *) iwp, extra); | 801 | err = handler(dev, info, (union iwreq_data *) iwp, extra); |
| 786 | 802 | ||
| 787 | iwp->length += essid_compat; | 803 | iwp->length += essid_compat; |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index a3cca0a94346..64f2ae1fdc15 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -101,7 +101,7 @@ resume: | |||
| 101 | err = -EHOSTUNREACH; | 101 | err = -EHOSTUNREACH; |
| 102 | goto error_nolock; | 102 | goto error_nolock; |
| 103 | } | 103 | } |
| 104 | skb_dst_set_noref(skb, dst); | 104 | skb_dst_set(skb, dst_clone(dst)); |
| 105 | x = dst->xfrm; | 105 | x = dst->xfrm; |
| 106 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 106 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
| 107 | 107 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b14ed4b1f27c..8bae6b22c846 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -1801,7 +1801,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1801 | struct xfrm_user_expire *ue = nlmsg_data(nlh); | 1801 | struct xfrm_user_expire *ue = nlmsg_data(nlh); |
| 1802 | struct xfrm_usersa_info *p = &ue->state; | 1802 | struct xfrm_usersa_info *p = &ue->state; |
| 1803 | struct xfrm_mark m; | 1803 | struct xfrm_mark m; |
| 1804 | u32 mark = xfrm_mark_get(attrs, &m);; | 1804 | u32 mark = xfrm_mark_get(attrs, &m); |
| 1805 | 1805 | ||
| 1806 | x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); | 1806 | x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); |
| 1807 | 1807 | ||
