diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-13 16:51:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-13 16:51:32 -0400 |
commit | 5d7d5d933256fc44f68e061ccd103b027fef0fc9 (patch) | |
tree | c3effea9a99409d4adec80dcf358e6d99736ed25 /net | |
parent | 8d86e5f91440aa56a5df516bf58fe3883552ad56 (diff) | |
parent | 7686d1cc5ed0932a533a5acbc3888b48de63bef8 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (21 commits)
slip: fix wrong SLIP6 ifdef-endif placing
natsemi: fix another dma-debug report
sctp: ABORT if receive, reassmbly, or reodering queue is not empty while closing socket
net: Fix default in docs for tcp_orphan_retries.
hso: fix a use after free condition
net/natsemi: Fix module parameter permissions
XFRM: Fix memory leak in xfrm_state_update
sctp: Enforce retransmission limit during shutdown
mac80211: fix TKIP replay vulnerability
mac80211: fix ie memory allocation for scheduled scans
ssb: fix init regression of hostmode PCI core
rtlwifi: rtl8192cu: Add new USB ID for Netgear WNA1000M
ath9k: Fix tx throughput drops for AR9003 chips with AES encryption
carl9170: add NEC WL300NU-AG usbid
cfg80211: fix deadlock with rfkill/sched_scan by adding new mutex
ath5k: fix incorrect use of drvdata in PCI suspend/resume code
ath5k: fix incorrect use of drvdata in sysfs code
Bluetooth: Fix memory leak under page timeouts
Bluetooth: Fix regression with incoming L2CAP connections
Bluetooth: Fix hidp disconnect deadlocks and lost wakeup
...
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_conn.c | 3 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 18 | ||||
-rw-r--r-- | net/bluetooth/hidp/hidp.h | 1 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 5 | ||||
-rw-r--r-- | net/mac80211/scan.c | 3 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 16 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 20 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 20 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 32 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 13 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 16 | ||||
-rw-r--r-- | net/wireless/core.c | 12 | ||||
-rw-r--r-- | net/wireless/core.h | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 24 | ||||
-rw-r--r-- | net/wireless/scan.c | 10 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 2 |
17 files changed, 151 insertions, 48 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index d3a05b9ade7a..bcd158f40bb9 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -393,6 +393,9 @@ int hci_conn_del(struct hci_conn *conn) | |||
393 | 393 | ||
394 | hci_dev_put(hdev); | 394 | hci_dev_put(hdev); |
395 | 395 | ||
396 | if (conn->handle == 0) | ||
397 | kfree(conn); | ||
398 | |||
396 | return 0; | 399 | return 0; |
397 | } | 400 | } |
398 | 401 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index c405a954a603..43b4c2deb7cc 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -464,7 +464,8 @@ static void hidp_idle_timeout(unsigned long arg) | |||
464 | { | 464 | { |
465 | struct hidp_session *session = (struct hidp_session *) arg; | 465 | struct hidp_session *session = (struct hidp_session *) arg; |
466 | 466 | ||
467 | kthread_stop(session->task); | 467 | atomic_inc(&session->terminate); |
468 | wake_up_process(session->task); | ||
468 | } | 469 | } |
469 | 470 | ||
470 | static void hidp_set_timer(struct hidp_session *session) | 471 | static void hidp_set_timer(struct hidp_session *session) |
@@ -535,7 +536,8 @@ static void hidp_process_hid_control(struct hidp_session *session, | |||
535 | skb_queue_purge(&session->ctrl_transmit); | 536 | skb_queue_purge(&session->ctrl_transmit); |
536 | skb_queue_purge(&session->intr_transmit); | 537 | skb_queue_purge(&session->intr_transmit); |
537 | 538 | ||
538 | kthread_stop(session->task); | 539 | atomic_inc(&session->terminate); |
540 | wake_up_process(current); | ||
539 | } | 541 | } |
540 | } | 542 | } |
541 | 543 | ||
@@ -706,9 +708,8 @@ static int hidp_session(void *arg) | |||
706 | add_wait_queue(sk_sleep(intr_sk), &intr_wait); | 708 | add_wait_queue(sk_sleep(intr_sk), &intr_wait); |
707 | session->waiting_for_startup = 0; | 709 | session->waiting_for_startup = 0; |
708 | wake_up_interruptible(&session->startup_queue); | 710 | wake_up_interruptible(&session->startup_queue); |
709 | while (!kthread_should_stop()) { | 711 | set_current_state(TASK_INTERRUPTIBLE); |
710 | set_current_state(TASK_INTERRUPTIBLE); | 712 | while (!atomic_read(&session->terminate)) { |
711 | |||
712 | if (ctrl_sk->sk_state != BT_CONNECTED || | 713 | if (ctrl_sk->sk_state != BT_CONNECTED || |
713 | intr_sk->sk_state != BT_CONNECTED) | 714 | intr_sk->sk_state != BT_CONNECTED) |
714 | break; | 715 | break; |
@@ -726,6 +727,7 @@ static int hidp_session(void *arg) | |||
726 | hidp_process_transmit(session); | 727 | hidp_process_transmit(session); |
727 | 728 | ||
728 | schedule(); | 729 | schedule(); |
730 | set_current_state(TASK_INTERRUPTIBLE); | ||
729 | } | 731 | } |
730 | set_current_state(TASK_RUNNING); | 732 | set_current_state(TASK_RUNNING); |
731 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); | 733 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); |
@@ -1060,7 +1062,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
1060 | err_add_device: | 1062 | err_add_device: |
1061 | hid_destroy_device(session->hid); | 1063 | hid_destroy_device(session->hid); |
1062 | session->hid = NULL; | 1064 | session->hid = NULL; |
1063 | kthread_stop(session->task); | 1065 | atomic_inc(&session->terminate); |
1066 | wake_up_process(session->task); | ||
1064 | 1067 | ||
1065 | unlink: | 1068 | unlink: |
1066 | hidp_del_timer(session); | 1069 | hidp_del_timer(session); |
@@ -1111,7 +1114,8 @@ int hidp_del_connection(struct hidp_conndel_req *req) | |||
1111 | skb_queue_purge(&session->ctrl_transmit); | 1114 | skb_queue_purge(&session->ctrl_transmit); |
1112 | skb_queue_purge(&session->intr_transmit); | 1115 | skb_queue_purge(&session->intr_transmit); |
1113 | 1116 | ||
1114 | kthread_stop(session->task); | 1117 | atomic_inc(&session->terminate); |
1118 | wake_up_process(session->task); | ||
1115 | } | 1119 | } |
1116 | } else | 1120 | } else |
1117 | err = -ENOENT; | 1121 | err = -ENOENT; |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 19e95004b286..af1bcc823f26 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
@@ -142,6 +142,7 @@ struct hidp_session { | |||
142 | uint ctrl_mtu; | 142 | uint ctrl_mtu; |
143 | uint intr_mtu; | 143 | uint intr_mtu; |
144 | 144 | ||
145 | atomic_t terminate; | ||
145 | struct task_struct *task; | 146 | struct task_struct *task; |
146 | 147 | ||
147 | unsigned char keys[8]; | 148 | unsigned char keys[8]; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 56fdd9162da9..ebff14c69078 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -2323,7 +2323,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2323 | 2323 | ||
2324 | sk = chan->sk; | 2324 | sk = chan->sk; |
2325 | 2325 | ||
2326 | if (sk->sk_state != BT_CONFIG) { | 2326 | if ((bt_sk(sk)->defer_setup && sk->sk_state != BT_CONNECT2) || |
2327 | (!bt_sk(sk)->defer_setup && sk->sk_state != BT_CONFIG)) { | ||
2327 | struct l2cap_cmd_rej rej; | 2328 | struct l2cap_cmd_rej rej; |
2328 | 2329 | ||
2329 | rej.reason = cpu_to_le16(0x0002); | 2330 | rej.reason = cpu_to_le16(0x0002); |
@@ -2334,7 +2335,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2334 | 2335 | ||
2335 | /* Reject if config buffer is too small. */ | 2336 | /* Reject if config buffer is too small. */ |
2336 | len = cmd_len - sizeof(*req); | 2337 | len = cmd_len - sizeof(*req); |
2337 | if (chan->conf_len + len > sizeof(chan->conf_req)) { | 2338 | if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { |
2338 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 2339 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
2339 | l2cap_build_conf_rsp(chan, rsp, | 2340 | l2cap_build_conf_rsp(chan, rsp, |
2340 | L2CAP_CONF_REJECT, flags), rsp); | 2341 | L2CAP_CONF_REJECT, flags), rsp); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 58ffa7d069c7..669d2e32efb6 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -877,7 +877,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
877 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 877 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
878 | local->sched_scan_ies.ie[i] = kzalloc(2 + | 878 | local->sched_scan_ies.ie[i] = kzalloc(2 + |
879 | IEEE80211_MAX_SSID_LEN + | 879 | IEEE80211_MAX_SSID_LEN + |
880 | local->scan_ies_len, | 880 | local->scan_ies_len + |
881 | req->ie_len, | ||
881 | GFP_KERNEL); | 882 | GFP_KERNEL); |
882 | if (!local->sched_scan_ies.ie[i]) { | 883 | if (!local->sched_scan_ies.ie[i]) { |
883 | ret = -ENOMEM; | 884 | ret = -ENOMEM; |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index d91c1a26630d..8f6a302d2ac3 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -86,6 +86,11 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
86 | struct sk_buff *skb = rx->skb; | 86 | struct sk_buff *skb = rx->skb; |
87 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 87 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
88 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 88 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
89 | int queue = rx->queue; | ||
90 | |||
91 | /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ | ||
92 | if (rx->queue == NUM_RX_DATA_QUEUES - 1) | ||
93 | queue = 0; | ||
89 | 94 | ||
90 | /* | 95 | /* |
91 | * it makes no sense to check for MIC errors on anything other | 96 | * it makes no sense to check for MIC errors on anything other |
@@ -148,8 +153,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
148 | 153 | ||
149 | update_iv: | 154 | update_iv: |
150 | /* update IV in key information to be able to detect replays */ | 155 | /* update IV in key information to be able to detect replays */ |
151 | rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; | 156 | rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32; |
152 | rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; | 157 | rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16; |
153 | 158 | ||
154 | return RX_CONTINUE; | 159 | return RX_CONTINUE; |
155 | 160 | ||
@@ -241,6 +246,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
241 | struct ieee80211_key *key = rx->key; | 246 | struct ieee80211_key *key = rx->key; |
242 | struct sk_buff *skb = rx->skb; | 247 | struct sk_buff *skb = rx->skb; |
243 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 248 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
249 | int queue = rx->queue; | ||
250 | |||
251 | /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ | ||
252 | if (rx->queue == NUM_RX_DATA_QUEUES - 1) | ||
253 | queue = 0; | ||
244 | 254 | ||
245 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 255 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
246 | 256 | ||
@@ -261,7 +271,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
261 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 271 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
262 | key, skb->data + hdrlen, | 272 | key, skb->data + hdrlen, |
263 | skb->len - hdrlen, rx->sta->sta.addr, | 273 | skb->len - hdrlen, rx->sta->sta.addr, |
264 | hdr->addr1, hwaccel, rx->queue, | 274 | hdr->addr1, hwaccel, queue, |
265 | &rx->tkip_iv32, | 275 | &rx->tkip_iv32, |
266 | &rx->tkip_iv16); | 276 | &rx->tkip_iv16); |
267 | if (res != TKIP_DECRYPT_OK) | 277 | if (res != TKIP_DECRYPT_OK) |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1c88c8911dc5..d03682109b7a 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -1582,6 +1582,8 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1582 | #endif /* SCTP_DEBUG */ | 1582 | #endif /* SCTP_DEBUG */ |
1583 | if (transport) { | 1583 | if (transport) { |
1584 | if (bytes_acked) { | 1584 | if (bytes_acked) { |
1585 | struct sctp_association *asoc = transport->asoc; | ||
1586 | |||
1585 | /* We may have counted DATA that was migrated | 1587 | /* We may have counted DATA that was migrated |
1586 | * to this transport due to DEL-IP operation. | 1588 | * to this transport due to DEL-IP operation. |
1587 | * Subtract those bytes, since the were never | 1589 | * Subtract those bytes, since the were never |
@@ -1600,6 +1602,17 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1600 | transport->error_count = 0; | 1602 | transport->error_count = 0; |
1601 | transport->asoc->overall_error_count = 0; | 1603 | transport->asoc->overall_error_count = 0; |
1602 | 1604 | ||
1605 | /* | ||
1606 | * While in SHUTDOWN PENDING, we may have started | ||
1607 | * the T5 shutdown guard timer after reaching the | ||
1608 | * retransmission limit. Stop that timer as soon | ||
1609 | * as the receiver acknowledged any data. | ||
1610 | */ | ||
1611 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING && | ||
1612 | del_timer(&asoc->timers | ||
1613 | [SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD])) | ||
1614 | sctp_association_put(asoc); | ||
1615 | |||
1603 | /* Mark the destination transport address as | 1616 | /* Mark the destination transport address as |
1604 | * active if it is not so marked. | 1617 | * active if it is not so marked. |
1605 | */ | 1618 | */ |
@@ -1629,10 +1642,15 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1629 | * A sender is doing zero window probing when the | 1642 | * A sender is doing zero window probing when the |
1630 | * receiver's advertised window is zero, and there is | 1643 | * receiver's advertised window is zero, and there is |
1631 | * only one data chunk in flight to the receiver. | 1644 | * only one data chunk in flight to the receiver. |
1645 | * | ||
1646 | * Allow the association to timeout while in SHUTDOWN | ||
1647 | * PENDING or SHUTDOWN RECEIVED in case the receiver | ||
1648 | * stays in zero window mode forever. | ||
1632 | */ | 1649 | */ |
1633 | if (!q->asoc->peer.rwnd && | 1650 | if (!q->asoc->peer.rwnd && |
1634 | !list_empty(&tlist) && | 1651 | !list_empty(&tlist) && |
1635 | (sack_ctsn+2 == q->asoc->next_tsn)) { | 1652 | (sack_ctsn+2 == q->asoc->next_tsn) && |
1653 | q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) { | ||
1636 | SCTP_DEBUG_PRINTK("%s: SACK received for zero " | 1654 | SCTP_DEBUG_PRINTK("%s: SACK received for zero " |
1637 | "window probe: %u\n", | 1655 | "window probe: %u\n", |
1638 | __func__, sack_ctsn); | 1656 | __func__, sack_ctsn); |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 534c2e5feb05..6e0f88295aaf 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -670,10 +670,19 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
670 | /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the | 670 | /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the |
671 | * HEARTBEAT should clear the error counter of the destination | 671 | * HEARTBEAT should clear the error counter of the destination |
672 | * transport address to which the HEARTBEAT was sent. | 672 | * transport address to which the HEARTBEAT was sent. |
673 | * The association's overall error count is also cleared. | ||
674 | */ | 673 | */ |
675 | t->error_count = 0; | 674 | t->error_count = 0; |
676 | t->asoc->overall_error_count = 0; | 675 | |
676 | /* | ||
677 | * Although RFC4960 specifies that the overall error count must | ||
678 | * be cleared when a HEARTBEAT ACK is received, we make an | ||
679 | * exception while in SHUTDOWN PENDING. If the peer keeps its | ||
680 | * window shut forever, we may never be able to transmit our | ||
681 | * outstanding data and rely on the retransmission limit be reached | ||
682 | * to shutdown the association. | ||
683 | */ | ||
684 | if (t->asoc->state != SCTP_STATE_SHUTDOWN_PENDING) | ||
685 | t->asoc->overall_error_count = 0; | ||
677 | 686 | ||
678 | /* Clear the hb_sent flag to signal that we had a good | 687 | /* Clear the hb_sent flag to signal that we had a good |
679 | * acknowledgement. | 688 | * acknowledgement. |
@@ -1437,6 +1446,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1437 | sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr); | 1446 | sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr); |
1438 | break; | 1447 | break; |
1439 | 1448 | ||
1449 | case SCTP_CMD_TIMER_START_ONCE: | ||
1450 | timer = &asoc->timers[cmd->obj.to]; | ||
1451 | |||
1452 | if (timer_pending(timer)) | ||
1453 | break; | ||
1454 | /* fall through */ | ||
1455 | |||
1440 | case SCTP_CMD_TIMER_START: | 1456 | case SCTP_CMD_TIMER_START: |
1441 | timer = &asoc->timers[cmd->obj.to]; | 1457 | timer = &asoc->timers[cmd->obj.to]; |
1442 | timeout = asoc->timeouts[cmd->obj.to]; | 1458 | timeout = asoc->timeouts[cmd->obj.to]; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index a297283154d5..246117142b5c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -5154,7 +5154,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
5154 | * The sender of the SHUTDOWN MAY also start an overall guard timer | 5154 | * The sender of the SHUTDOWN MAY also start an overall guard timer |
5155 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | 5155 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. |
5156 | */ | 5156 | */ |
5157 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 5157 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
5158 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5158 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
5159 | 5159 | ||
5160 | if (asoc->autoclose) | 5160 | if (asoc->autoclose) |
@@ -5299,14 +5299,28 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
5299 | SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); | 5299 | SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); |
5300 | 5300 | ||
5301 | if (asoc->overall_error_count >= asoc->max_retrans) { | 5301 | if (asoc->overall_error_count >= asoc->max_retrans) { |
5302 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | 5302 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { |
5303 | SCTP_ERROR(ETIMEDOUT)); | 5303 | /* |
5304 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 5304 | * We are here likely because the receiver had its rwnd |
5305 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5305 | * closed for a while and we have not been able to |
5306 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5306 | * transmit the locally queued data within the maximum |
5307 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5307 | * retransmission attempts limit. Start the T5 |
5308 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 5308 | * shutdown guard timer to give the receiver one last |
5309 | return SCTP_DISPOSITION_DELETE_TCB; | 5309 | * chance and some additional time to recover before |
5310 | * aborting. | ||
5311 | */ | ||
5312 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START_ONCE, | ||
5313 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
5314 | } else { | ||
5315 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
5316 | SCTP_ERROR(ETIMEDOUT)); | ||
5317 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | ||
5318 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
5319 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | ||
5320 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
5321 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
5322 | return SCTP_DISPOSITION_DELETE_TCB; | ||
5323 | } | ||
5310 | } | 5324 | } |
5311 | 5325 | ||
5312 | /* E1) For the destination address for which the timer | 5326 | /* E1) For the destination address for which the timer |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 0338dc6fdc9d..7c211a7f90f4 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -827,7 +827,7 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
827 | /* SCTP_STATE_ESTABLISHED */ \ | 827 | /* SCTP_STATE_ESTABLISHED */ \ |
828 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 828 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
829 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 829 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
830 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 830 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ |
831 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 831 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
832 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ | 832 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ |
833 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ | 833 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 08c6238802de..d3ccf7973c59 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1384,6 +1384,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1384 | struct sctp_endpoint *ep; | 1384 | struct sctp_endpoint *ep; |
1385 | struct sctp_association *asoc; | 1385 | struct sctp_association *asoc; |
1386 | struct list_head *pos, *temp; | 1386 | struct list_head *pos, *temp; |
1387 | unsigned int data_was_unread; | ||
1387 | 1388 | ||
1388 | SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); | 1389 | SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); |
1389 | 1390 | ||
@@ -1393,6 +1394,10 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1393 | 1394 | ||
1394 | ep = sctp_sk(sk)->ep; | 1395 | ep = sctp_sk(sk)->ep; |
1395 | 1396 | ||
1397 | /* Clean up any skbs sitting on the receive queue. */ | ||
1398 | data_was_unread = sctp_queue_purge_ulpevents(&sk->sk_receive_queue); | ||
1399 | data_was_unread += sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby); | ||
1400 | |||
1396 | /* Walk all associations on an endpoint. */ | 1401 | /* Walk all associations on an endpoint. */ |
1397 | list_for_each_safe(pos, temp, &ep->asocs) { | 1402 | list_for_each_safe(pos, temp, &ep->asocs) { |
1398 | asoc = list_entry(pos, struct sctp_association, asocs); | 1403 | asoc = list_entry(pos, struct sctp_association, asocs); |
@@ -1410,7 +1415,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1410 | } | 1415 | } |
1411 | } | 1416 | } |
1412 | 1417 | ||
1413 | if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { | 1418 | if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) || |
1419 | !skb_queue_empty(&asoc->ulpq.reasm) || | ||
1420 | (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) { | ||
1414 | struct sctp_chunk *chunk; | 1421 | struct sctp_chunk *chunk; |
1415 | 1422 | ||
1416 | chunk = sctp_make_abort_user(asoc, NULL, 0); | 1423 | chunk = sctp_make_abort_user(asoc, NULL, 0); |
@@ -1420,10 +1427,6 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1420 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1427 | sctp_primitive_SHUTDOWN(asoc, NULL); |
1421 | } | 1428 | } |
1422 | 1429 | ||
1423 | /* Clean up any skbs sitting on the receive queue. */ | ||
1424 | sctp_queue_purge_ulpevents(&sk->sk_receive_queue); | ||
1425 | sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby); | ||
1426 | |||
1427 | /* On a TCP-style socket, block for at most linger_time if set. */ | 1430 | /* On a TCP-style socket, block for at most linger_time if set. */ |
1428 | if (sctp_style(sk, TCP) && timeout) | 1431 | if (sctp_style(sk, TCP) && timeout) |
1429 | sctp_wait_for_close(sk, timeout); | 1432 | sctp_wait_for_close(sk, timeout); |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index e70e5fc87890..8a84017834c2 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -1081,9 +1081,19 @@ void sctp_ulpevent_free(struct sctp_ulpevent *event) | |||
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | /* Purge the skb lists holding ulpevents. */ | 1083 | /* Purge the skb lists holding ulpevents. */ |
1084 | void sctp_queue_purge_ulpevents(struct sk_buff_head *list) | 1084 | unsigned int sctp_queue_purge_ulpevents(struct sk_buff_head *list) |
1085 | { | 1085 | { |
1086 | struct sk_buff *skb; | 1086 | struct sk_buff *skb; |
1087 | while ((skb = skb_dequeue(list)) != NULL) | 1087 | unsigned int data_unread = 0; |
1088 | sctp_ulpevent_free(sctp_skb2event(skb)); | 1088 | |
1089 | while ((skb = skb_dequeue(list)) != NULL) { | ||
1090 | struct sctp_ulpevent *event = sctp_skb2event(skb); | ||
1091 | |||
1092 | if (!sctp_ulpevent_is_notification(event)) | ||
1093 | data_unread += skb->len; | ||
1094 | |||
1095 | sctp_ulpevent_free(event); | ||
1096 | } | ||
1097 | |||
1098 | return data_unread; | ||
1089 | } | 1099 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index c22ef3492ee6..880dbe2e6f94 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -366,6 +366,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
366 | 366 | ||
367 | mutex_init(&rdev->mtx); | 367 | mutex_init(&rdev->mtx); |
368 | mutex_init(&rdev->devlist_mtx); | 368 | mutex_init(&rdev->devlist_mtx); |
369 | mutex_init(&rdev->sched_scan_mtx); | ||
369 | INIT_LIST_HEAD(&rdev->netdev_list); | 370 | INIT_LIST_HEAD(&rdev->netdev_list); |
370 | spin_lock_init(&rdev->bss_lock); | 371 | spin_lock_init(&rdev->bss_lock); |
371 | INIT_LIST_HEAD(&rdev->bss_list); | 372 | INIT_LIST_HEAD(&rdev->bss_list); |
@@ -701,6 +702,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) | |||
701 | rfkill_destroy(rdev->rfkill); | 702 | rfkill_destroy(rdev->rfkill); |
702 | mutex_destroy(&rdev->mtx); | 703 | mutex_destroy(&rdev->mtx); |
703 | mutex_destroy(&rdev->devlist_mtx); | 704 | mutex_destroy(&rdev->devlist_mtx); |
705 | mutex_destroy(&rdev->sched_scan_mtx); | ||
704 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) | 706 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) |
705 | cfg80211_put_bss(&scan->pub); | 707 | cfg80211_put_bss(&scan->pub); |
706 | cfg80211_rdev_free_wowlan(rdev); | 708 | cfg80211_rdev_free_wowlan(rdev); |
@@ -737,12 +739,16 @@ static void wdev_cleanup_work(struct work_struct *work) | |||
737 | ___cfg80211_scan_done(rdev, true); | 739 | ___cfg80211_scan_done(rdev, true); |
738 | } | 740 | } |
739 | 741 | ||
742 | cfg80211_unlock_rdev(rdev); | ||
743 | |||
744 | mutex_lock(&rdev->sched_scan_mtx); | ||
745 | |||
740 | if (WARN_ON(rdev->sched_scan_req && | 746 | if (WARN_ON(rdev->sched_scan_req && |
741 | rdev->sched_scan_req->dev == wdev->netdev)) { | 747 | rdev->sched_scan_req->dev == wdev->netdev)) { |
742 | __cfg80211_stop_sched_scan(rdev, false); | 748 | __cfg80211_stop_sched_scan(rdev, false); |
743 | } | 749 | } |
744 | 750 | ||
745 | cfg80211_unlock_rdev(rdev); | 751 | mutex_unlock(&rdev->sched_scan_mtx); |
746 | 752 | ||
747 | mutex_lock(&rdev->devlist_mtx); | 753 | mutex_lock(&rdev->devlist_mtx); |
748 | rdev->opencount--; | 754 | rdev->opencount--; |
@@ -830,9 +836,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
830 | break; | 836 | break; |
831 | case NL80211_IFTYPE_P2P_CLIENT: | 837 | case NL80211_IFTYPE_P2P_CLIENT: |
832 | case NL80211_IFTYPE_STATION: | 838 | case NL80211_IFTYPE_STATION: |
833 | cfg80211_lock_rdev(rdev); | 839 | mutex_lock(&rdev->sched_scan_mtx); |
834 | __cfg80211_stop_sched_scan(rdev, false); | 840 | __cfg80211_stop_sched_scan(rdev, false); |
835 | cfg80211_unlock_rdev(rdev); | 841 | mutex_unlock(&rdev->sched_scan_mtx); |
836 | 842 | ||
837 | wdev_lock(wdev); | 843 | wdev_lock(wdev); |
838 | #ifdef CONFIG_CFG80211_WEXT | 844 | #ifdef CONFIG_CFG80211_WEXT |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3dce1f167eba..a570ff9214ec 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -65,6 +65,8 @@ struct cfg80211_registered_device { | |||
65 | struct work_struct scan_done_wk; | 65 | struct work_struct scan_done_wk; |
66 | struct work_struct sched_scan_results_wk; | 66 | struct work_struct sched_scan_results_wk; |
67 | 67 | ||
68 | struct mutex sched_scan_mtx; | ||
69 | |||
68 | #ifdef CONFIG_NL80211_TESTMODE | 70 | #ifdef CONFIG_NL80211_TESTMODE |
69 | struct genl_info *testmode_info; | 71 | struct genl_info *testmode_info; |
70 | #endif | 72 | #endif |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f07602d7bf68..cea338150d05 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3461,9 +3461,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
3461 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3461 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3462 | return -EINVAL; | 3462 | return -EINVAL; |
3463 | 3463 | ||
3464 | if (rdev->sched_scan_req) | ||
3465 | return -EINPROGRESS; | ||
3466 | |||
3467 | if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) | 3464 | if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) |
3468 | return -EINVAL; | 3465 | return -EINVAL; |
3469 | 3466 | ||
@@ -3502,12 +3499,21 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
3502 | if (ie_len > wiphy->max_scan_ie_len) | 3499 | if (ie_len > wiphy->max_scan_ie_len) |
3503 | return -EINVAL; | 3500 | return -EINVAL; |
3504 | 3501 | ||
3502 | mutex_lock(&rdev->sched_scan_mtx); | ||
3503 | |||
3504 | if (rdev->sched_scan_req) { | ||
3505 | err = -EINPROGRESS; | ||
3506 | goto out; | ||
3507 | } | ||
3508 | |||
3505 | request = kzalloc(sizeof(*request) | 3509 | request = kzalloc(sizeof(*request) |
3506 | + sizeof(*request->ssids) * n_ssids | 3510 | + sizeof(*request->ssids) * n_ssids |
3507 | + sizeof(*request->channels) * n_channels | 3511 | + sizeof(*request->channels) * n_channels |
3508 | + ie_len, GFP_KERNEL); | 3512 | + ie_len, GFP_KERNEL); |
3509 | if (!request) | 3513 | if (!request) { |
3510 | return -ENOMEM; | 3514 | err = -ENOMEM; |
3515 | goto out; | ||
3516 | } | ||
3511 | 3517 | ||
3512 | if (n_ssids) | 3518 | if (n_ssids) |
3513 | request->ssids = (void *)&request->channels[n_channels]; | 3519 | request->ssids = (void *)&request->channels[n_channels]; |
@@ -3605,6 +3611,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
3605 | out_free: | 3611 | out_free: |
3606 | kfree(request); | 3612 | kfree(request); |
3607 | out: | 3613 | out: |
3614 | mutex_unlock(&rdev->sched_scan_mtx); | ||
3608 | return err; | 3615 | return err; |
3609 | } | 3616 | } |
3610 | 3617 | ||
@@ -3612,12 +3619,17 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb, | |||
3612 | struct genl_info *info) | 3619 | struct genl_info *info) |
3613 | { | 3620 | { |
3614 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3621 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3622 | int err; | ||
3615 | 3623 | ||
3616 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 3624 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
3617 | !rdev->ops->sched_scan_stop) | 3625 | !rdev->ops->sched_scan_stop) |
3618 | return -EOPNOTSUPP; | 3626 | return -EOPNOTSUPP; |
3619 | 3627 | ||
3620 | return __cfg80211_stop_sched_scan(rdev, false); | 3628 | mutex_lock(&rdev->sched_scan_mtx); |
3629 | err = __cfg80211_stop_sched_scan(rdev, false); | ||
3630 | mutex_unlock(&rdev->sched_scan_mtx); | ||
3631 | |||
3632 | return err; | ||
3621 | } | 3633 | } |
3622 | 3634 | ||
3623 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 3635 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 7a6c67667d70..ae0c2256ba3b 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -100,14 +100,14 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) | |||
100 | rdev = container_of(wk, struct cfg80211_registered_device, | 100 | rdev = container_of(wk, struct cfg80211_registered_device, |
101 | sched_scan_results_wk); | 101 | sched_scan_results_wk); |
102 | 102 | ||
103 | cfg80211_lock_rdev(rdev); | 103 | mutex_lock(&rdev->sched_scan_mtx); |
104 | 104 | ||
105 | /* we don't have sched_scan_req anymore if the scan is stopping */ | 105 | /* we don't have sched_scan_req anymore if the scan is stopping */ |
106 | if (rdev->sched_scan_req) | 106 | if (rdev->sched_scan_req) |
107 | nl80211_send_sched_scan_results(rdev, | 107 | nl80211_send_sched_scan_results(rdev, |
108 | rdev->sched_scan_req->dev); | 108 | rdev->sched_scan_req->dev); |
109 | 109 | ||
110 | cfg80211_unlock_rdev(rdev); | 110 | mutex_unlock(&rdev->sched_scan_mtx); |
111 | } | 111 | } |
112 | 112 | ||
113 | void cfg80211_sched_scan_results(struct wiphy *wiphy) | 113 | void cfg80211_sched_scan_results(struct wiphy *wiphy) |
@@ -123,9 +123,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy) | |||
123 | { | 123 | { |
124 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 124 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
125 | 125 | ||
126 | cfg80211_lock_rdev(rdev); | 126 | mutex_lock(&rdev->sched_scan_mtx); |
127 | __cfg80211_stop_sched_scan(rdev, true); | 127 | __cfg80211_stop_sched_scan(rdev, true); |
128 | cfg80211_unlock_rdev(rdev); | 128 | mutex_unlock(&rdev->sched_scan_mtx); |
129 | } | 129 | } |
130 | EXPORT_SYMBOL(cfg80211_sched_scan_stopped); | 130 | EXPORT_SYMBOL(cfg80211_sched_scan_stopped); |
131 | 131 | ||
@@ -135,7 +135,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | |||
135 | int err; | 135 | int err; |
136 | struct net_device *dev; | 136 | struct net_device *dev; |
137 | 137 | ||
138 | ASSERT_RDEV_LOCK(rdev); | 138 | lockdep_assert_held(&rdev->sched_scan_mtx); |
139 | 139 | ||
140 | if (!rdev->sched_scan_req) | 140 | if (!rdev->sched_scan_req) |
141 | return 0; | 141 | return 0; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index d70f85eb7864..9414b9c5b1e4 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1345,6 +1345,8 @@ out: | |||
1345 | xfrm_state_check_expire(x1); | 1345 | xfrm_state_check_expire(x1); |
1346 | 1346 | ||
1347 | err = 0; | 1347 | err = 0; |
1348 | x->km.state = XFRM_STATE_DEAD; | ||
1349 | __xfrm_state_put(x); | ||
1348 | } | 1350 | } |
1349 | spin_unlock_bh(&x1->lock); | 1351 | spin_unlock_bh(&x1->lock); |
1350 | 1352 | ||