]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 21 Jun 2021 15:33:43 +0000 (17:33 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 21 Jun 2021 15:33:43 +0000 (17:33 +0200)
added patches:
can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch
usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch

queue-4.9/can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch [new file with mode: 0644]

diff --git a/queue-4.9/can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch b/queue-4.9/can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch
new file mode 100644 (file)
index 0000000..f715376
--- /dev/null
@@ -0,0 +1,303 @@
+From 8d0caedb759683041d9db82069937525999ada53 Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+Date: Sat, 5 Jun 2021 19:26:35 +0900
+Subject: can: bcm/raw/isotp: use per module netdevice notifier
+
+From: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+
+commit 8d0caedb759683041d9db82069937525999ada53 upstream.
+
+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.
+
+Link: https://syzkaller.appspot.com/bug?id=391b9498827788b3cc6830226d4ff5be87107c30 [1]
+Link: https://syzkaller.appspot.com/bug?id=1724d278c83ca6e6df100a2e320c10d991cf2bce [2]
+Link: https://lore.kernel.org/r/54a5f451-05ed-f977-8534-79e7aa2bcc8f@i-love.sakura.ne.jp
+Cc: linux-stable <stable@vger.kernel.org>
+Reported-by: syzbot <syzbot+355f8edb2ff45d5f95fa@syzkaller.appspotmail.com>
+Reported-by: syzbot <syzbot+0f1827363a305f74996f@syzkaller.appspotmail.com>
+Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
+Tested-by: syzbot <syzbot+355f8edb2ff45d5f95fa@syzkaller.appspotmail.com>
+Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/can/bcm.c |   61 ++++++++++++++++++++++++++++++++++++++++++++-------------
+ net/can/raw.c |   62 ++++++++++++++++++++++++++++++++++++++++++++--------------
+ 2 files changed, 96 insertions(+), 27 deletions(-)
+
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -127,7 +127,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;
+@@ -135,6 +135,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;
+@@ -1439,20 +1443,15 @@ static int bcm_sendmsg(struct socket *so
+ /*
+  * 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), &init_net))
+-              return NOTIFY_DONE;
+-
+-      if (dev->type != ARPHRD_CAN)
+-              return NOTIFY_DONE;
++              return;
+       switch (msg) {
+@@ -1487,7 +1486,28 @@ static int bcm_notifier(struct notifier_
+                               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;
+ }
+@@ -1507,9 +1527,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;
+ }
+@@ -1530,7 +1550,14 @@ static int bcm_release(struct socket *so
+       /* 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);
+@@ -1716,6 +1743,10 @@ static const struct can_proto bcm_can_pr
+       .prot       = &bcm_proto,
+ };
++static struct notifier_block canbcm_notifier = {
++      .notifier_call = bcm_notifier
++};
++
+ static int __init bcm_module_init(void)
+ {
+       int err;
+@@ -1730,6 +1761,8 @@ static int __init bcm_module_init(void)
+       /* create /proc/net/can-bcm directory */
+       proc_dir = proc_mkdir("can-bcm", init_net.proc_net);
++      register_netdevice_notifier(&canbcm_notifier);
++
+       return 0;
+ }
+@@ -1739,6 +1772,8 @@ static void __exit bcm_module_exit(void)
+       if (proc_dir)
+               remove_proc_entry("can-bcm", init_net.proc_net);
++
++      unregister_netdevice_notifier(&canbcm_notifier);
+ }
+ module_init(bcm_module_init);
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -84,7 +84,7 @@ struct raw_sock {
+       struct sock sk;
+       int bound;
+       int ifindex;
+-      struct notifier_block notifier;
++      struct list_head notifier;
+       int loopback;
+       int recv_own_msgs;
+       int fd_frames;
+@@ -96,6 +96,10 @@ struct raw_sock {
+       struct uniqframe __percpu *uniq;
+ };
++static LIST_HEAD(raw_notifier_list);
++static DEFINE_SPINLOCK(raw_notifier_lock);
++static struct raw_sock *raw_busy_notifier;
++
+ /*
+  * Return pointer to store the extra msg flags for raw_recvmsg().
+  * We use the space of one unsigned int beyond the 'struct sockaddr_can'
+@@ -260,21 +264,16 @@ static int raw_enable_allfilters(struct
+       return err;
+ }
+-static int raw_notifier(struct notifier_block *nb,
+-                      unsigned long msg, void *ptr)
++static void raw_notify(struct raw_sock *ro, unsigned long msg,
++                     struct net_device *dev)
+ {
+-      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+-      struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
+       struct sock *sk = &ro->sk;
+       if (!net_eq(dev_net(dev), &init_net))
+-              return NOTIFY_DONE;
+-
+-      if (dev->type != ARPHRD_CAN)
+-              return NOTIFY_DONE;
++              return;
+       if (ro->ifindex != dev->ifindex)
+-              return NOTIFY_DONE;
++              return;
+       switch (msg) {
+@@ -303,7 +302,28 @@ static int raw_notifier(struct notifier_
+                       sk->sk_error_report(sk);
+               break;
+       }
++}
++
++static int raw_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(raw_busy_notifier)) /* Check for reentrant bug. */
++              return NOTIFY_DONE;
++      spin_lock(&raw_notifier_lock);
++      list_for_each_entry(raw_busy_notifier, &raw_notifier_list, notifier) {
++              spin_unlock(&raw_notifier_lock);
++              raw_notify(raw_busy_notifier, msg, dev);
++              spin_lock(&raw_notifier_lock);
++      }
++      raw_busy_notifier = NULL;
++      spin_unlock(&raw_notifier_lock);
+       return NOTIFY_DONE;
+ }
+@@ -332,9 +352,9 @@ static int raw_init(struct sock *sk)
+               return -ENOMEM;
+       /* set notifier */
+-      ro->notifier.notifier_call = raw_notifier;
+-
+-      register_netdevice_notifier(&ro->notifier);
++      spin_lock(&raw_notifier_lock);
++      list_add_tail(&ro->notifier, &raw_notifier_list);
++      spin_unlock(&raw_notifier_lock);
+       return 0;
+ }
+@@ -349,7 +369,14 @@ static int raw_release(struct socket *so
+       ro = raw_sk(sk);
+-      unregister_netdevice_notifier(&ro->notifier);
++      spin_lock(&raw_notifier_lock);
++      while (raw_busy_notifier == ro) {
++              spin_unlock(&raw_notifier_lock);
++              schedule_timeout_uninterruptible(1);
++              spin_lock(&raw_notifier_lock);
++      }
++      list_del(&ro->notifier);
++      spin_unlock(&raw_notifier_lock);
+       lock_sock(sk);
+@@ -857,6 +884,10 @@ static const struct can_proto raw_can_pr
+       .prot       = &raw_proto,
+ };
++static struct notifier_block canraw_notifier = {
++      .notifier_call = raw_notifier
++};
++
+ static __init int raw_module_init(void)
+ {
+       int err;
+@@ -866,6 +897,8 @@ static __init int raw_module_init(void)
+       err = can_proto_register(&raw_can_proto);
+       if (err < 0)
+               printk(KERN_ERR "can: registration of raw protocol failed\n");
++      else
++              register_netdevice_notifier(&canraw_notifier);
+       return err;
+ }
+@@ -873,6 +906,7 @@ static __init int raw_module_init(void)
+ static __exit void raw_module_exit(void)
+ {
+       can_proto_unregister(&raw_can_proto);
++      unregister_netdevice_notifier(&canraw_notifier);
+ }
+ module_init(raw_module_init);
index 7c81160606714c0f4ff357c6047dca8f85e8cdff..0ce26ae467e96d23524796d985485dcb00dd37a2 100644 (file)
@@ -42,3 +42,5 @@ pci-mark-some-nvidia-gpus-to-avoid-bus-reset.patch
 arcv2-save-abi-registers-across-signal-handling.patch
 dmaengine-pl330-fix-wrong-usage-of-spinlock-flags-in-dma_cyclc.patch
 net-fec_ptp-add-clock-rate-zero-check.patch
