Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 886e1974 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller
Browse files

s390/qeth: don't access skb after transmission



After transmitting a skb via send_packet[_fast](), the statistics
code accesses the skb once more to account for transmitted page frags.
This has a (theoretical?) race against the TX completion - if the TX
completion is processed and frees the skb before hard_start_xmit()
gets to the statistics part, we access random memory.

Fix this by caching the # of page frags, before the skb is transmitted.

Signed-off-by: default avatarJulian Wiedmann <jwi@linux.vnet.ibm.com>
Acked-by: default avatarUrsula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d396179c
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -707,7 +707,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
	int data_offset = -1;
	int elements_needed = 0;
	int hd_len = 0;
	int nr_frags;
	unsigned int nr_frags;

	if (card->qdio.do_prio_queueing || (cast_type &&
					card->info.is_multicast_different))
@@ -747,6 +747,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
		if (lin_rc)
			goto tx_drop;
	}
	nr_frags = skb_shinfo(new_skb)->nr_frags;

	if (card->info.type == QETH_CARD_TYPE_OSN)
		hdr = (struct qeth_hdr *)skb->data;
@@ -799,14 +800,11 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
	if (!rc) {
		card->stats.tx_packets++;
		card->stats.tx_bytes += tx_bytes;
		if (card->options.performance_stats) {
			nr_frags = skb_shinfo(new_skb)->nr_frags;
			if (nr_frags) {
		if (card->options.performance_stats && nr_frags) {
			card->perf_stats.sg_skbs_sent++;
			/* nr_frags + skb->data */
			card->perf_stats.sg_frags_sent += nr_frags + 1;
		}
		}
		if (new_skb != skb)
			dev_kfree_skb_any(skb);
		rc = NETDEV_TX_OK;
+2 −2
Original line number Diff line number Diff line
@@ -2650,7 +2650,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
	int tx_bytes = skb->len;
	bool use_tso;
	int data_offset = -1;
	int nr_frags;
	unsigned int nr_frags;

	if (((card->info.type == QETH_CARD_TYPE_IQD) &&
	     (((card->options.cq != QETH_CQ_ENABLED) && !ipv) ||
@@ -2727,6 +2727,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
		if (lin_rc)
			goto tx_drop;
	}
	nr_frags = skb_shinfo(new_skb)->nr_frags;

	if (use_tso) {
		hdr = skb_push(new_skb, sizeof(struct qeth_hdr_tso));
@@ -2786,7 +2787,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
		if (new_skb != skb)
			dev_kfree_skb_any(skb);
		if (card->options.performance_stats) {
			nr_frags = skb_shinfo(new_skb)->nr_frags;
			if (use_tso) {
				card->perf_stats.large_send_bytes += tx_bytes;
				card->perf_stats.large_send_cnt++;