Skip to content

Commit 321c181

Browse files
idoschgregkh
authored andcommitted
mlxsw: pci: Fix use-after-free in case of failed devlink reload
[ Upstream commit c4317b1 ] In case devlink reload failed, it is possible to trigger a use-after-free when querying the kernel for device info via 'devlink dev info' [1]. This happens because as part of the reload error path the PCI command interface is de-initialized and its mailboxes are freed. When the devlink '->info_get()' callback is invoked the device is queried via the command interface and the freed mailboxes are accessed. Fix this by initializing the command interface once during probe and not during every reload. This is consistent with the other bus used by mlxsw (i.e., 'mlxsw_i2c') and also allows user space to query the running firmware version (for example) from the device after a failed reload. [1] BUG: KASAN: use-after-free in memcpy include/linux/string.h:406 [inline] BUG: KASAN: use-after-free in mlxsw_pci_cmd_exec+0x177/0xa60 drivers/net/ethernet/mellanox/mlxsw/pci.c:1675 Write of size 4096 at addr ffff88810ae32000 by task syz-executor.1/2355 CPU: 1 PID: 2355 Comm: syz-executor.1 Not tainted 5.8.0-rc2+ #29 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xf6/0x16e lib/dump_stack.c:118 print_address_description.constprop.0+0x1c/0x250 mm/kasan/report.c:383 __kasan_report mm/kasan/report.c:513 [inline] kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530 check_memory_region_inline mm/kasan/generic.c:186 [inline] check_memory_region+0x14e/0x1b0 mm/kasan/generic.c:192 memcpy+0x39/0x60 mm/kasan/common.c:106 memcpy include/linux/string.h:406 [inline] mlxsw_pci_cmd_exec+0x177/0xa60 drivers/net/ethernet/mellanox/mlxsw/pci.c:1675 mlxsw_cmd_exec+0x249/0x550 drivers/net/ethernet/mellanox/mlxsw/core.c:2335 mlxsw_cmd_access_reg drivers/net/ethernet/mellanox/mlxsw/cmd.h:859 [inline] mlxsw_core_reg_access_cmd drivers/net/ethernet/mellanox/mlxsw/core.c:1938 [inline] mlxsw_core_reg_access+0x2f6/0x540 drivers/net/ethernet/mellanox/mlxsw/core.c:1985 mlxsw_reg_query drivers/net/ethernet/mellanox/mlxsw/core.c:2000 [inline] mlxsw_devlink_info_get+0x17f/0x6e0 drivers/net/ethernet/mellanox/mlxsw/core.c:1090 devlink_nl_info_fill.constprop.0+0x13c/0x2d0 net/core/devlink.c:4588 devlink_nl_cmd_info_get_dumpit+0x246/0x460 net/core/devlink.c:4648 genl_lock_dumpit+0x85/0xc0 net/netlink/genetlink.c:575 netlink_dump+0x515/0xe50 net/netlink/af_netlink.c:2245 __netlink_dump_start+0x53d/0x830 net/netlink/af_netlink.c:2353 genl_family_rcv_msg_dumpit.isra.0+0x296/0x300 net/netlink/genetlink.c:638 genl_family_rcv_msg net/netlink/genetlink.c:733 [inline] genl_rcv_msg+0x78d/0x9d0 net/netlink/genetlink.c:753 netlink_rcv_skb+0x152/0x440 net/netlink/af_netlink.c:2469 genl_rcv+0x24/0x40 net/netlink/genetlink.c:764 netlink_unicast_kernel net/netlink/af_netlink.c:1303 [inline] netlink_unicast+0x53a/0x750 net/netlink/af_netlink.c:1329 netlink_sendmsg+0x850/0xd90 net/netlink/af_netlink.c:1918 sock_sendmsg_nosec net/socket.c:652 [inline] sock_sendmsg+0x150/0x190 net/socket.c:672 ____sys_sendmsg+0x6d8/0x840 net/socket.c:2363 ___sys_sendmsg+0xff/0x170 net/socket.c:2417 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2450 do_syscall_64+0x56/0xa0 arch/x86/entry/common.c:359 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: a9c8336 ("mlxsw: core: Add support for devlink info command") Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 477656c commit 321c181

File tree

1 file changed

+38
-16
lines changed
  • drivers/net/ethernet/mellanox/mlxsw

