Commit d3a37f33 authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by openeuler-sync-bot
Browse files

ravb: Fix races between ravb_tx_timeout_work() and net related ops

stable inclusion
from stable-v5.10.203
commit f78d0f301395018162f3916a9ce57c41c8898891
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I7EDZ1
CVE: CVE-2023-35827

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f78d0f301395018162f3916a9ce57c41c8898891



--------------------------------

[ Upstream commit 9870257a0a338cd8d6c1cddab74e703f490f6779 ]

Fix races between ravb_tx_timeout_work() and functions of net_device_ops
and ethtool_ops by using rtnl_trylock() and rtnl_unlock(). Note that
since ravb_close() is under the rtnl lock and calls cancel_work_sync(),
ravb_tx_timeout_work() should calls rtnl_trylock(). Otherwise, a deadlock
may happen in ravb_tx_timeout_work() like below:

CPU0			CPU1
			ravb_tx_timeout()
			schedule_work()
...
__dev_close_many()
// Under rtnl lock
ravb_close()
cancel_work_sync()
// Waiting
			ravb_tx_timeout_work()
			rtnl_lock()
			// This is possible to cause a deadlock

If rtnl_trylock() fails, rescheduling the work with sleep for 1 msec.

Fixes: c156633f ("Renesas Ethernet AVB driver proper")
Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: default avatarSergey Shtylyov <s.shtylyov@omp.ru>
Link: https://lore.kernel.org/r/20231127122420.3706751-1-yoshihiro.shimoda.uh@renesas.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarZiyang Xuan <william.xuanziyang@huawei.com>
(cherry picked from commit 9542c73a)
parent 20bc17be
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1442,6 +1442,12 @@ static void ravb_tx_timeout_work(struct work_struct *work)
	struct net_device *ndev = priv->ndev;
	int error;

	if (!rtnl_trylock()) {
		usleep_range(1000, 2000);
		schedule_work(&priv->work);
		return;
	}

	netif_tx_stop_all_queues(ndev);

	/* Stop PTP Clock driver */
@@ -1474,7 +1480,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
		 */
		netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
			   __func__, error);
		return;
		goto out_unlock;
	}
	ravb_emac_init(ndev);

@@ -1484,6 +1490,9 @@ static void ravb_tx_timeout_work(struct work_struct *work)
		ravb_ptp_init(ndev, priv->pdev);

	netif_tx_start_all_queues(ndev);

out_unlock:
	rtnl_unlock();
}

/* Packet transmit function for Ethernet AVB */