Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mlxsw: spectrum_router: Fix use-after-free in router init / de-init

Several notifiers are registered as part of router initialization.
Since some of these notifiers are registered before the end of the
initialization, it is possible for them to access uninitialized or freed
memory when processing notifications [1].

Additionally, some of these notifiers queue work items on a workqueue.
If these work items are executed after the router was de-initialized,
they will access freed memory.

Fix both problems by moving the registration of the notifiers to the end
of the router initialization and flush the work queue after they are
unregistered.

[1]
BUG: KASAN: use-after-free in __mutex_lock_common kernel/locking/mutex.c:938 [inline]
BUG: KASAN: use-after-free in __mutex_lock+0xeea/0x1340 kernel/locking/mutex.c:1103
Read of size 8 at addr ffff888038c3a6e0 by task kworker/u4:1/61

CPU: 1 PID: 61 Comm: kworker/u4:1 Not tainted 5.8.0-rc2+ #36
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
Workqueue: mlxsw_core_ordered mlxsw_sp_inet6addr_event_work
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
__mutex_lock_common kernel/locking/mutex.c:938 [inline]
__mutex_lock+0xeea/0x1340 kernel/locking/mutex.c:1103
mlxsw_sp_inet6addr_event_work+0xb3/0x1b0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7123
process_one_work+0xa3e/0x17a0 kernel/workqueue.c:2269
worker_thread+0x9e/0x1050 kernel/workqueue.c:2415
kthread+0x355/0x470 kernel/kthread.c:291
ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:293

Allocated by task 1298:
save_stack+0x1b/0x40 mm/kasan/common.c:48
set_track mm/kasan/common.c:56 [inline]
__kasan_kmalloc mm/kasan/common.c:494 [inline]
__kasan_kmalloc.constprop.0+0xc2/0xd0 mm/kasan/common.c:467
kmalloc include/linux/slab.h:555 [inline]
kzalloc include/linux/slab.h:669 [inline]
mlxsw_sp_router_init+0xb2/0x1d20 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:8074
mlxsw_sp_init+0xbd8/0x3ac0 drivers/net/ethernet/mellanox/mlxsw/spectrum.c:2932
__mlxsw_core_bus_device_register+0x657/0x10d0 drivers/net/ethernet/mellanox/mlxsw/core.c:1375
mlxsw_core_bus_device_register drivers/net/ethernet/mellanox/mlxsw/core.c:1436 [inline]
mlxsw_devlink_core_bus_device_reload_up+0xcd/0x150 drivers/net/ethernet/mellanox/mlxsw/core.c:1133
devlink_reload net/core/devlink.c:2959 [inline]
devlink_reload+0x281/0x3b0 net/core/devlink.c:2944
devlink_nl_cmd_reload+0x2f1/0x7c0 net/core/devlink.c:2987
genl_family_rcv_msg_doit net/netlink/genetlink.c:691 [inline]
genl_family_rcv_msg net/netlink/genetlink.c:736 [inline]
genl_rcv_msg+0x611/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

Freed by task 1348:
save_stack+0x1b/0x40 mm/kasan/common.c:48
set_track mm/kasan/common.c:56 [inline]
kasan_set_free_info mm/kasan/common.c:316 [inline]
__kasan_slab_free+0x12c/0x170 mm/kasan/common.c:455
slab_free_hook mm/slub.c:1474 [inline]
slab_free_freelist_hook mm/slub.c:1507 [inline]
slab_free mm/slub.c:3072 [inline]
kfree+0xe6/0x320 mm/slub.c:4063
mlxsw_sp_fini+0x340/0x4e0 drivers/net/ethernet/mellanox/mlxsw/spectrum.c:3132
mlxsw_core_bus_device_unregister+0x16c/0x6d0 drivers/net/ethernet/mellanox/mlxsw/core.c:1474
mlxsw_devlink_core_bus_device_reload_down+0x8e/0xc0 drivers/net/ethernet/mellanox/mlxsw/core.c:1123
devlink_reload+0xc6/0x3b0 net/core/devlink.c:2952
devlink_nl_cmd_reload+0x2f1/0x7c0 net/core/devlink.c:2987
genl_family_rcv_msg_doit net/netlink/genetlink.c:691 [inline]
genl_family_rcv_msg net/netlink/genetlink.c:736 [inline]
genl_rcv_msg+0x611/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

The buggy address belongs to the object at ffff888038c3a000
which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 1760 bytes inside of
2048-byte region [ffff888038c3a000, ffff888038c3a800)
The buggy address belongs to the page:
page:ffffea0000e30e00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 head:ffffea0000e30e00 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x100000000010200(slab|head)
raw: 0100000000010200 dead000000000100 dead000000000122 ffff88806c40c000
raw: 0000000000000000 0000000000080008 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
ffff888038c3a580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888038c3a600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888038c3a680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff888038c3a700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888038c3a780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb

