From: Greg Kroah-Hartman Date: Mon, 21 Jun 2021 15:34:17 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v5.4.128~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=61cf838fa9dc3281be426a557c47a25aca708d9f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch inet-use-bigger-hash-table-for-ip-id-generation.patch kvm-arm-arm64-fix-kvm_vgic_v3_addr_type_redist-read.patch usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch usb-dwc3-debugfs-add-and-remove-endpoint-dirs-dynamically.patch --- diff --git a/queue-4.19/can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch b/queue-4.19/can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch new file mode 100644 index 00000000000..ed2201865c6 --- /dev/null +++ b/queue-4.19/can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch @@ -0,0 +1,294 @@ +From 8d0caedb759683041d9db82069937525999ada53 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Sat, 5 Jun 2021 19:26:35 +0900 +Subject: can: bcm/raw/isotp: use per module netdevice notifier + +From: Tetsuo Handa + +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 +Reported-by: syzbot +Reported-by: syzbot +Reviewed-by: Kirill Tkhai +Tested-by: syzbot +Tested-by: Oliver Hartkopp +Signed-off-by: Tetsuo Handa +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -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; +@@ -1432,20 +1436,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), sock_net(sk))) +- return NOTIFY_DONE; +- +- if (dev->type != ARPHRD_CAN) +- return NOTIFY_DONE; ++ return; + + switch (msg) { + +@@ -1480,7 +1479,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; + } + +@@ -1500,9 +1520,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; + } +@@ -1525,7 +1545,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); + +@@ -1740,6 +1767,10 @@ static struct pernet_operations canbcm_p + .exit = canbcm_pernet_exit, + }; + ++static struct notifier_block canbcm_notifier = { ++ .notifier_call = bcm_notifier ++}; ++ + static int __init bcm_module_init(void) + { + int err; +@@ -1753,12 +1784,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); + } + +--- 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' +@@ -266,21 +270,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), sock_net(sk))) +- return NOTIFY_DONE; +- +- if (dev->type != ARPHRD_CAN) +- return NOTIFY_DONE; ++ return; + + if (ro->ifindex != dev->ifindex) +- return NOTIFY_DONE; ++ return; + + switch (msg) { + +@@ -309,7 +308,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; + } + +@@ -338,9 +358,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; + } +@@ -355,7 +375,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); + +@@ -870,6 +897,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; +@@ -879,6 +910,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; + } +@@ -886,6 +919,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); diff --git a/queue-4.19/inet-use-bigger-hash-table-for-ip-id-generation.patch b/queue-4.19/inet-use-bigger-hash-table-for-ip-id-generation.patch new file mode 100644 index 00000000000..f0d115f15d5 --- /dev/null +++ b/queue-4.19/inet-use-bigger-hash-table-for-ip-id-generation.patch @@ -0,0 +1,113 @@ +From aa6dd211e4b1dde9d5dc25d699d35f789ae7eeba Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 24 Mar 2021 14:53:37 -0700 +Subject: inet: use bigger hash table for IP ID generation + +From: Eric Dumazet + +commit aa6dd211e4b1dde9d5dc25d699d35f789ae7eeba upstream. + +In commit 73f156a6e8c1 ("inetpeer: get rid of ip_id_count") +I used a very small hash table that could be abused +by patient attackers to reveal sensitive information. + +Switch to a dynamic sizing, depending on RAM size. + +Typical big hosts will now use 128x more storage (2 MB) +to get a similar increase in security and reduction +of hash collisions. + +As a bonus, use of alloc_large_system_hash() spreads +allocated memory among all NUMA nodes. + +Fixes: 73f156a6e8c1 ("inetpeer: get rid of ip_id_count") +Reported-by: Amit Klein +Signed-off-by: Eric Dumazet +Cc: Willy Tarreau +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/ipv4/route.c | 46 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 30 insertions(+), 16 deletions(-) + +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -70,6 +70,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -470,8 +471,10 @@ static void ipv4_confirm_neigh(const str + __ipv4_confirm_neigh(dev, *(__force u32 *)pkey); + } + +-#define IP_IDENTS_SZ 2048u +- ++/* Hash tables of size 2048..262144 depending on RAM size. ++ * Each bucket uses 8 bytes. ++ */ ++static u32 ip_idents_mask __read_mostly; + static atomic_t *ip_idents __read_mostly; + static u32 *ip_tstamps __read_mostly; + +@@ -481,12 +484,16 @@ static u32 *ip_tstamps __read_mostly; + */ + u32 ip_idents_reserve(u32 hash, int segs) + { +- u32 *p_tstamp = ip_tstamps + hash % IP_IDENTS_SZ; +- atomic_t *p_id = ip_idents + hash % IP_IDENTS_SZ; +- u32 old = READ_ONCE(*p_tstamp); +- u32 now = (u32)jiffies; ++ u32 bucket, old, now = (u32)jiffies; ++ atomic_t *p_id; ++ u32 *p_tstamp; + u32 delta = 0; + ++ bucket = hash & ip_idents_mask; ++ p_tstamp = ip_tstamps + bucket; ++ p_id = ip_idents + bucket; ++ old = READ_ONCE(*p_tstamp); ++ + if (old != now && cmpxchg(p_tstamp, old, now) == old) + delta = prandom_u32_max(now - old); + +@@ -3197,18 +3204,25 @@ struct ip_rt_acct __percpu *ip_rt_acct _ + + int __init ip_rt_init(void) + { ++ void *idents_hash; + int cpu; + +- ip_idents = kmalloc_array(IP_IDENTS_SZ, sizeof(*ip_idents), +- GFP_KERNEL); +- if (!ip_idents) +- panic("IP: failed to allocate ip_idents\n"); +- +- prandom_bytes(ip_idents, IP_IDENTS_SZ * sizeof(*ip_idents)); +- +- ip_tstamps = kcalloc(IP_IDENTS_SZ, sizeof(*ip_tstamps), GFP_KERNEL); +- if (!ip_tstamps) +- panic("IP: failed to allocate ip_tstamps\n"); ++ /* For modern hosts, this will use 2 MB of memory */ ++ idents_hash = alloc_large_system_hash("IP idents", ++ sizeof(*ip_idents) + sizeof(*ip_tstamps), ++ 0, ++ 16, /* one bucket per 64 KB */ ++ HASH_ZERO, ++ NULL, ++ &ip_idents_mask, ++ 2048, ++ 256*1024); ++ ++ ip_idents = idents_hash; ++ ++ prandom_bytes(ip_idents, (ip_idents_mask + 1) * sizeof(*ip_idents)); ++ ++ ip_tstamps = idents_hash + (ip_idents_mask + 1) * sizeof(*ip_idents); + + for_each_possible_cpu(cpu) { + struct uncached_list *ul = &per_cpu(rt_uncached_list, cpu); diff --git a/queue-4.19/kvm-arm-arm64-fix-kvm_vgic_v3_addr_type_redist-read.patch b/queue-4.19/kvm-arm-arm64-fix-kvm_vgic_v3_addr_type_redist-read.patch new file mode 100644 index 00000000000..87c11c096d0 --- /dev/null +++ b/queue-4.19/kvm-arm-arm64-fix-kvm_vgic_v3_addr_type_redist-read.patch @@ -0,0 +1,43 @@ +From 94ac0835391efc1a30feda6fc908913ec012951e Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 12 Apr 2021 17:00:34 +0200 +Subject: KVM: arm/arm64: Fix KVM_VGIC_V3_ADDR_TYPE_REDIST read + +From: Eric Auger + +commit 94ac0835391efc1a30feda6fc908913ec012951e upstream. + +When reading the base address of the a REDIST region +through KVM_VGIC_V3_ADDR_TYPE_REDIST we expect the +redistributor region list to be populated with a single +element. + +However list_first_entry() expects the list to be non empty. +Instead we should use list_first_entry_or_null which effectively +returns NULL if the list is empty. + +Fixes: dbd9733ab674 ("KVM: arm/arm64: Replace the single rdist region by a list") +Cc: # v4.18+ +Signed-off-by: Eric Auger +Reported-by: Gavin Shan +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20210412150034.29185-1-eric.auger@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + virt/kvm/arm/vgic/vgic-kvm-device.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + + +--- a/virt/kvm/arm/vgic/vgic-kvm-device.c ++++ b/virt/kvm/arm/vgic/vgic-kvm-device.c +@@ -95,8 +95,8 @@ int kvm_vgic_addr(struct kvm *kvm, unsig + r = vgic_v3_set_redist_base(kvm, 0, *addr, 0); + goto out; + } +- rdreg = list_first_entry(&vgic->rd_regions, +- struct vgic_redist_region, list); ++ rdreg = list_first_entry_or_null(&vgic->rd_regions, ++ struct vgic_redist_region, list); + if (!rdreg) + addr_ptr = &undef_value; + else diff --git a/queue-4.19/series b/queue-4.19/series index be581f7d930..55620858a67 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -74,3 +74,8 @@ mm-slub-clarify-verification-reporting.patch mm-slub.c-include-swab.h.patch net-fec_ptp-add-clock-rate-zero-check.patch tools-headers-uapi-sync-linux-in.h-copy-with-the-kernel-sources.patch +kvm-arm-arm64-fix-kvm_vgic_v3_addr_type_redist-read.patch +can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch +inet-use-bigger-hash-table-for-ip-id-generation.patch +usb-dwc3-debugfs-add-and-remove-endpoint-dirs-dynamically.patch +usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch diff --git a/queue-4.19/usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch b/queue-4.19/usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch new file mode 100644 index 00000000000..cd20370a7d0 --- /dev/null +++ b/queue-4.19/usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch @@ -0,0 +1,86 @@ +From 4bf584a03eec674975ee9fe36c8583d9d470dab1 Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Tue, 8 Jun 2021 18:56:56 +0800 +Subject: usb: dwc3: core: fix kernel panic when do reboot + +From: Peter Chen + +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 +Tested-by: Jack Pham +Signed-off-by: Peter Chen +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 +--- + 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 +@@ -1550,8 +1550,8 @@ static int dwc3_remove(struct platform_d + + pm_runtime_get_sync(&pdev->dev); + +- dwc3_debugfs_exit(dwc); + dwc3_core_exit_mode(dwc); ++ dwc3_debugfs_exit(dwc); + + dwc3_core_exit(dwc); + dwc3_ulpi_exit(dwc); diff --git a/queue-4.19/usb-dwc3-debugfs-add-and-remove-endpoint-dirs-dynamically.patch b/queue-4.19/usb-dwc3-debugfs-add-and-remove-endpoint-dirs-dynamically.patch new file mode 100644 index 00000000000..7cab6b8a673 --- /dev/null +++ b/queue-4.19/usb-dwc3-debugfs-add-and-remove-endpoint-dirs-dynamically.patch @@ -0,0 +1,122 @@ +From 8d396bb0a5b62b326f6be7594d8bd46b088296bd Mon Sep 17 00:00:00 2001 +From: Jack Pham +Date: Sat, 29 May 2021 12:29:32 -0700 +Subject: usb: dwc3: debugfs: Add and remove endpoint dirs dynamically + +From: Jack Pham + +commit 8d396bb0a5b62b326f6be7594d8bd46b088296bd upstream. + +The DWC3 DebugFS directory and files are currently created once +during probe. This includes creation of subdirectories for each +of the gadget's endpoints. This works fine for peripheral-only +controllers, as dwc3_core_init_mode() calls dwc3_gadget_init() +just prior to calling dwc3_debugfs_init(). + +However, for dual-role controllers, dwc3_core_init_mode() will +instead call dwc3_drd_init() which is problematic in a few ways. +First, the initial state must be determined, then dwc3_set_mode() +will have to schedule drd_work and by then dwc3_debugfs_init() +could have already been invoked. Even if the initial mode is +peripheral, dwc3_gadget_init() happens after the DebugFS files +are created, and worse so if the initial state is host and the +controller switches to peripheral much later. And secondly, +even if the gadget endpoints' debug entries were successfully +created, if the controller exits peripheral mode, its dwc3_eps +are freed so the debug files would now hold stale references. + +So it is best if the DebugFS endpoint entries are created and +removed dynamically at the same time the underlying dwc3_eps are. +Do this by calling dwc3_debugfs_create_endpoint_dir() as each +endpoint is created, and conversely remove the DebugFS entry when +the endpoint is freed. + +Fixes: 41ce1456e1db ("usb: dwc3: core: make dwc3_set_mode() work properly") +Cc: stable +Reviewed-by: Peter Chen +Signed-off-by: Jack Pham +Link: https://lore.kernel.org/r/20210529192932.22912-1-jackp@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/debug.h | 3 +++ + drivers/usb/dwc3/debugfs.c | 21 ++------------------- + drivers/usb/dwc3/gadget.c | 3 +++ + 3 files changed, 8 insertions(+), 19 deletions(-) + +--- a/drivers/usb/dwc3/debug.h ++++ b/drivers/usb/dwc3/debug.h +@@ -653,9 +653,12 @@ static inline const char *dwc3_gadget_ge + + + #ifdef CONFIG_DEBUG_FS ++extern void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep); + extern void dwc3_debugfs_init(struct dwc3 *); + extern void dwc3_debugfs_exit(struct dwc3 *); + #else ++static inline void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep) ++{ } + static inline void dwc3_debugfs_init(struct dwc3 *d) + { } + static inline void dwc3_debugfs_exit(struct dwc3 *d) +--- a/drivers/usb/dwc3/debugfs.c ++++ b/drivers/usb/dwc3/debugfs.c +@@ -725,30 +725,14 @@ static void dwc3_debugfs_create_endpoint + } + } + +-static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep, +- struct dentry *parent) ++void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep) + { + struct dentry *dir; + +- dir = debugfs_create_dir(dep->name, parent); ++ dir = debugfs_create_dir(dep->name, dep->dwc->root); + dwc3_debugfs_create_endpoint_files(dep, dir); + } + +-static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc, +- struct dentry *parent) +-{ +- int i; +- +- for (i = 0; i < dwc->num_eps; i++) { +- struct dwc3_ep *dep = dwc->eps[i]; +- +- if (!dep) +- continue; +- +- dwc3_debugfs_create_endpoint_dir(dep, parent); +- } +-} +- + void dwc3_debugfs_init(struct dwc3 *dwc) + { + struct dentry *root; +@@ -777,7 +761,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc) + &dwc3_testmode_fops); + debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, dwc, + &dwc3_link_state_fops); +- dwc3_debugfs_create_endpoint_dirs(dwc, root); + } + } + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2255,6 +2255,8 @@ static int dwc3_gadget_init_endpoint(str + INIT_LIST_HEAD(&dep->started_list); + INIT_LIST_HEAD(&dep->cancelled_list); + ++ dwc3_debugfs_create_endpoint_dir(dep); ++ + return 0; + } + +@@ -2298,6 +2300,7 @@ static void dwc3_gadget_free_endpoints(s + list_del(&dep->endpoint.ep_list); + } + ++ debugfs_remove_recursive(debugfs_lookup(dep->name, dwc->root)); + kfree(dep); + } + }