+can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch
+usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch
diff --git a/queue-4.9/usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch b/queue-4.9/usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch
new file mode 100644 (file)
index 0000000..ac93d5d
--- /dev/null
@@ -0,0 +1,86 @@
+From 4bf584a03eec674975ee9fe36c8583d9d470dab1 Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@kernel.org>
+Date: Tue, 8 Jun 2021 18:56:56 +0800
+Subject: usb: dwc3: core: fix kernel panic when do reboot
+
+From: Peter Chen <peter.chen@kernel.org>
+
+commit 4bf584a03eec674975ee9fe36c8583d9d470dab1 upstream.
+
+When do system reboot, it calls dwc3_shutdown and the whole debugfs
+for dwc3 has removed first, when the gadget tries to do deinit, and
+remove debugfs for its endpoints, it meets NULL pointer dereference
+issue when call debugfs_lookup. Fix it by removing the whole dwc3
+debugfs later than dwc3_drd_exit.
+
+[ 2924.958838] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000002
+....
+[ 2925.030994] pstate: 60000005 (nZCv daif -PAN -UAO -TCO BTYPE=--)
+[ 2925.037005] pc : inode_permission+0x2c/0x198
+[ 2925.041281] lr : lookup_one_len_common+0xb0/0xf8
+[ 2925.045903] sp : ffff80001276ba70
+[ 2925.049218] x29: ffff80001276ba70 x28: ffff0000c01f0000 x27: 0000000000000000
+[ 2925.056364] x26: ffff800011791e70 x25: 0000000000000008 x24: dead000000000100
+[ 2925.063510] x23: dead000000000122 x22: 0000000000000000 x21: 0000000000000001
+[ 2925.070652] x20: ffff8000122c6188 x19: 0000000000000000 x18: 0000000000000000
+[ 2925.077797] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000004
+[ 2925.084943] x14: ffffffffffffffff x13: 0000000000000000 x12: 0000000000000030
+[ 2925.092087] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f x9 : ffff8000102b2420
+[ 2925.099232] x8 : 7f7f7f7f7f7f7f7f x7 : feff73746e2f6f64 x6 : 0000000000008080
+[ 2925.106378] x5 : 61c8864680b583eb x4 : 209e6ec2d263dbb7 x3 : 000074756f307065
+[ 2925.113523] x2 : 0000000000000001 x1 : 0000000000000000 x0 : ffff8000122c6188
+[ 2925.120671] Call trace:
+[ 2925.123119]  inode_permission+0x2c/0x198
+[ 2925.127042]  lookup_one_len_common+0xb0/0xf8
+[ 2925.131315]  lookup_one_len_unlocked+0x34/0xb0
+[ 2925.135764]  lookup_positive_unlocked+0x14/0x50
+[ 2925.140296]  debugfs_lookup+0x68/0xa0
+[ 2925.143964]  dwc3_gadget_free_endpoints+0x84/0xb0
+[ 2925.148675]  dwc3_gadget_exit+0x28/0x78
+[ 2925.152518]  dwc3_drd_exit+0x100/0x1f8
+[ 2925.156267]  dwc3_remove+0x11c/0x120
+[ 2925.159851]  dwc3_shutdown+0x14/0x20
+[ 2925.163432]  platform_shutdown+0x28/0x38
+[ 2925.167360]  device_shutdown+0x15c/0x378
+[ 2925.171291]  kernel_restart_prepare+0x3c/0x48
+[ 2925.175650]  kernel_restart+0x1c/0x68
+[ 2925.179316]  __do_sys_reboot+0x218/0x240
+[ 2925.183247]  __arm64_sys_reboot+0x28/0x30
+[ 2925.187262]  invoke_syscall+0x48/0x100
+[ 2925.191017]  el0_svc_common.constprop.0+0x48/0xc8
+[ 2925.195726]  do_el0_svc+0x28/0x88
+[ 2925.199045]  el0_svc+0x20/0x30
+[ 2925.202104]  el0_sync_handler+0xa8/0xb0
+[ 2925.205942]  el0_sync+0x148/0x180
+[ 2925.209270] Code: a9025bf5 2a0203f5 121f0056 370802b5 (79400660)
+[ 2925.215372] ---[ end trace 124254d8e485a58b ]---
+[ 2925.220012] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
+[ 2925.227676] Kernel Offset: disabled
+[ 2925.231164] CPU features: 0x00001001,20000846
+[ 2925.235521] Memory Limit: none
+[ 2925.238580] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
+
+Fixes: 8d396bb0a5b6 ("usb: dwc3: debugfs: Add and remove endpoint dirs dynamically")
+Cc: Jack Pham <jackp@codeaurora.org>
+Tested-by: Jack Pham <jackp@codeaurora.org>
+Signed-off-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20210608105656.10795-1-peter.chen@kernel.org
+(cherry picked from commit 2a042767814bd0edf2619f06fecd374e266ea068)
+Link: https://lore.kernel.org/r/20210615080847.GA10432@jackp-linux.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1199,8 +1199,8 @@ static int dwc3_remove(struct platform_d
+        */
+       res->start -= DWC3_GLOBALS_REGS_START;
+-      dwc3_debugfs_exit(dwc);
+       dwc3_core_exit_mode(dwc);
++      dwc3_debugfs_exit(dwc);
+       dwc3_core_exit(dwc);
+       dwc3_ulpi_exit(dwc);