FAILED: patch "[PATCH] can: bcm/raw/isotp: use per module netdevice notifier" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8d0caedb759683041d9db82069937525999ada53 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <[email protected]>
Date: Sat, 5 Jun 2021 19:26:35 +0900
Subject: [PATCH] can: bcm/raw/isotp: use per module netdevice notifier
syzbot is reporting hung task at register_netdevice_notifier() [1] and unregister_netdevice_notifier() [2], for cleanup_net() might perform time consuming operations while CAN driver's raw/bcm/isotp modules are calling {register,unregister}_netdevice_notifier() on each socket.
Change raw/bcm/isotp modules to call register_netdevice_notifier() from module's __init function and call unregister_netdevice_notifier() from module's __exit function, as with gw/j1939 modules are doing.
net/can/bcm.c +46 -13
@@ -125,7 +125,7 @@ struct bcm_sock {struct sock sk;int bound;int ifindex; -struct notifier_block notifier; +struct list_head notifier;struct list_head rx_ops;struct list_head tx_ops;unsigned long dropped_usr_msgs;
@@ -133,6 +133,10 @@ struct bcm_sock {char procname [32 ];/* inode number in decimal with \0 */ }; +static LIST_HEAD (bcm_notifier_list); +static DEFINE_SPINLOCK (bcm_notifier_lock); +static struct bcm_sock *bcm_busy_notifier; +static inline struct bcm_sock *bcm_sk (const struct sock *sk) {return (struct bcm_sock *)sk;
@@ -1378,20 +1382,15 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)/* * notification handler for netdevice status changes */ -static int bcm_notifier (struct notifier_block *nb,unsigned long msg, -void *ptr) +static void bcm_notify (struct bcm_sock *bo,unsigned long msg, +struct net_device *dev) { -struct net_device *dev =netdev_notifier_info_to_dev (ptr); - struct bcm_sock *bo = container_of(nb, struct bcm_sock, notifier);struct sock *sk = &bo->sk;struct bcm_op *op;int notify_enodev =0 ;if (!net_eq (dev_net (dev),sock_net (sk))) -return NOTIFY_DONE ; - -if (dev->type !=ARPHRD_CAN ) -return NOTIFY_DONE ; +return ;switch (msg) {
@@ -1426,7 +1425,28 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg, sk->sk_error_report (sk); } } +} +static int bcm_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 ; +if (msg !=NETDEV_UNREGISTER && msg !=NETDEV_DOWN ) +return NOTIFY_DONE ; +if (unlikely (bcm_busy_notifier))/* Check for reentrant bug. */ +return NOTIFY_DONE ; + +spin_lock (&bcm_notifier_lock); +list_for_each_entry (bcm_busy_notifier, &bcm_notifier_list, notifier) { +spin_unlock (&bcm_notifier_lock); +bcm_notify (bcm_busy_notifier, msg, dev); +spin_lock (&bcm_notifier_lock); + } + bcm_busy_notifier =NULL ; +spin_unlock (&bcm_notifier_lock);return NOTIFY_DONE ; }
@@ -1446,9 +1466,9 @@ static int bcm_init(struct sock *sk)INIT_LIST_HEAD (&bo->rx_ops);/* set notifier */ - bo->notifier.notifier_call = bcm_notifier; - -register_netdevice_notifier (&bo->notifier); +spin_lock (&bcm_notifier_lock); +list_add_tail (&bo->notifier, &bcm_notifier_list); +spin_unlock (&bcm_notifier_lock);return 0 ; }
@@ -1471,7 +1491,14 @@ static int bcm_release(struct socket *sock)/* remove bcm_ops, timer, rx_unregister(), etc. */ -unregister_netdevice_notifier (&bo->notifier); +spin_lock (&bcm_notifier_lock); +while (bcm_busy_notifier == bo) { +spin_unlock (&bcm_notifier_lock); +schedule_timeout_uninterruptible (1 ); +spin_lock (&bcm_notifier_lock); + } +list_del (&bo->notifier); +spin_unlock (&bcm_notifier_lock);lock_sock (sk);
@@ -1692,6 +1719,10 @@ static struct pernet_operations canbcm_pernet_ops __read_mostly = { .exit = canbcm_pernet_exit, }; +static struct notifier_block canbcm_notifier = { + .notifier_call = bcm_notifier +}; +static int __init bcm_module_init (void ) {int err;
@@ -1705,12 +1736,14 @@ static int __init bcm_module_init(void) }register_pernet_subsys (&canbcm_pernet_ops); +register_netdevice_notifier (&canbcm_notifier);return 0 ; } static void __exit bcm_module_exit(void) {can_proto_unregister (&bcm_can_proto); +unregister_netdevice_notifier (&canbcm_notifier);unregister_pernet_subsys (&canbcm_pernet_ops); }
net/can/isotp.c +48 -13
119 lines not on this page · raw message
net/can/raw.c +48 -14
123 lines not on this page · raw message