Fixes: 965fa8e600d2 ("mlxsw: spectrum_router: Make RIF deletion more robust")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
5515c344 3c8ce24b

+26 -24
+26 -24
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
··· 8069 8069 mlxsw_sp->router = router; 8070 8070 router->mlxsw_sp = mlxsw_sp; 8071 8071 8072 - router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event; 8073 - err = register_inetaddr_notifier(&router->inetaddr_nb); 8074 - if (err) 8075 - goto err_register_inetaddr_notifier; 8076 - 8077 - router->inet6addr_nb.notifier_call = mlxsw_sp_inet6addr_event; 8078 - err = register_inet6addr_notifier(&router->inet6addr_nb); 8079 - if (err) 8080 - goto err_register_inet6addr_notifier; 8081 - 8082 8072 INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list); 8083 8073 err = __mlxsw_sp_router_init(mlxsw_sp); 8084 8074 if (err) ··· 8109 8119 if (err) 8110 8120 goto err_neigh_init; 8111 8121 8112 - mlxsw_sp->router->netevent_nb.notifier_call = 8113 - mlxsw_sp_router_netevent_event; 8114 - err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb); 8115 - if (err) 8116 - goto err_register_netevent_notifier; 8117 - 8118 8122 err = mlxsw_sp_mp_hash_init(mlxsw_sp); 8119 8123 if (err) 8120 8124 goto err_mp_hash_init; ··· 8116 8132 err = mlxsw_sp_dscp_init(mlxsw_sp); 8117 8133 if (err) 8118 8134 goto err_dscp_init; 8135 + 8136 + router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event; 8137 + err = register_inetaddr_notifier(&router->inetaddr_nb); 8138 + if (err) 8139 + goto err_register_inetaddr_notifier; 8140 + 8141 + router->inet6addr_nb.notifier_call = mlxsw_sp_inet6addr_event; 8142 + err = register_inet6addr_notifier(&router->inet6addr_nb); 8143 + if (err) 8144 + goto err_register_inet6addr_notifier; 8145 + 8146 + mlxsw_sp->router->netevent_nb.notifier_call = 8147 + mlxsw_sp_router_netevent_event; 8148 + err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb); 8149 + if (err) 8150 + goto err_register_netevent_notifier; 8119 8151 8120 8152 mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event; 8121 8153 err = register_fib_notifier(mlxsw_sp_net(mlxsw_sp), ··· 8143 8143 return 0; 8144 8144 8145 8145 err_register_fib_notifier: 8146 - err_dscp_init: 8147 - err_mp_hash_init: 8148 8146 unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb); 8149 8147 err_register_netevent_notifier: 8148 + unregister_inet6addr_notifier(&router->inet6addr_nb); 8149 + err_register_inet6addr_notifier: 8150 + unregister_inetaddr_notifier(&router->inetaddr_nb); 8151 + err_register_inetaddr_notifier: 8152 + mlxsw_core_flush_owq(); 8153 + err_dscp_init: 8154 + err_mp_hash_init: 8150 8155 mlxsw_sp_neigh_fini(mlxsw_sp); 8151 8156 err_neigh_init: 8152 8157 mlxsw_sp_vrs_fini(mlxsw_sp); ··· 8170 8165 err_rifs_init: 8171 8166 __mlxsw_sp_router_fini(mlxsw_sp); 8172 8167 err_router_init: 8173 - unregister_inet6addr_notifier(&router->inet6addr_nb); 8174 - err_register_inet6addr_notifier: 8175 - unregister_inetaddr_notifier(&router->inetaddr_nb); 8176 - err_register_inetaddr_notifier: 8177 8168 mutex_destroy(&mlxsw_sp->router->lock); 8178 8169 kfree(mlxsw_sp->router); 8179 8170 return err; ··· 8180 8179 unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), 8181 8180 &mlxsw_sp->router->fib_nb); 8182 8181 unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb); 8182 + unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb); 8183 + unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb); 8184 + mlxsw_core_flush_owq(); 8183 8185 mlxsw_sp_neigh_fini(mlxsw_sp); 8184 8186 mlxsw_sp_vrs_fini(mlxsw_sp); 8185 8187 mlxsw_sp_mr_fini(mlxsw_sp); ··· 8192 8188 mlxsw_sp_ipips_fini(mlxsw_sp); 8193 8189 mlxsw_sp_rifs_fini(mlxsw_sp); 8194 8190 __mlxsw_sp_router_fini(mlxsw_sp); 8195 - unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb); 8196 - unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb); 8197 8191 mutex_destroy(&mlxsw_sp->router->lock); 8198 8192 kfree(mlxsw_sp->router); 8199 8193 }