aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-09-25 17:20:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-09-25 17:20:29 -0400
commit6f0f9b6b3fcfe5e156f20d4f804f0d505c750b3c (patch)
tree3e708164563b979e1c1af5557031021b15710aeb /net
parent9391734d7662019f52db42e6e2c434f81aa0d2a2 (diff)
parent96af69ea2a83d292238bdba20e4508ee967cf8cb (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull more networking fixes from David Miller: 1) Eric Dumazet discovered and fixed what turned out to be a family of bugs. These functions were using pskb_may_pull() which might need to reallocate the linear SKB data buffer, but the callers were not expecting this possibility. The callers have cached pointers to the packet header areas, and would need to reload them if we were to continue using pskb_may_pull(). So they could end up reading garbage. It's easier to just change these RAW4/RAW6/MIP6 routines to use skb_header_pointer() instead of pskb_may_pull(), which won't modify the linear SKB data area. 2) Dave Jone's syscall spammer caught a case where a non-TCP socket can call down into the TCP keepalive code. The case basically involves creating a raw socket with sk_protocol == IPPROTO_TCP, then calling setsockopt(sock_fd, SO_KEEPALIVE, ...) Fixed by Eric Dumazet. 3) Bluetooth devices do not get configured properly while being powered on, resulting in always using legacy pairing instead of SSP. Fix from Andrzej Kaczmarek. 4) Bluetooth cancels delayed work erroneously, put stricter checks in place. From Andrei Emeltchenko. 5) Fix deadlock between cfg80211_mutex and reg_regdb_search_mutex in cfg80211, from Luis R. Rodriguez. 6) Fix interrupt double release in iwlwifi, from Emmanuel Grumbach. 7) Missing module license in bcm87xx driver, from Peter Huewe. 8) Team driver can lose port changed events when adding devices to a team, fix from Jiri Pirko. 9) Fix endless loop when trying ot unregister PPPOE device in zombie state, from Xiaodong Xu. 10) batman-adv layer needs to set MAC address of software device earlier, otherwise we call tt_local_add with it uninitialized. 11) Fix handling of KSZ8021 PHYs, it's matched currently by KS8051 but that doesn't program the device properly. From Marek Vasut. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: ipv6: mip6: fix mip6_mh_filter() ipv6: raw: fix icmpv6_filter() net: guard tcp_set_keepalive() to tcp sockets phy/micrel: Add missing header to micrel_phy.h phy/micrel: Rename KS80xx to KSZ80xx phy/micrel: Implement support for KSZ8021 batman-adv: Fix symmetry check / route flapping in multi interface setups batman-adv: Fix change mac address of soft iface. pppoe: drop PPPOX_ZOMBIEs in pppoe_release team: send port changed when added ipv4: raw: fix icmp_filter() net/phy/bcm87xx: Add MODULE_LICENSE("GPL") to GPL driver iwlwifi: don't double free the interrupt in failure path cfg80211: fix possible circular lock on reg_regdb_search() Bluetooth: Fix not removing power_off delayed work Bluetooth: Fix freeing uninitialized delayed works Bluetooth: mgmt: Fix enabling LE while powered off Bluetooth: mgmt: Fix enabling SSP while powered off
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/bat_iv_ogm.c13
-rw-r--r--net/batman-adv/soft-interface.c7
-rw-r--r--net/bluetooth/hci_core.c2
-rw-r--r--net/bluetooth/l2cap_core.c2
-rw-r--r--net/bluetooth/mgmt.c16
-rw-r--r--net/core/sock.c3
-rw-r--r--net/ipv4/raw.c14
-rw-r--r--net/ipv6/mip6.c20
-rw-r--r--net/ipv6/raw.c21
-rw-r--r--net/wireless/reg.c12
10 files changed, 71 insertions, 39 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index e877af8bdd1e..469daabd90c7 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -642,7 +642,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
642 struct batadv_neigh_node *router = NULL; 642 struct batadv_neigh_node *router = NULL;
643 struct batadv_orig_node *orig_node_tmp; 643 struct batadv_orig_node *orig_node_tmp;
644 struct hlist_node *node; 644 struct hlist_node *node;
645 uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; 645 int if_num;
646 uint8_t sum_orig, sum_neigh;
646 uint8_t *neigh_addr; 647 uint8_t *neigh_addr;
647 648
648 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 649 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -727,17 +728,17 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
727 if (router && (neigh_node->tq_avg == router->tq_avg)) { 728 if (router && (neigh_node->tq_avg == router->tq_avg)) {
728 orig_node_tmp = router->orig_node; 729 orig_node_tmp = router->orig_node;
729 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); 730 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
730 bcast_own_sum_orig = 731 if_num = router->if_incoming->if_num;
731 orig_node_tmp->bcast_own_sum[if_incoming->if_num]; 732 sum_orig = orig_node_tmp->bcast_own_sum[if_num];
732 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); 733 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
733 734
734 orig_node_tmp = neigh_node->orig_node; 735 orig_node_tmp = neigh_node->orig_node;
735 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); 736 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
736 bcast_own_sum_neigh = 737 if_num = neigh_node->if_incoming->if_num;
737 orig_node_tmp->bcast_own_sum[if_incoming->if_num]; 738 sum_neigh = orig_node_tmp->bcast_own_sum[if_num];
738 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); 739 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
739 740
740 if (bcast_own_sum_orig >= bcast_own_sum_neigh) 741 if (sum_orig >= sum_neigh)
741 goto update_tt; 742 goto update_tt;
742 } 743 }
743 744
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 109ea2aae96c..21c53577c8d6 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -100,18 +100,21 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
100{ 100{
101 struct batadv_priv *bat_priv = netdev_priv(dev); 101 struct batadv_priv *bat_priv = netdev_priv(dev);
102 struct sockaddr *addr = p; 102 struct sockaddr *addr = p;
103 uint8_t old_addr[ETH_ALEN];
103 104
104 if (!is_valid_ether_addr(addr->sa_data)) 105 if (!is_valid_ether_addr(addr->sa_data))
105 return -EADDRNOTAVAIL; 106 return -EADDRNOTAVAIL;
106 107
108 memcpy(old_addr, dev->dev_addr, ETH_ALEN);
109 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
110
107 /* only modify transtable if it has been initialized before */ 111 /* only modify transtable if it has been initialized before */
108 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { 112 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) {
109 batadv_tt_local_remove(bat_priv, dev->dev_addr, 113 batadv_tt_local_remove(bat_priv, old_addr,
110 "mac address changed", false); 114 "mac address changed", false);
111 batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX); 115 batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);
112 } 116 }
113 117
114 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
115 dev->addr_assign_type &= ~NET_ADDR_RANDOM; 118 dev->addr_assign_type &= ~NET_ADDR_RANDOM;
116 return 0; 119 return 0;
117} 120}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d4de5db18d5a..0b997c8f9655 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -734,6 +734,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
734 734
735 cancel_work_sync(&hdev->le_scan); 735 cancel_work_sync(&hdev->le_scan);
736 736
737 cancel_delayed_work(&hdev->power_off);
738
737 hci_req_cancel(hdev, ENODEV); 739 hci_req_cancel(hdev, ENODEV);
738 hci_req_lock(hdev); 740 hci_req_lock(hdev);
739 741
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4ea1710a4783..38c00f142203 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1008,7 +1008,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
1008 if (!conn) 1008 if (!conn)
1009 return; 1009 return;
1010 1010
1011 if (chan->mode == L2CAP_MODE_ERTM) { 1011 if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
1012 __clear_retrans_timer(chan); 1012 __clear_retrans_timer(chan);
1013 __clear_monitor_timer(chan); 1013 __clear_monitor_timer(chan);
1014 __clear_ack_timer(chan); 1014 __clear_ack_timer(chan);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ad6613d17ca6..eba022de3c20 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2875,6 +2875,22 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
2875 if (scan) 2875 if (scan)
2876 hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); 2876 hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2877 2877
2878 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
2879 u8 ssp = 1;
2880
2881 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
2882 }
2883
2884 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2885 struct hci_cp_write_le_host_supported cp;
2886
2887 cp.le = 1;
2888 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
2889
2890 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
2891 sizeof(cp), &cp);
2892 }
2893
2878 update_class(hdev); 2894 update_class(hdev);
2879 update_name(hdev, hdev->dev_name); 2895 update_name(hdev, hdev->dev_name);
2880 update_eir(hdev); 2896 update_eir(hdev);
diff --git a/net/core/sock.c b/net/core/sock.c
index 305792076121..a6000fbad294 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -691,7 +691,8 @@ set_rcvbuf:
691 691
692 case SO_KEEPALIVE: 692 case SO_KEEPALIVE:
693#ifdef CONFIG_INET 693#ifdef CONFIG_INET
694 if (sk->sk_protocol == IPPROTO_TCP) 694 if (sk->sk_protocol == IPPROTO_TCP &&
695 sk->sk_type == SOCK_STREAM)
695 tcp_set_keepalive(sk, valbool); 696 tcp_set_keepalive(sk, valbool);
696#endif 697#endif
697 sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); 698 sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index ff0f071969ea..d23c6571ba1c 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -131,18 +131,20 @@ found:
131 * 0 - deliver 131 * 0 - deliver
132 * 1 - block 132 * 1 - block
133 */ 133 */
134static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) 134static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
135{ 135{
136 int type; 136 struct icmphdr _hdr;
137 const struct icmphdr *hdr;
137 138
138 if (!pskb_may_pull(skb, sizeof(struct icmphdr))) 139 hdr = skb_header_pointer(skb, skb_transport_offset(skb),
140 sizeof(_hdr), &_hdr);
141 if (!hdr)
139 return 1; 142 return 1;
140 143
141 type = icmp_hdr(skb)->type; 144 if (hdr->type < 32) {
142 if (type < 32) {
143 __u32 data = raw_sk(sk)->filter.data; 145 __u32 data = raw_sk(sk)->filter.data;
144 146
145 return ((1 << type) & data) != 0; 147 return ((1U << hdr->type) & data) != 0;
146 } 148 }
147 149
148 /* Do not block unknown ICMP types */ 150 /* Do not block unknown ICMP types */
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 5b087c31d87b..0f9bdc5ee9f3 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -86,28 +86,30 @@ static int mip6_mh_len(int type)
86 86
87static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) 87static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
88{ 88{
89 struct ip6_mh *mh; 89 struct ip6_mh _hdr;
90 const struct ip6_mh *mh;
90 91
91 if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || 92 mh = skb_header_pointer(skb, skb_transport_offset(skb),
92 !pskb_may_pull(skb, (skb_transport_offset(skb) + 93 sizeof(_hdr), &_hdr);
93 ((skb_transport_header(skb)[1] + 1) << 3)))) 94 if (!mh)
94 return -1; 95 return -1;
95 96
96 mh = (struct ip6_mh *)skb_transport_header(skb); 97 if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len)
98 return -1;
97 99
98 if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { 100 if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
99 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", 101 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
100 mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); 102 mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
101 mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - 103 mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) +
102 skb_network_header(skb))); 104 skb_network_header_len(skb));
103 return -1; 105 return -1;
104 } 106 }
105 107
106 if (mh->ip6mh_proto != IPPROTO_NONE) { 108 if (mh->ip6mh_proto != IPPROTO_NONE) {
107 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", 109 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
108 mh->ip6mh_proto); 110 mh->ip6mh_proto);
109 mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - 111 mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) +
110 skb_network_header(skb))); 112 skb_network_header_len(skb));
111 return -1; 113 return -1;
112 } 114 }
113 115
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ef0579d5bca6..4a5f78b50495 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -107,21 +107,20 @@ found:
107 * 0 - deliver 107 * 0 - deliver
108 * 1 - block 108 * 1 - block
109 */ 109 */
110static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) 110static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
111{ 111{
112 struct icmp6hdr *icmph; 112 struct icmp6hdr *_hdr;
113 struct raw6_sock *rp = raw6_sk(sk); 113 const struct icmp6hdr *hdr;
114
115 if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
116 __u32 *data = &rp->filter.data[0];
117 int bit_nr;
118 114
119 icmph = (struct icmp6hdr *) skb->data; 115 hdr = skb_header_pointer(skb, skb_transport_offset(skb),
120 bit_nr = icmph->icmp6_type; 116 sizeof(_hdr), &_hdr);
117 if (hdr) {
118 const __u32 *data = &raw6_sk(sk)->filter.data[0];
119 unsigned int type = hdr->icmp6_type;
121 120
122 return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; 121 return (data[type >> 5] & (1U << (type & 31))) != 0;
123 } 122 }
124 return 0; 123 return 1;
125} 124}
126 125
127#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 126#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2ded3c7fad06..72d170ca3406 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -350,6 +350,9 @@ static void reg_regdb_search(struct work_struct *work)
350 struct reg_regdb_search_request *request; 350 struct reg_regdb_search_request *request;
351 const struct ieee80211_regdomain *curdom, *regdom; 351 const struct ieee80211_regdomain *curdom, *regdom;
352 int i, r; 352 int i, r;
353 bool set_reg = false;
354
355 mutex_lock(&cfg80211_mutex);
353 356
354 mutex_lock(&reg_regdb_search_mutex); 357 mutex_lock(&reg_regdb_search_mutex);
355 while (!list_empty(&reg_regdb_search_list)) { 358 while (!list_empty(&reg_regdb_search_list)) {
@@ -365,9 +368,7 @@ static void reg_regdb_search(struct work_struct *work)
365 r = reg_copy_regd(&regdom, curdom); 368 r = reg_copy_regd(&regdom, curdom);
366 if (r) 369 if (r)
367 break; 370 break;
368 mutex_lock(&cfg80211_mutex); 371 set_reg = true;
369 set_regdom(regdom);
370 mutex_unlock(&cfg80211_mutex);
371 break; 372 break;
372 } 373 }
373 } 374 }
@@ -375,6 +376,11 @@ static void reg_regdb_search(struct work_struct *work)
375 kfree(request); 376 kfree(request);
376 } 377 }
377 mutex_unlock(&reg_regdb_search_mutex); 378 mutex_unlock(&reg_regdb_search_mutex);
379
380 if (set_reg)
381 set_regdom(regdom);
382
383 mutex_unlock(&cfg80211_mutex);
378} 384}
379 385
380static DECLARE_WORK(reg_regdb_work, reg_regdb_search); 386static DECLARE_WORK(reg_regdb_work, reg_regdb_search);