Commit e5c111ca authored by Chun-Yi Lee's avatar Chun-Yi Lee Committed by Ziyang Xuan
Browse files

aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts

stable inclusion
from stable-v5.10.214
commit faf0b4c5e00bb680e8e43ac936df24d3f48c8e65
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8TQCT
CVE: CVE-2023-6270

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

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

[ Upstream commit f98364e926626c678fb4b9004b75cacf92ff0662 ]

This patch is against CVE-2023-6270. The description of cve is:

  A flaw was found in the ATA over Ethernet (AoE) driver in the Linux
  kernel. The aoecmd_cfg_pkts() function improperly updates the refcnt on
  `struct net_device`, and a use-after-free can be triggered by racing
  between the free on the struct and the access through the `skbtxq`
  global queue. This could lead to a denial of service condition or
  potential code execution.

In aoecmd_cfg_pkts(), it always calls dev_put(ifp) when skb initial
code is finished. But the net_device ifp will still be used in
later tx()->dev_queue_xmit() in kthread. Which means that the
dev_put(ifp) should NOT be called in the success path of skb
initial code in aoecmd_cfg_pkts(). Otherwise tx() may run into
use-after-free because the net_device is freed.

This patch removed the dev_put(ifp) in the success path in
aoecmd_cfg_pkts(), and added dev_put() after skb xmit in tx().

Link: https://nvd.nist.gov/vuln/detail/CVE-2023-6270


Fixes: 7562f876 ("[NET]: Rework dev_base via list_head (v3)")
Signed-off-by: default avatarChun-Yi Lee <jlee@suse.com>
Link: https://lore.kernel.org/r/20240305082048.25526-1-jlee@suse.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarZiyang Xuan <william.xuanziyang@huawei.com>
parent b74d64b8
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -420,13 +420,16 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *qu
	rcu_read_lock();
	for_each_netdev_rcu(&init_net, ifp) {
		dev_hold(ifp);
		if (!is_aoe_netif(ifp))
			goto cont;
		if (!is_aoe_netif(ifp)) {
			dev_put(ifp);
			continue;
		}

		skb = new_skb(sizeof *h + sizeof *ch);
		if (skb == NULL) {
			printk(KERN_INFO "aoe: skb alloc failure\n");
			goto cont;
			dev_put(ifp);
			continue;
		}
		skb_put(skb, sizeof *h + sizeof *ch);
		skb->dev = ifp;
@@ -441,9 +444,6 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *qu
		h->major = cpu_to_be16(aoemajor);
		h->minor = aoeminor;
		h->cmd = AOECMD_CFG;

cont:
		dev_put(ifp);
	}
	rcu_read_unlock();
}
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ tx(int id) __must_hold(&txlock)
			pr_warn("aoe: packet could not be sent on %s.  %s\n",
				ifp ? ifp->name : "netif",
				"consider increasing tx_queue_len");
		dev_put(ifp);
		spin_lock_irq(&txlock);
	}
	return 0;