Commit bb65a0fa authored by Oleksij Rempel's avatar Oleksij Rempel Committed by Zicheng Qu
Browse files

net: usb: lan78xx: Fix double free issue with interrupt buffer allocation

stable inclusion
from stable-v6.6.64
commit a422ebec863d99d5607fb41bb7af3347fcb436d3
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAEY
CVE: CVE-2024-53213

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



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

[ Upstream commit 03819abbeb11117dcbba40bfe322b88c0c88a6b6 ]

In lan78xx_probe(), the buffer `buf` was being freed twice: once
implicitly through `usb_free_urb(dev->urb_intr)` with the
`URB_FREE_BUFFER` flag and again explicitly by `kfree(buf)`. This caused
a double free issue.

To resolve this, reordered `kmalloc()` and `usb_alloc_urb()` calls to
simplify the initialization sequence and removed the redundant
`kfree(buf)`.  Now, `buf` is allocated after `usb_alloc_urb()`, ensuring
it is correctly managed by  `usb_fill_int_urb()` and freed by
`usb_free_urb()` as intended.

Fixes: a6df95ca ("lan78xx: Fix memory allocation bug")
Cc: John Efstathiades <john.efstathiades@pebblebay.com>
Signed-off-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20241116130558.1352230-1-o.rempel@pengutronix.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarZicheng Qu <quzicheng@huawei.com>
parent 92381e91
Loading
Loading
Loading
Loading
+14 −15
Original line number Diff line number Diff line
@@ -4414,29 +4414,30 @@ static int lan78xx_probe(struct usb_interface *intf,

	period = ep_intr->desc.bInterval;
	maxp = usb_maxpacket(dev->udev, dev->pipe_intr);
	buf = kmalloc(maxp, GFP_KERNEL);
	if (!buf) {

	dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->urb_intr) {
		ret = -ENOMEM;
		goto out5;
	}

	dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->urb_intr) {
	buf = kmalloc(maxp, GFP_KERNEL);
	if (!buf) {
		ret = -ENOMEM;
		goto out6;
	} else {
		goto free_urbs;
	}

	usb_fill_int_urb(dev->urb_intr, dev->udev,
			 dev->pipe_intr, buf, maxp,
			 intr_complete, dev, period);
	dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
	}

	dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out);

	/* Reject broken descriptors. */
	if (dev->maxpacket == 0) {
		ret = -ENODEV;
		goto out6;
		goto free_urbs;
	}

	/* driver requires remote-wakeup capability during autosuspend. */
@@ -4444,7 +4445,7 @@ static int lan78xx_probe(struct usb_interface *intf,

	ret = lan78xx_phy_init(dev);
	if (ret < 0)
		goto out7;
		goto free_urbs;

	ret = register_netdev(netdev);
	if (ret != 0) {
@@ -4466,10 +4467,8 @@ static int lan78xx_probe(struct usb_interface *intf,

out8:
	phy_disconnect(netdev->phydev);
out7:
free_urbs:
	usb_free_urb(dev->urb_intr);
out6:
	kfree(buf);
out5:
	lan78xx_unbind(dev, intf);
out4: