Unverified Commit 418d2110 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!9657 v2 CVE-2024-38586

Merge Pull Request from: @ci-robot 
 
PR sync from: Liu Jian <liujian56@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/TMPPVFK7UH3BQ6ST5UWBP6EGGUSFJ4SW/ 
CVE-2024-38586

Heiner Kallweit (5):
  r8169: remove unneeded memory barrier in rtl_tx
  r8169: use READ_ONCE in rtl_tx_slots_avail
  r8169: improve rtl_tx
  r8169: improve rtl8169_start_xmit
  r8169: remove nr_frags argument from rtl_tx_slots_avail

Ken Milmore (1):
  r8169: Fix possible ring buffer corruption on fragmented Tx packets.


-- 
2.34.1
 
https://gitee.com/src-openeuler/kernel/issues/IA6SF4 
 
Link:https://gitee.com/openeuler/kernel/pulls/9657

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 2356504f def045a5
Loading
Loading
Loading
Loading
+19 −25
Original line number Diff line number Diff line
@@ -4253,13 +4253,13 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
	return true;
}

static bool rtl_tx_slots_avail(struct rtl8169_private *tp,
			       unsigned int nr_frags)
static bool rtl_tx_slots_avail(struct rtl8169_private *tp)
{
	unsigned int slots_avail = tp->dirty_tx + NUM_TX_DESC - tp->cur_tx;
	unsigned int slots_avail = READ_ONCE(tp->dirty_tx) + NUM_TX_DESC
					- READ_ONCE(tp->cur_tx);

	/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
	return slots_avail > nr_frags;
	return slots_avail > MAX_SKB_FRAGS;
}

/* Versions RTL8102e and from RTL8168c onwards support csum_v2 */
@@ -4285,16 +4285,16 @@ static void rtl8169_doorbell(struct rtl8169_private *tp)
static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
				      struct net_device *dev)
{
	unsigned int frags = skb_shinfo(skb)->nr_frags;
	struct rtl8169_private *tp = netdev_priv(dev);
	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
	struct TxDesc *txd_first, *txd_last;
	bool stop_queue, door_bell;
	unsigned int frags;
	u32 opts[2];

	txd_first = tp->TxDescArray + entry;

	if (unlikely(!rtl_tx_slots_avail(tp, frags))) {
	if (unlikely(!rtl_tx_slots_avail(tp))) {
		if (net_ratelimit())
			netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
		goto err_stop_0;
@@ -4315,6 +4315,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
				    entry, false)))
		goto err_dma_0;

	frags = skb_shinfo(skb)->nr_frags;
	if (frags) {
		if (rtl8169_xmit_frags(tp, skb, opts, entry))
			goto err_dma_1;
@@ -4337,22 +4338,15 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
	/* rtl_tx needs to see descriptor changes before updated tp->cur_tx */
	smp_wmb();

	tp->cur_tx += frags + 1;
	WRITE_ONCE(tp->cur_tx, tp->cur_tx + frags + 1);

	stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS);
	stop_queue = !rtl_tx_slots_avail(tp);
	if (unlikely(stop_queue)) {
		/* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
		 * not miss a ring update when it notices a stopped queue.
		 */
		smp_wmb();
		netif_stop_queue(dev);
		door_bell = true;
	}

	if (door_bell)
		rtl8169_doorbell(tp);

	if (unlikely(stop_queue)) {
		/* Sync with rtl_tx:
		 * - publish queue status and cur_tx ring index (write barrier)
		 * - refresh dirty_tx ring index (read barrier).
@@ -4360,11 +4354,15 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
		 * status and forget to wake up queue, a racing rtl_tx thread
		 * can't.
		 */
		smp_mb();
		if (rtl_tx_slots_avail(tp, MAX_SKB_FRAGS))
		smp_mb__after_atomic();
		if (rtl_tx_slots_avail(tp))
			netif_start_queue(dev);
		door_bell = true;
	}

	if (door_bell)
		rtl8169_doorbell(tp);

	return NETDEV_TX_OK;

err_dma_1:
@@ -4475,12 +4473,11 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,
		   int budget)
{
	unsigned int dirty_tx, tx_left, bytes_compl = 0, pkts_compl = 0;
	unsigned int dirty_tx, bytes_compl = 0, pkts_compl = 0;

	dirty_tx = tp->dirty_tx;
	smp_rmb();

	for (tx_left = tp->cur_tx - dirty_tx; tx_left > 0; tx_left--) {
	while (READ_ONCE(tp->cur_tx) != dirty_tx) {
		unsigned int entry = dirty_tx % NUM_TX_DESC;
		struct sk_buff *skb = tp->tx_skb[entry].skb;
		u32 status;
@@ -4504,7 +4501,6 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,

		rtl_inc_priv_stats(&tp->tx_stats, pkts_compl, bytes_compl);

		tp->dirty_tx = dirty_tx;
		/* Sync with rtl8169_start_xmit:
		 * - publish dirty_tx ring index (write barrier)
		 * - refresh cur_tx ring index and queue status (read barrier)
@@ -4512,11 +4508,9 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,
		 * a racing xmit thread can only have a right view of the
		 * ring status.
		 */
		smp_mb();
		if (netif_queue_stopped(dev) &&
		    rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) {
		smp_store_mb(tp->dirty_tx, dirty_tx);
		if (netif_queue_stopped(dev) && rtl_tx_slots_avail(tp))
			netif_wake_queue(dev);
		}
		/*
		 * 8168 hack: TxPoll requests are lost when the Tx packets are
		 * too close. Let's kick an extra TxPoll request when a burst