1 file changed

+38
-16
lines changed

drivers/net/ethernet/mellanox/mlxsw/pci.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,23 +1414,12 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
14141414
u16 num_pages;
14151415
int err;
14161416

1417-
mutex_init(&mlxsw_pci->cmd.lock);
1418-
init_waitqueue_head(&mlxsw_pci->cmd.wait);
1419-
14201417
mlxsw_pci->core = mlxsw_core;
14211418

14221419
mbox = mlxsw_cmd_mbox_alloc();
14231420
if (!mbox)
14241421
return -ENOMEM;
14251422

1426-
err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
1427-
if (err)
1428-
goto mbox_put;
1429-
1430-
err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
1431-
if (err)
1432-
goto err_out_mbox_alloc;
1433-
14341423
err = mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id);
14351424
if (err)
14361425
goto err_sw_reset;
@@ -1537,9 +1526,6 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
15371526
mlxsw_pci_free_irq_vectors(mlxsw_pci);
15381527
err_alloc_irq:
15391528
err_sw_reset:
1540-
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
1541-
err_out_mbox_alloc:
1542-
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
15431529
mbox_put:
15441530
mlxsw_cmd_mbox_free(mbox);
15451531
return err;
@@ -1553,8 +1539,6 @@ static void mlxsw_pci_fini(void *bus_priv)
15531539
mlxsw_pci_aqs_fini(mlxsw_pci);
15541540
mlxsw_pci_fw_area_fini(mlxsw_pci);
15551541
mlxsw_pci_free_irq_vectors(mlxsw_pci);
1556-
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
1557-
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
15581542
}
15591543

15601544
static struct mlxsw_pci_queue *
@@ -1776,6 +1760,37 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
17761760
.features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
17771761
};
17781762

1763+
static int mlxsw_pci_cmd_init(struct mlxsw_pci *mlxsw_pci)
1764+
{
1765+
int err;
1766+
1767+
mutex_init(&mlxsw_pci->cmd.lock);
1768+
init_waitqueue_head(&mlxsw_pci->cmd.wait);
1769+
1770+
err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
1771+
if (err)
1772+
goto err_in_mbox_alloc;
1773+
1774+
err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
1775+
if (err)
1776+
goto err_out_mbox_alloc;
1777+
1778+
return 0;
1779+
1780+
err_out_mbox_alloc:
1781+
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
1782+
err_in_mbox_alloc:
1783+
mutex_destroy(&mlxsw_pci->cmd.lock);
1784+
return err;
1785+
}
1786+
1787+
static void mlxsw_pci_cmd_fini(struct mlxsw_pci *mlxsw_pci)
1788+
{
1789+
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
1790+
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
1791+
mutex_destroy(&mlxsw_pci->cmd.lock);
1792+
}
1793+
17791794
static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
17801795
{
17811796
const char *driver_name = pdev->driver->name;
@@ -1831,6 +1846,10 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
18311846
mlxsw_pci->pdev = pdev;
18321847
pci_set_drvdata(pdev, mlxsw_pci);
18331848

1849+
err = mlxsw_pci_cmd_init(mlxsw_pci);
1850+
if (err)
1851+
goto err_pci_cmd_init;
1852+
18341853
mlxsw_pci->bus_info.device_kind = driver_name;
18351854
mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
18361855
mlxsw_pci->bus_info.dev = &pdev->dev;
@@ -1848,6 +1867,8 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
18481867
return 0;
18491868

18501869
err_bus_device_register:
1870+
mlxsw_pci_cmd_fini(mlxsw_pci);
1871+
err_pci_cmd_init:
18511872
iounmap(mlxsw_pci->hw_addr);
18521873
err_ioremap:
18531874
err_pci_resource_len_check:
@@ -1865,6 +1886,7 @@ static void mlxsw_pci_remove(struct pci_dev *pdev)
18651886
struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev);
18661887

18671888
mlxsw_core_bus_device_unregister(mlxsw_pci->core, false);
1889+
mlxsw_pci_cmd_fini(mlxsw_pci);
18681890
iounmap(mlxsw_pci->hw_addr);
18691891
pci_release_regions(mlxsw_pci->pdev);
18701892
pci_disable_device(mlxsw_pci->pdev);

0 commit comments

Comments
 (0)