net: introduce CAN specific pointer in the struct net_device
[ Upstream commit 4e096a18867a5a989b510f6999d9c6b6622e8f7b ] Since20dd3850bc
("can: Speed up CAN frame receiption by using ml_priv") the CAN framework uses per device specific data in the AF_CAN protocol. For this purpose the struct net_device->ml_priv is used. Later the ml_priv usage in CAN was extended for other users, one of them being CAN_J1939. Later in the kernel ml_priv was converted to an union, used by other drivers. E.g. the tun driver started storing it's stats pointer. Since tun devices can claim to be a CAN device, CAN specific protocols will wrongly interpret this pointer, which will cause system crashes. Mostly this issue is visible in the CAN_J1939 stack. To fix this issue, we request a dedicated CAN pointer within the net_device struct. Reported-by: syzbot+5138c4dd15a0401bec7b@syzkaller.appspotmail.com Fixes:20dd3850bc
("can: Speed up CAN frame receiption by using ml_priv") Fixes:ffd956eef6
("can: introduce CAN midlayer private and allocate it automatically") Fixes:9d71dd0c70
("can: add support of SAE J1939 protocol") Fixes: 497a5757ce4e ("tun: switch to net core provided statistics counters") Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Link: https://lore.kernel.org/r/20210223070127.4538-1-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
9e35159c6e
commit
1a5751d58b
@@ -304,8 +304,8 @@ static struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net,
|
||||
struct net_device *dev)
|
||||
{
|
||||
if (dev) {
|
||||
struct can_ml_priv *ml_priv = dev->ml_priv;
|
||||
return &ml_priv->dev_rcv_lists;
|
||||
struct can_ml_priv *can_ml = can_get_ml_priv(dev);
|
||||
return &can_ml->dev_rcv_lists;
|
||||
} else {
|
||||
return net->can.rx_alldev_list;
|
||||
}
|
||||
@@ -790,25 +790,6 @@ void can_proto_unregister(const struct can_proto *cp)
|
||||
}
|
||||
EXPORT_SYMBOL(can_proto_unregister);
|
||||
|
||||
/* af_can notifier to create/remove CAN netdevice specific structs */
|
||||
static int can_notifier(struct notifier_block *nb, unsigned long msg,
|
||||
void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
if (dev->type != ARPHRD_CAN)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
switch (msg) {
|
||||
case NETDEV_REGISTER:
|
||||
WARN(!dev->ml_priv,
|
||||
"No CAN mid layer private allocated, please fix your driver and use alloc_candev()!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int can_pernet_init(struct net *net)
|
||||
{
|
||||
spin_lock_init(&net->can.rcvlists_lock);
|
||||
@@ -876,11 +857,6 @@ static const struct net_proto_family can_family_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/* notifier block for netdevice event */
|
||||
static struct notifier_block can_netdev_notifier __read_mostly = {
|
||||
.notifier_call = can_notifier,
|
||||
};
|
||||
|
||||
static struct pernet_operations can_pernet_ops __read_mostly = {
|
||||
.init = can_pernet_init,
|
||||
.exit = can_pernet_exit,
|
||||
@@ -911,17 +887,12 @@ static __init int can_init(void)
|
||||
err = sock_register(&can_family_ops);
|
||||
if (err)
|
||||
goto out_sock;
|
||||
err = register_netdevice_notifier(&can_netdev_notifier);
|
||||
if (err)
|
||||
goto out_notifier;
|
||||
|
||||
dev_add_pack(&can_packet);
|
||||
dev_add_pack(&canfd_packet);
|
||||
|
||||
return 0;
|
||||
|
||||
out_notifier:
|
||||
sock_unregister(PF_CAN);
|
||||
out_sock:
|
||||
unregister_pernet_subsys(&can_pernet_ops);
|
||||
out_pernet:
|
||||
@@ -935,7 +906,6 @@ static __exit void can_exit(void)
|
||||
/* protocol unregister */
|
||||
dev_remove_pack(&canfd_packet);
|
||||
dev_remove_pack(&can_packet);
|
||||
unregister_netdevice_notifier(&can_netdev_notifier);
|
||||
sock_unregister(PF_CAN);
|
||||
|
||||
unregister_pernet_subsys(&can_pernet_ops);
|
||||
|
Reference in New Issue
Block a user