From: Greg Kroah-Hartman Date: Mon, 15 Oct 2012 19:07:08 +0000 (-0700) Subject: 3.6-stable patches X-Git-Tag: v3.0.47~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=91e3baec1dee572bde1b1d0800ccf896ef4c94fd;p=thirdparty%2Fkernel%2Fstable-queue.git 3.6-stable patches added patches: ath9k-use-ieee80211_free_txskb.patch kdb-vt_console-fix-missed-data-due-to-pager-overruns.patch mac80211-use-ieee80211_free_txskb-to-fix-possible-skb-leaks.patch md-raid10-use-correct-limit-variable.patch pktgen-fix-crash-when-generating-ipv6-packets.patch --- diff --git a/queue-3.6/ath9k-use-ieee80211_free_txskb.patch b/queue-3.6/ath9k-use-ieee80211_free_txskb.patch new file mode 100644 index 00000000000..84bbce52117 --- /dev/null +++ b/queue-3.6/ath9k-use-ieee80211_free_txskb.patch @@ -0,0 +1,171 @@ +From 249ee72249140fe5b9adc988f97298f0aa5db2fc Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Wed, 3 Oct 2012 21:07:52 +0200 +Subject: ath9k: use ieee80211_free_txskb + +From: Felix Fietkau + +commit 249ee72249140fe5b9adc988f97298f0aa5db2fc upstream. + +Using ieee80211_free_txskb for tx frames is required, since mac80211 clones +skbs for which socket tx status is requested. + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/beacon.c | 2 - + drivers/net/wireless/ath/ath9k/main.c | 2 - + drivers/net/wireless/ath/ath9k/xmit.c | 53 +++++++++++++++++--------------- + 3 files changed, 31 insertions(+), 26 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -120,7 +120,7 @@ static void ath9k_tx_cabq(struct ieee802 + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_dbg(common, XMIT, "CABQ TX failed\n"); +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + } + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -767,7 +767,7 @@ static void ath9k_tx(struct ieee80211_hw + + return; + exit: +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + + static void ath9k_stop(struct ieee80211_hw *hw) +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -66,8 +66,7 @@ static void ath_tx_update_baw(struct ath + static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, + struct ath_txq *txq, + struct ath_atx_tid *tid, +- struct sk_buff *skb, +- bool dequeue); ++ struct sk_buff *skb); + + enum { + MCS_HT20, +@@ -176,7 +175,15 @@ static void ath_tx_flush_tid(struct ath_ + fi = get_frame_info(skb); + bf = fi->bf; + +- if (bf && fi->retries) { ++ if (!bf) { ++ bf = ath_tx_setup_buffer(sc, txq, tid, skb); ++ if (!bf) { ++ ieee80211_free_txskb(sc->hw, skb); ++ continue; ++ } ++ } ++ ++ if (fi->retries) { + list_add_tail(&bf->list, &bf_head); + ath_tx_update_baw(sc, tid, bf->bf_state.seqno); + ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); +@@ -785,10 +792,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_ + fi = get_frame_info(skb); + bf = fi->bf; + if (!fi->bf) +- bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); ++ bf = ath_tx_setup_buffer(sc, txq, tid, skb); + +- if (!bf) ++ if (!bf) { ++ __skb_unlink(skb, &tid->buf_q); ++ ieee80211_free_txskb(sc->hw, skb); + continue; ++ } + + bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; + seqno = bf->bf_state.seqno; +@@ -1731,9 +1741,11 @@ static void ath_tx_send_ampdu(struct ath + return; + } + +- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); +- if (!bf) ++ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); ++ if (!bf) { ++ ieee80211_free_txskb(sc->hw, skb); + return; ++ } + + bf->bf_state.bf_type = BUF_AMPDU; + INIT_LIST_HEAD(&bf_head); +@@ -1757,11 +1769,6 @@ static void ath_tx_send_normal(struct at + struct ath_buf *bf; + + bf = fi->bf; +- if (!bf) +- bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); +- +- if (!bf) +- return; + + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); +@@ -1834,8 +1841,7 @@ u8 ath_txchainmask_reduction(struct ath_ + static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, + struct ath_txq *txq, + struct ath_atx_tid *tid, +- struct sk_buff *skb, +- bool dequeue) ++ struct sk_buff *skb) + { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_frame_info *fi = get_frame_info(skb); +@@ -1847,7 +1853,7 @@ static struct ath_buf *ath_tx_setup_buff + bf = ath_tx_get_buffer(sc); + if (!bf) { + ath_dbg(common, XMIT, "TX buffers are full\n"); +- goto error; ++ return NULL; + } + + ATH_TXBUF_RESET(bf); +@@ -1876,18 +1882,12 @@ static struct ath_buf *ath_tx_setup_buff + ath_err(ath9k_hw_common(sc->sc_ah), + "dma_mapping_error() on TX\n"); + ath_tx_return_buffer(sc, bf); +- goto error; ++ return NULL; + } + + fi->bf = bf; + + return bf; +- +-error: +- if (dequeue) +- __skb_unlink(skb, &tid->buf_q); +- dev_kfree_skb_any(skb); +- return NULL; + } + + /* FIXME: tx power */ +@@ -1916,9 +1916,14 @@ static void ath_tx_start_dma(struct ath_ + */ + ath_tx_send_ampdu(sc, tid, skb, txctl); + } else { +- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); +- if (!bf) ++ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); ++ if (!bf) { ++ if (txctl->paprd) ++ dev_kfree_skb_any(skb); ++ else ++ ieee80211_free_txskb(sc->hw, skb); + return; ++ } + + bf->bf_state.bfs_paprd = txctl->paprd; + diff --git a/queue-3.6/kdb-vt_console-fix-missed-data-due-to-pager-overruns.patch b/queue-3.6/kdb-vt_console-fix-missed-data-due-to-pager-overruns.patch new file mode 100644 index 00000000000..2e488ee0084 --- /dev/null +++ b/queue-3.6/kdb-vt_console-fix-missed-data-due-to-pager-overruns.patch @@ -0,0 +1,126 @@ +From 17b572e82032bc246324ce136696656b66d4e3f1 Mon Sep 17 00:00:00 2001 +From: Jason Wessel +Date: Sun, 26 Aug 2012 22:37:03 -0500 +Subject: kdb,vt_console: Fix missed data due to pager overruns + +From: Jason Wessel + +commit 17b572e82032bc246324ce136696656b66d4e3f1 upstream. + +It is possible to miss data when using the kdb pager. The kdb pager +does not pay attention to the maximum column constraint of the screen +or serial terminal. This result is not incrementing the shown lines +correctly and the pager will print more lines that fit on the screen. +Obviously that is less than useful when using a VGA console where you +cannot scroll back. + +The pager will now look at the kdb_buffer string to see how many +characters are printed. It might not be perfect considering you can +output ASCII that might move the cursor position, but it is a +substantially better approximation for viewing dmesg and trace logs. + +This also means that the vt screen needs to set the kdb COLUMNS +variable. + +Signed-off-by: Jason Wessel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/vt/vt.c | 13 +++++++++++++ + kernel/debug/kdb/kdb_io.c | 33 ++++++++++++++++++++++++++++----- + 2 files changed, 41 insertions(+), 5 deletions(-) + +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -3475,6 +3475,19 @@ int con_debug_enter(struct vc_data *vc) + kdb_set(2, setargs); + } + } ++ if (vc->vc_cols < 999) { ++ int colcount; ++ char cols[4]; ++ const char *setargs[3] = { ++ "set", ++ "COLUMNS", ++ cols, ++ }; ++ if (kdbgetintenv(setargs[0], &colcount)) { ++ snprintf(cols, 4, "%i", vc->vc_cols); ++ kdb_set(2, setargs); ++ } ++ } + #endif /* CONFIG_KGDB_KDB */ + return ret; + } +--- a/kernel/debug/kdb/kdb_io.c ++++ b/kernel/debug/kdb/kdb_io.c +@@ -552,6 +552,7 @@ int vkdb_printf(const char *fmt, va_list + { + int diag; + int linecount; ++ int colcount; + int logging, saved_loglevel = 0; + int saved_trap_printk; + int got_printf_lock = 0; +@@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list + if (diag || linecount <= 1) + linecount = 24; + ++ diag = kdbgetintenv("COLUMNS", &colcount); ++ if (diag || colcount <= 1) ++ colcount = 80; ++ + diag = kdbgetintenv("LOGGING", &logging); + if (diag) + logging = 0; +@@ -690,7 +695,7 @@ kdb_printit: + gdbstub_msg_write(kdb_buffer, retlen); + } else { + if (dbg_io_ops && !dbg_io_ops->is_console) { +- len = strlen(kdb_buffer); ++ len = retlen; + cp = kdb_buffer; + while (len--) { + dbg_io_ops->write_char(*cp); +@@ -709,11 +714,29 @@ kdb_printit: + printk(KERN_INFO "%s", kdb_buffer); + } + +- if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) +- kdb_nextline++; ++ if (KDB_STATE(PAGER)) { ++ /* ++ * Check printed string to decide how to bump the ++ * kdb_nextline to control when the more prompt should ++ * show up. ++ */ ++ int got = 0; ++ len = retlen; ++ while (len--) { ++ if (kdb_buffer[len] == '\n') { ++ kdb_nextline++; ++ got = 0; ++ } else if (kdb_buffer[len] == '\r') { ++ got = 0; ++ } else { ++ got++; ++ } ++ } ++ kdb_nextline += got / (colcount + 1); ++ } + + /* check for having reached the LINES number of printed lines */ +- if (kdb_nextline == linecount) { ++ if (kdb_nextline >= linecount) { + char buf1[16] = ""; + + /* Watch out for recursion here. Any routine that calls +@@ -765,7 +788,7 @@ kdb_printit: + kdb_grepping_flag = 0; + kdb_printf("\n"); + } else if (buf1[0] == ' ') { +- kdb_printf("\n"); ++ kdb_printf("\r"); + suspend_grep = 1; /* for this recursion */ + } else if (buf1[0] == '\n') { + kdb_nextline = linecount - 1; diff --git a/queue-3.6/mac80211-use-ieee80211_free_txskb-to-fix-possible-skb-leaks.patch b/queue-3.6/mac80211-use-ieee80211_free_txskb-to-fix-possible-skb-leaks.patch new file mode 100644 index 00000000000..7f781617779 --- /dev/null +++ b/queue-3.6/mac80211-use-ieee80211_free_txskb-to-fix-possible-skb-leaks.patch @@ -0,0 +1,129 @@ +From c3e7724b6bc2f25e46c38dbe68f09d71fafeafb8 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 8 Oct 2012 14:39:33 +0200 +Subject: mac80211: use ieee80211_free_txskb to fix possible skb leaks + +From: Felix Fietkau + +commit c3e7724b6bc2f25e46c38dbe68f09d71fafeafb8 upstream. + +A few places free skbs using dev_kfree_skb even though they're called +after ieee80211_subif_start_xmit might have cloned it for tracking tx +status. Use ieee80211_free_txskb here to prevent skb leaks. + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/status.c | 4 ++-- + net/mac80211/tx.c | 22 ++++++++++++---------- + 2 files changed, 14 insertions(+), 12 deletions(-) + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -34,7 +34,7 @@ void ieee80211_tx_status_irqsafe(struct + skb_queue_len(&local->skb_queue_unreliable); + while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && + (skb = skb_dequeue(&local->skb_queue_unreliable))) { +- dev_kfree_skb_irq(skb); ++ ieee80211_free_txskb(hw, skb); + tmp--; + I802_DEBUG_INC(local->tx_status_drop); + } +@@ -159,7 +159,7 @@ static void ieee80211_handle_filtered_fr + "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", + skb_queue_len(&sta->tx_filtered[ac]), + !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies); +- dev_kfree_skb(skb); ++ ieee80211_free_txskb(&local->hw, skb); + } + + static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid) +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -354,7 +354,7 @@ static void purge_old_ps_buffers(struct + total += skb_queue_len(&sta->ps_tx_buf[ac]); + if (skb) { + purged++; +- dev_kfree_skb(skb); ++ ieee80211_free_txskb(&local->hw, skb); + break; + } + } +@@ -466,7 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee + ps_dbg(tx->sdata, + "STA %pM TX buffer for AC %d full - dropping oldest frame\n", + sta->sta.addr, ac); +- dev_kfree_skb(old); ++ ieee80211_free_txskb(&local->hw, old); + } else + tx->local->total_ps_buffered++; + +@@ -1103,7 +1103,7 @@ static bool ieee80211_tx_prep_agg(struct + spin_unlock(&tx->sta->lock); + + if (purge_skb) +- dev_kfree_skb(purge_skb); ++ ieee80211_free_txskb(&tx->local->hw, purge_skb); + } + + /* reset session timer */ +@@ -1214,7 +1214,7 @@ static bool ieee80211_tx_frags(struct ie + #ifdef CONFIG_MAC80211_VERBOSE_DEBUG + if (WARN_ON_ONCE(q >= local->hw.queues)) { + __skb_unlink(skb, skbs); +- dev_kfree_skb(skb); ++ ieee80211_free_txskb(&local->hw, skb); + continue; + } + #endif +@@ -1356,7 +1356,7 @@ static int invoke_tx_handlers(struct iee + if (unlikely(res == TX_DROP)) { + I802_DEBUG_INC(tx->local->tx_handlers_drop); + if (tx->skb) +- dev_kfree_skb(tx->skb); ++ ieee80211_free_txskb(&tx->local->hw, tx->skb); + else + __skb_queue_purge(&tx->skbs); + return -1; +@@ -1393,7 +1393,7 @@ static bool ieee80211_tx(struct ieee8021 + res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); + + if (unlikely(res_prepare == TX_DROP)) { +- dev_kfree_skb(skb); ++ ieee80211_free_txskb(&local->hw, skb); + goto out; + } else if (unlikely(res_prepare == TX_QUEUED)) { + goto out; +@@ -1466,7 +1466,7 @@ void ieee80211_xmit(struct ieee80211_sub + headroom = max_t(int, 0, headroom); + + if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { +- dev_kfree_skb(skb); ++ ieee80211_free_txskb(&local->hw, skb); + rcu_read_unlock(); + return; + } +@@ -2060,8 +2060,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s + head_need += IEEE80211_ENCRYPT_HEADROOM; + head_need += local->tx_headroom; + head_need = max_t(int, 0, head_need); +- if (ieee80211_skb_resize(sdata, skb, head_need, true)) +- goto fail; ++ if (ieee80211_skb_resize(sdata, skb, head_need, true)) { ++ ieee80211_free_txskb(&local->hw, skb); ++ return NETDEV_TX_OK; ++ } + } + + if (encaps_data) { +@@ -2196,7 +2198,7 @@ void ieee80211_tx_pending(unsigned long + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + if (WARN_ON(!info->control.vif)) { +- kfree_skb(skb); ++ ieee80211_free_txskb(&local->hw, skb); + continue; + } + diff --git a/queue-3.6/md-raid10-use-correct-limit-variable.patch b/queue-3.6/md-raid10-use-correct-limit-variable.patch new file mode 100644 index 00000000000..b33b4d1fdf6 --- /dev/null +++ b/queue-3.6/md-raid10-use-correct-limit-variable.patch @@ -0,0 +1,34 @@ +From 91502f099dfc5a1e8812898e26ee280713e1d002 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Thu, 11 Oct 2012 14:20:58 +1100 +Subject: md/raid10: use correct limit variable + +From: Dan Carpenter + +commit 91502f099dfc5a1e8812898e26ee280713e1d002 upstream. + +Clang complains that we are assigning a variable to itself. This should +be using bad_sectors like the similar earlier check does. + +Bug has been present since 3.1-rc1. It is minor but could +conceivably cause corruption or other bad behaviour. + +Signed-off-by: Dan Carpenter +Signed-off-by: NeilBrown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/raid10.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -3158,7 +3158,7 @@ static sector_t sync_request(struct mdde + else { + bad_sectors -= (sector - first_bad); + if (max_sync > bad_sectors) +- max_sync = max_sync; ++ max_sync = bad_sectors; + continue; + } + } diff --git a/queue-3.6/pktgen-fix-crash-when-generating-ipv6-packets.patch b/queue-3.6/pktgen-fix-crash-when-generating-ipv6-packets.patch new file mode 100644 index 00000000000..e01c11f19f1 --- /dev/null +++ b/queue-3.6/pktgen-fix-crash-when-generating-ipv6-packets.patch @@ -0,0 +1,44 @@ +From 5aa8b572007c4bca1e6d3dd4c4820f1ae49d6bb2 Mon Sep 17 00:00:00 2001 +From: Amerigo Wang +Date: Tue, 9 Oct 2012 17:48:16 +0000 +Subject: pktgen: fix crash when generating IPv6 packets + +From: Amerigo Wang + +commit 5aa8b572007c4bca1e6d3dd4c4820f1ae49d6bb2 upstream. + +For IPv6, sizeof(struct ipv6hdr) = 40, thus the following +expression will result negative: + + datalen = pkt_dev->cur_pkt_size - 14 - + sizeof(struct ipv6hdr) - sizeof(struct udphdr) - + pkt_dev->pkt_overhead; + +And, the check "if (datalen < sizeof(struct pktgen_hdr))" will be +passed as "datalen" is promoted to unsigned, therefore will cause +a crash later. + +This is a quick fix by checking if "datalen" is negative. The following +patch will increase the default value of 'min_pkt_size' for IPv6. + +This bug should exist for a long time, so Cc -stable too. + +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/core/pktgen.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -2927,7 +2927,7 @@ static struct sk_buff *fill_packet_ipv6( + sizeof(struct ipv6hdr) - sizeof(struct udphdr) - + pkt_dev->pkt_overhead; + +- if (datalen < sizeof(struct pktgen_hdr)) { ++ if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) { + datalen = sizeof(struct pktgen_hdr); + net_info_ratelimited("increased datalen to %d\n", datalen); + } diff --git a/queue-3.6/series b/queue-3.6/series index dfb838e89bd..4c18aa2471f 100644 --- a/queue-3.6/series +++ b/queue-3.6/series @@ -44,3 +44,8 @@ viafb-don-t-touch-clock-state-on-olpc-xo-1.5.patch timekeeping-cast-raw_interval-to-u64-to-avoid-shift-overflow.patch timers-fix-endless-looping-between-cascade-and-internal_add_timer.patch nohz-fix-one-jiffy-count-too-far-in-idle-cputime.patch +ath9k-use-ieee80211_free_txskb.patch +mac80211-use-ieee80211_free_txskb-to-fix-possible-skb-leaks.patch +md-raid10-use-correct-limit-variable.patch +kdb-vt_console-fix-missed-data-due-to-pager-overruns.patch +pktgen-fix-crash-when-generating-ipv6-packets.patch